4.4 KiB
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).
Tools
web_search
Provider abstraction — same pattern as providers. Default: DuckDuckGo. Admin adds SearXNG instances or other search APIs.
Model: searchResult[] — title, url, snippet.
{
\"tool_name\": \"web_search\",
\"parameters\": {
\"query\": \"string\" // required
}
}
Backend: Provider interface, DuckDuckGo fallback. Results deduped by URL. Max 10 results (configurable). Results cached in-memory 1h (channel-scoped).
url_fetch
Model: webPage — title, url, content (HTML or text).
{
\"tool_name\": \"url_fetch\",
\"parameters\": {
\"url\": \"string\" // required, validated
}
}
Backend: HTTP GET with timeout (10s), content-type sniffing, HTML→text conversion (go-readability). Max 100KB extracted text. Cached 1h.
Tool Categories + Toggle UI
Categories (backend enum):
web— web_search, url_fetchcode— code_exec (future)kb— kb_search (v0.14.0)memory— memory_recall (v0.18.0)
Per-chat persistence: channel.settings.tools[] array of enabled categories.
Default: all.
Chat bar UI: Toggle icon → dropdown with checkboxes per category.
Syncs to API on change (PATCH /channels/:id {tools: [...]}).
Admin global default: global_settings.default_tools[].
Backend Changes
1. server/tools/search.go — New file
// web_search + url_fetch providers + caching
2. server/tools/registry.go — Category enum + filtering
type ToolCategory string
const (
CategoryWeb ToolCategory = \"web\"
CategoryCode ToolCategory = \"code\"
// ...
)
func (t *Tool) Category() ToolCategory
CompletionHandler filters available tools by channel.settings.tools.
3. server/handlers/channels.go — PATCH tools[]
case \"tools\":
if tools, ok := data.([]string); ok {
ch.Tools = tools
}
4. server/config/config.go — Global defaults
DefaultTools []string `json:\"default_tools\"`
5. VERSION
0.13.1
Frontend Changes
src/js/chat-ui.js — Tool toggle button
After model selector (~line 450):
// Tool toggle dropdown
const toolToggle = document.createElement('div');
toolToggle.className = 'tool-toggle';
toolToggle.innerHTML = `
<button class=\"tool-btn\" onclick=\"ChatUI.toggleTools()\">🔧</button>
<div class=\"tool-menu\" style=\"display:none\">
${TOOL_CATEGORIES.map(cat =>
`<label><input type=\"checkbox\" data-cat=\"${cat}\" checked> ${cat}</label>`
).join('')}
</div>
`;
chatBar.appendChild(toolToggle);
Event handler
ChatUI.toggleTools = function() {
const menu = document.querySelector('.tool-menu');
menu.style.display = menu.style.display === 'none' ? 'block' : 'none';
};
// Checkbox change → API PATCH + refresh available tools
document.querySelectorAll('[data-cat]').forEach(cb => {
cb.addEventListener('change', async function() {
const tools = Array.from(document.querySelectorAll('[data-cat]:checked'))
.map(cb => cb.dataset.cat);
await API.updateChannel(channelId, { tools });
ChatUI.refreshTools(); // filter tool_calls display
});
});
Testing Checklist
- Tools register — logs show
🔧 Registered tool: web_search - web_search works — DuckDuckGo fallback, results in tool_calls
- Admin search provider — add SearXNG, verify switch
- url_fetch — valid URL → content extracted
- Toggle UI — checkbox → tools filtered from completion
- Persistence — reload chat → toggles restored
- Admin default — new chat inherits global default_tools
Architecture Notes
- No tool auth — web_search/url_fetch are anon-safe
- Caching — channel-scoped LRU (100 entries), 1h TTL
- Rate limiting — 5/min per channel (global_settings.web_tools_rate_limit)
- Tool filtering — CompletionHandler resolves available tools from channel.tools + global default_tools intersection with registered tools' categories
- Provider symmetry — search providers mirror LLM providers (health, priority)