feat(tools): add web_search with SearXNG and /search command#50
Merged
Conversation
Summary: Add a new read-only `web_search` tool to the Ollama tool registry, backed by SearXNG when configured and DuckDuckGo as an automatic fallback. Store the SearXNG base URL in the existing user config file and add a `/search` TUI command so users can set or clear that URL without editing JSON manually. Key Changes: - Add a new tool name `web_search` to the existing tool constant/type surface. - Extend the Ollama tool schema with `web_search(query)` and describe it as a read-only web search tool for external/current information. - Implement `web_search` in `src/utils/tools.ts`: - load `searxngBaseUrl` from the existing config layer - if configured, query the SearXNG JSON search endpoint first - if unconfigured, unreachable, invalid, or returns unusable results, fall back to DuckDuckGo HTML search - format results into the existing `ToolResult.content` string contract with compact title, URL, and snippet entries - return a useful error only when both providers fail - Add `web_search` to `READ_TOOLS` and keep it out of `WRITE_TOOLS`. - Update tool instruction text so the model knows `web_search` exists and should use it for web/current-information lookups. - Leave plan checklist generation unchanged so executable plans still only emit `write_file`, `edit_file`, and `run_shell`. Config and Command Changes: - Extend the persisted config shape in `src/utils/config.ts` with: - `searxngBaseUrl?: string` - Keep the default as unset/undefined rather than assuming a localhost URL. - Preserve current config behavior for malformed or partial JSON files. - Add a new slash command: - `/search` - `/search` should open a small interactive flow in the TUI that shows: - the current configured SearXNG URL, or `not set` - that DuckDuckGo fallback remains available - actions: set URL, clear URL, cancel - "Set URL" should accept and save a string URL through `saveConfig()`. - "Clear URL" should remove or unset `searxngBaseUrl`, causing future searches to use DuckDuckGo fallback directly. - Update command menu/help surfaces so `/search` is discoverable anywhere `/model` is currently surfaced. Public Interface Changes: - New tool: - `web_search(query: string)` - Extended config file schema: - `host: string` - `model: string` - `searxngBaseUrl?: string` - New slash command: - `/search` Test Plan: - Add tool registry tests to confirm `web_search` is exported, is included in `READ_TOOLS`, and is excluded from `WRITE_TOOLS`. - Add `executeTool` tests for: - successful SearXNG response parsing - missing `searxngBaseUrl` using DuckDuckGo directly - configured SearXNG failure falling back to DuckDuckGo - no results returned - total failure when both backends fail - Extend config tests to cover: - reading `searxngBaseUrl` from config - saving `searxngBaseUrl` - missing `searxngBaseUrl` remaining undefined - Add TUI tests for `/search`: - command menu includes `/search` - issuing `/search` opens the search settings flow - setting a URL persists config and returns to chat - clearing the URL persists the cleared state and returns to chat - cancel leaves config unchanged - Update prompt/help assertions where they enumerate available tools or commands. Assumptions: - `web_search` is intended for plan-mode research as well as normal chat execution. - Output stays plain text via `ToolResult.content`; no structured search result type is introduced. - SearXNG configuration is user-level and persistent, so config storage is preferred over env-only configuration. - No default localhost SearXNG URL is assumed; unset means `DuckDuckGo fallback only`. - URL validation should be lightweight and pragmatic: reject obviously invalid URLs when saving if feasible, but do not over-design a full settings validation layer for this change.
```
src/utils/tools/
├── index.ts # Barrel exports (TOOLS, READ_TOOLS, WRITE_TOOLS, executeTool)
├── definitions.ts # Tool definitions and permission sets
├── dispatcher.ts # executeTool() switch statement
├── filesystem.ts # readFile, writeFile, editFile, viewRange, listDir, grepSearch
├── shell.ts # runShell, execShell
└── web/
├── index.ts # webSearch export
├── search.ts # webSearch, searchSearxng, searchDuckDuckGo
├── fetch.ts # fetchText
└── utils.ts # Text utilities (stripTags, decodeHtml, cleanText, truncate)
```
```
src/utils/tools/
├── definitions.test.ts # 3 tests - TOOLS, READ_TOOLS, WRITE_TOOLS
├── dispatcher.test.ts # 5 tests - executeTool integration
├── filesystem.test.ts # 31 tests - file/directory operations
├── shell.test.ts # 5 tests - shell execution
└── web/
└── search.test.ts # 21 tests - web search functionality
```
`stubGlobal` permanently replaces the value on `globalThis` for the remainder of the test environment unless you undo it. That can leak state between tests and create flaky behavior.
web_search with SearXNG and /search command
Codecov Report✅ All modified and coverable lines are covered by tests.
🚀 New features to boost your workflow:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What is the motivation for this pull request?
This is a feature that adds web search capability to the Ollama CLI agent, allowing users to search the web and get results that can be used in conversations with the AI.
What is the current behavior?
No web search functionality exists.
What is the new behavior?
web_searchtool with SearXNG as primary provider and DuckDuckGo as fallback/searchcommand to configure web search settingsChecklist: