232 lines
8.0 KiB
Markdown
232 lines
8.0 KiB
Markdown
# DESIGN-0.13.1 — Web Search + URL Fetch + Tool Toggle
|
||
|
||
## Overview
|
||
|
||
Built-in `web_search` and `url_fetch` tools using the existing tool framework (v0.11.0),
|
||
plus a chat-bar tools toggle menu so users can enable/disable tool categories per-session.
|
||
|
||
Depends on: tool framework (v0.11.0), admin panel (v0.13.0).
|
||
|
||
---
|
||
|
||
## 1. Tool Categories
|
||
|
||
Add a `Category` field to `ToolDef` so tools self-declare their group.
|
||
The frontend uses categories for the toggle menu; the backend ignores them.
|
||
|
||
| Category | Tools | Default |
|
||
|-----------|---------------------------------------------|---------|
|
||
| search | `web_search`, `url_fetch` | ON |
|
||
| notes | `note_create`, `note_search`, `note_update`, `note_list` | ON |
|
||
| utilities | `datetime`, `calculator` | ON |
|
||
| browser | (extension-defined: `js_eval`, `regex_test`)| ON |
|
||
|
||
```go
|
||
type ToolDef struct {
|
||
Name string `json:"name"`
|
||
DisplayName string `json:"display_name,omitempty"` // human-readable label for UI
|
||
Description string `json:"description"`
|
||
Parameters json.RawMessage `json:"parameters"`
|
||
Category string `json:"category,omitempty"` // NEW
|
||
}
|
||
```
|
||
|
||
## 2. Per-Request Tool Filtering
|
||
|
||
### Request field
|
||
```json
|
||
{ "disabled_tools": ["web_search", "url_fetch"] }
|
||
```
|
||
|
||
### Backend filter
|
||
`buildToolDefs()` skips tools whose name appears in `disabled_tools`.
|
||
Zero API changes — the field is optional, empty = all tools enabled.
|
||
|
||
### Frontend state
|
||
`localStorage` key: `cs-disabled-tools` → JSON array of tool names.
|
||
The tools toggle menu flips categories on/off which maps to individual tool names.
|
||
|
||
## 3. web_search Tool
|
||
|
||
### Search Provider Interface
|
||
```go
|
||
type SearchProvider interface {
|
||
Search(ctx context.Context, query string, maxResults int) ([]SearchResult, error)
|
||
Name() string
|
||
}
|
||
|
||
type SearchResult struct {
|
||
Title string `json:"title"`
|
||
URL string `json:"url"`
|
||
Snippet string `json:"snippet"`
|
||
}
|
||
```
|
||
|
||
### DuckDuckGo Provider (default — no API key)
|
||
Uses the DuckDuckGo HTML search endpoint. No rate-limit key required.
|
||
Falls back gracefully if blocked (returns error result to LLM, doesn't crash).
|
||
|
||
### SearXNG Provider (self-hosted)
|
||
Configurable endpoint + optional API key. JSON API (`/search?format=json`).
|
||
Good fit for airgapped deployments.
|
||
|
||
### Admin Config
|
||
Stored in `global_config` table (existing):
|
||
- `search_provider`: `"duckduckgo"` | `"searxng"` (default: `"duckduckgo"`)
|
||
- `search_endpoint`: SearXNG URL (only used when provider=searxng)
|
||
- `search_max_results`: `5` (default)
|
||
|
||
Admin UI: System → Settings section (new "Search" subsection).
|
||
|
||
### Tool Schema
|
||
```json
|
||
{
|
||
"name": "web_search",
|
||
"description": "Search the web for current information. Returns titles, URLs, and snippets.",
|
||
"category": "search",
|
||
"parameters": {
|
||
"type": "object",
|
||
"properties": {
|
||
"query": { "type": "string", "description": "Search query" },
|
||
"max_results": { "type": "integer", "description": "Max results (1-10, default 5)" }
|
||
},
|
||
"required": ["query"]
|
||
}
|
||
}
|
||
```
|
||
|
||
## 4. url_fetch Tool
|
||
|
||
HTTP GET with content extraction. Reuses the text extraction pattern
|
||
from file handling (v0.12.0) where possible.
|
||
|
||
### Behavior
|
||
1. HTTP GET with reasonable timeout (15s) and User-Agent
|
||
2. Follow redirects (max 3)
|
||
3. Extract readable text content (strip HTML tags, scripts, styles)
|
||
4. Truncate to ~8000 chars to avoid flooding the context
|
||
5. Return title + extracted text + metadata
|
||
|
||
### Safety
|
||
- Respect robots.txt? No — the LLM is fetching on behalf of the user, not crawling.
|
||
- Block private/internal IPs (10.x, 192.168.x, 127.x, ::1) to prevent SSRF.
|
||
- Configurable domain allowlist/blocklist in admin settings (future).
|
||
|
||
### Tool Schema
|
||
```json
|
||
{
|
||
"name": "url_fetch",
|
||
"description": "Fetch and extract readable text content from a URL.",
|
||
"category": "search",
|
||
"parameters": {
|
||
"type": "object",
|
||
"properties": {
|
||
"url": { "type": "string", "description": "URL to fetch" },
|
||
"max_length": { "type": "integer", "description": "Max content length in chars (default 8000)" }
|
||
},
|
||
"required": ["url"]
|
||
}
|
||
}
|
||
```
|
||
|
||
## 5. Frontend: Tools Toggle Menu
|
||
|
||
### UI Position
|
||
Chat input bar, left side, next to the attach button. Wrench/tool icon.
|
||
|
||
```
|
||
┌──────────────────────────────────────┐
|
||
│ 📎 🔧 [message input...] [Send]│
|
||
└──────────────────────────────────────┘
|
||
▲
|
||
┌────────────────┐
|
||
│ ☑ Web Search │
|
||
│ ☑ Notes │
|
||
│ ☑ Utilities │
|
||
│ ☑ Extensions │
|
||
└────────────────┘
|
||
```
|
||
|
||
### Behavior
|
||
- Click tool icon → popup above (using existing popup-menu pattern)
|
||
- Each category row has a toggle checkbox + expand chevron
|
||
- **Category toggle**: master on/off for all tools in the category
|
||
- **Expand chevron**: shows individual tool rows indented below
|
||
- **Tri-state checkbox**: if some tools in a category are disabled, category shows indeterminate (─)
|
||
- Toggling a category adds/removes all its tool names from `cs-disabled-tools`
|
||
- Toggling an individual tool adds/removes just that name
|
||
- State persists across page reloads via localStorage
|
||
- Disabled tools sent as `disabled_tools` array in completion request
|
||
- Tool icon shows visual indicator when any category is disabled
|
||
- If model doesn't support tool_calling, icon is hidden/grayed
|
||
|
||
```
|
||
┌────────────────────────┐
|
||
│ ☑ 🔍 Web Search › │ ← click › to expand
|
||
│ ☑ Search │
|
||
│ ☑ Fetch URL │
|
||
│ ☑ 📝 Notes › │
|
||
│ ☐ 🧮 Utilities › │ ← category off = all children off
|
||
│ ☑ 🧩 Extensions › │
|
||
└────────────────────────┘
|
||
```
|
||
|
||
### Tool Manifest
|
||
Frontend needs to know the category mapping and display names.
|
||
|
||
**API endpoint** — `GET /api/v1/tools` returns `[{name, display_name, category, description}]`
|
||
The frontend caches this on login. `display_name` provides human-readable labels
|
||
(e.g. "Search" instead of "web_search", "Create" instead of "note_create").
|
||
|
||
### New API Endpoint
|
||
```
|
||
GET /api/v1/tools → [{name, description, category}]
|
||
```
|
||
Returns server-side tools + browser extension tool schemas.
|
||
Used by frontend to build the toggle menu dynamically.
|
||
|
||
## 6. File Structure
|
||
|
||
### New backend files
|
||
- `server/tools/websearch.go` — web_search tool + search provider interface
|
||
- `server/tools/urlfetch.go` — url_fetch tool
|
||
- `server/tools/search/duckduckgo.go` — DuckDuckGo provider
|
||
- `server/tools/search/searxng.go` — SearXNG provider
|
||
- `server/tools/search/provider.go` — interface + registry
|
||
|
||
### Modified backend files
|
||
- `server/tools/types.go` — add Category to ToolDef
|
||
- `server/tools/registry.go` — add AllDefinitionsFiltered(disabled)
|
||
- `server/handlers/completion.go` — accept disabled_tools, filter in buildToolDefs
|
||
- `server/handlers/messages.go` — same filtering
|
||
- `server/handlers/routes.go` — add GET /api/v1/tools endpoint
|
||
- `server/tools/datetime.go` — add Category: "utilities"
|
||
- `server/tools/calculator.go` — add Category: "utilities"
|
||
- `server/tools/notes.go` — add Category: "notes"
|
||
|
||
### New/modified frontend files
|
||
- `src/index.html` — tools toggle button in input-wrap
|
||
- `src/css/styles.css` — tools popup styling
|
||
- `src/js/chat.js` — send disabled_tools in completion, wire toggle
|
||
- `src/js/api.js` — add disabled_tools param, add getTools() method
|
||
|
||
## 7. Phased Delivery
|
||
|
||
**Phase 1: Backend tools + filtering**
|
||
- ToolDef.Category, disabled_tools filtering
|
||
- web_search + url_fetch tools
|
||
- DuckDuckGo provider
|
||
- GET /api/v1/tools endpoint
|
||
- Tests
|
||
|
||
**Phase 2: Frontend toggle**
|
||
- Tools toggle popup menu
|
||
- localStorage persistence
|
||
- Completion request wiring
|
||
- CSS
|
||
|
||
**Phase 3: Admin config + SearXNG**
|
||
- Search provider settings in admin panel
|
||
- SearXNG provider implementation
|
||
- Domain filtering
|