This repository has been archived on 2026-04-03. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
core/DESIGN-0.13.1.md
2026-02-25 23:56:27 +00:00

232 lines
8.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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