dsh-web-search-ddg
aooyoo
Zero-token DuckDuckGo search provider for the DeepSeek Harness (DSH) web seam — local headless browser, no API key, no m…
PROJECT TOPICS
PROJECT README
English | 中文
An automatically mounted, presentation-only progressive tool disclosure layer for every DeepSeek Harness Agent preset in Native, Code, and Both modes. It keeps the model-visible tool prefix stable while the live ToolRuntime catalog may register, unregister, restrict, or shadow non-eager tools.
Follow INSTALL.md and install this standalone bundle into a dsh profile. Its bundle patch mounts the plugin once on the host plane, whose scoped ToolRuntime and SystemPrompt views carry it into every existing and future Agent preset. No preset copy, preset edit, or preset selection is required. The plugin requires tools, systemPrompt, and llm; codeRuntime is required only when an agent actually presents Code Mode. It never patches the Harness checkout.
- id: progressive-tools
config:
eagerTools: []
maxSearchResults: 10
maxDescribeTools: 5
maxSummaryChars: 240
maxQueryChars: 500
maxToolNameChars: 200
maxResultBytes: 1048576
The configuration block above is an optional override in the profile's cordis.patch.yml; the bundle already owns the progressive-tools row. eagerTools contains exact, genuinely stable tools that remain declared directly. Unknown eager names fail assembly. Every count, grapheme, and rendered UTF-8 result limit is enforced before a successful discovery result returns.
| Effective mode | Stable model-visible tools | Invocation after describe |
|---|---|---|
| Native, native deferred API | search_tools, describe_tools, eager tools |
ordinary tool call with the returned exact name and arguments |
| Native, other API | search_tools, describe_tools, invoke_tool, eager tools |
invoke_tool({ name, arguments }) |
| Code | run_code; its SDK declares discovery and eager bindings |
tools[exactName](arguments) inside a later run_code |
| Both | run_code, discovery tools, eager tools |
ordinary tool call or Code binding |
invoke_tool is a capability fallback, not a second Code transport. The plugin removes it at the pi-ai request boundary when the resolved model supports OpenAI Responses client tool search or Anthropic tool references. Code and Both already have run_code, so they never expose invoke_tool.
search_tools({}) or search_tools({ query: "*" }) directly in Native/Both, or as a Code binding in Code mode, to list the complete lightweight catalog. Each entry contains only the exact name and a bounded description, matching Harness Skills' summary-first shape. A text query is an optional ranking filter: terms are matched independently instead of all being required, and a zero-match query falls back to the complete catalog. An explicit limit still narrows a response when desired.describe_tools({ names }) for the candidates you intend to use. It returns their canonical input/output schemas and full descriptions; Code/Both also receives the active-runtime SDK excerpt.describe_tools results from durable request history and injects their schemas at the matching tool-result position. A Native API without that capability calls the stable invoke_tool({ name, arguments }) fallback. Code calls tools[exactName](arguments) from a later run_code.Search and describe use ctx.tools.schemas(exec.agent) and ctx.tools.get(name, exec.agent) on every call. Search returns only name and description entries plus compact count metadata; describe returns exact schemas only for selected names. Neither result exposes internal catalog or presentation metadata.
The protocol keeps no mutable reveal set: search does not unlock a capability, and the complete runtime catalog remains the execution authority. Native disclosure is reconstructed from logged describe_tools call/result pairs on every request.
Harness request objects stay frozen and read-only. The plugin uses the public llm/stream waterfall to carry one request's durable disclosures, then reversibly wraps the resolved pi-ai Models.streamSimple instance. For capable models it adds pi-ai addedToolNames to the matching result and supplies the disclosed schemas; pi-ai serializes OpenAI tool_search_call/tool_search_output or Anthropic tool_reference blocks at that transcript position. Unsupported or unrecognized adapters are left untouched and retain invoke_tool.
## Progressive tool disclosure
Start with search_tools({}) or search_tools({ query: "*" }) when you need the complete lightweight catalog of all available names and summaries. A text query is only an optional ranking filter and falls back to that catalog when nothing matches.
Call describe_tools with only the exact names you intend to use.
describe_tools returns the exact input and output schemas; in Code Mode it also returns the active-runtime SDK excerpt.
On a later model step, issue an ordinary tool call with the returned exact name and arguments.
If the interface declares invoke_tool instead, pass it that exact name and arguments.
An unavailable call fails with the current ToolRuntime reason.
The wire remains run_code; its compact SDK contains only search_tools, describe_tools, and eager bindings. Search lists or optionally ranks the lightweight catalog, describe returns exact target schemas and an SDK excerpt, and a later program calls tools[exactName](arguments).
The stable prefix scales with discovery declarations, the fixed fallback, and eagerTools, not the complete visible catalog. Native APIs append disclosed schemas at the historical describe result rather than replacing the top-level tool array, so the cached prefix remains stable. Registering or unregistering a non-eager tool changes only later discovery results. This directly addresses dynamic-tool prefix invalidation such as deepseek-harness discussion #935.
invoke_tool fallback; Both continues to have run_code.compat.supportsToolSearch; Anthropic uses supportsToolReferences or pi-ai's first-party model rule. A gateway that over-claims either capability may reject the injected protocol.Apache License 2.0. See LICENSE.
CLASSIFICATION EVIDENCE
系统优先读取 GitHub Topics,再与站内分类词典和词根规则比对。