Skip to content

feat(tools): add web_search with SearXNG and /search command#50

Merged
remarkablemark merged 7 commits into
masterfrom
feat/web_search
May 10, 2026
Merged

feat(tools): add web_search with SearXNG and /search command#50
remarkablemark merged 7 commits into
masterfrom
feat/web_search

Conversation

@remarkablemark
Copy link
Copy Markdown
Member

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?

  • Adds web_search tool with SearXNG as primary provider and DuckDuckGo as fallback
  • Adds /search command to configure web search settings
  • Modularizes tool utilities into separate files (dispatcher, filesystem, shell, web)
  • Adds comprehensive tests for all tool modules
  • Changes SearchSettings placeholder to http://localhost:8080 for local SearXNG instances

Checklist:

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.
@remarkablemark remarkablemark self-assigned this May 10, 2026
@remarkablemark remarkablemark added the enhancement New feature or request label May 10, 2026
@remarkablemark remarkablemark changed the title feat(tools): add web_search with SearXNG and /search command feat(tools): add web_search with SearXNG and /search command May 10, 2026
@codecov
Copy link
Copy Markdown

codecov Bot commented May 10, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

Files with missing lines Coverage Δ
src/components/App.tsx 100.00% <100.00%> (ø)
src/components/SearchSettings.tsx 100.00% <100.00%> (ø)
src/constants/command.ts 100.00% <ø> (ø)
src/constants/package.ts 100.00% <100.00%> (ø)
src/constants/prompt.ts 100.00% <100.00%> (ø)
src/constants/tool.ts 100.00% <100.00%> (ø)
src/utils/config.ts 100.00% <100.00%> (ø)
src/utils/tools/definitions.ts 100.00% <100.00%> (ø)
src/utils/tools/dispatcher.ts 100.00% <100.00%> (ø)
src/utils/tools/filesystem.ts 100.00% <100.00%> (ø)
... and 4 more
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Comment thread src/utils/tools/filesystem.ts Dismissed
Comment thread src/utils/tools/filesystem.ts Fixed
Comment thread src/utils/tools/web/utils.ts Fixed
@remarkablemark remarkablemark added the bug Something isn't working label May 10, 2026
@remarkablemark remarkablemark merged commit df94bba into master May 10, 2026
15 checks passed
@remarkablemark remarkablemark deleted the feat/web_search branch May 10, 2026 20:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants