fix(web): narrow default search review scope
This commit is contained in:
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write packages/web/tool-web/README.md
|
||||
README.md: 7bee0d2d30fbbcf582fd7b60eb5d9130b6bdf888
|
||||
README.zh.md: 3d708839c9ffbdd89df08678fd6997fc6c45ee07
|
||||
README.md: 12f5c806db66b2109888c1ec642d117f3432d0df
|
||||
README.zh.md: cfbf47219f160af706912ca53f85cff535c381ec
|
||||
|
||||
@@ -4,7 +4,7 @@ English | [中文](README.zh.md)
|
||||
|
||||
The model-facing web tool suite — `web_search` and `web_fetch` — over the [web capability seam](../web/README.md) (`ctx.web`). It owns model-facing concerns only: tool names, JSON schemas, snake_case argument names, prompt sections, the result-count bound, result formatting, HTML→markdown presentation, and the UI presentation projection — `presentCall`, `presentResult` (a `card: 'web'` result card discriminated by `kind: 'search' | 'fetch'`), and the `output.presentationMeta` that carries the structured search sources or the fetch summary the lossy render text cannot (see the [web-result-card Agent Note](../../../.agents/notes/implemented/feature/2026-07-30-web-result-card.md)). All web access goes through `ctx.web`; this package never imports a concrete provider. Neither tool exposes a model-facing timeout — each tool's cooperative tool-call budget is declared here via config (`fetchTimeoutMs`/`searchTimeoutMs`, attached as `ToolDefinition.timeoutMs`) and enforced by [`@deepseek-ai/dsh-timeout-policy`](../../timeout/timeout-policy/README.md) (a `tools/execute` wrapper); each tool just forwards `exec.signal` to the seam.
|
||||
|
||||
Each tool is registered independently; a product that wants only one disables the other via config (`{ search: false }` / `{ fetch: false }`).
|
||||
Each tool is registered independently; a product that wants only one disables the other via config (`{ search: false }` / `{ fetch: false }`). Search guidance mentions `web_fetch` only when fetch is also config-enabled; a search-only composition instead tells the model to use returned snippets and cite their URLs.
|
||||
|
||||
## Tools
|
||||
|
||||
@@ -47,14 +47,20 @@ The tool never calls a provider's `available()` and never enumerates providers
|
||||
|
||||
#### What the model sees
|
||||
|
||||
Search and fetch contribute the web-search and web-fetch guidance below. A scoped tool restriction does not remove these independently registered sections.
|
||||
Search and fetch contribute the web-search and web-fetch guidance below. Search chooses its fetch-enabled or search-only text from config at registration time. A scoped tool restriction does not remove these independently registered sections.
|
||||
|
||||
##### Web search guidance
|
||||
##### Web search guidance with fetch enabled
|
||||
|
||||
```markdown
|
||||
Use the web_search tool to discover current information on the web. It returns an optional answer plus a list of source URLs. Follow up with web_fetch when you need the full content of a specific result, and cite the relevant URLs as markdown links.
|
||||
```
|
||||
|
||||
##### Web search-only guidance
|
||||
|
||||
```markdown
|
||||
Use the web_search tool to discover current information on the web. It returns an optional answer plus a list of source URLs. Use the returned source snippets when available, and cite the relevant URLs as markdown links.
|
||||
```
|
||||
|
||||
##### Web fetch guidance
|
||||
|
||||
```markdown
|
||||
@@ -63,11 +69,11 @@ Use the web_fetch tool to retrieve the content of a specific HTTP(S) URL (for ex
|
||||
|
||||
#### Token effect
|
||||
|
||||
Fixed guidance cost per request for each config-enabled tool, even when a restriction hides its schema.
|
||||
Fixed guidance cost per request for each config-enabled tool, even when a restriction hides its schema. Toggling fetch changes the search guidance as well as registering or removing the fetch section.
|
||||
|
||||
#### KV Cache effect
|
||||
|
||||
Prefix-stable while enabled tools, scope, and guidance text are unchanged. Config enablement or plugin lifecycle may invalidate reuse from the first changed prompt section; scoped schema restrictions do not remove it.
|
||||
Prefix-stable while enabled tools, scope, and guidance text are unchanged. Config enablement—including toggling fetch's search-guidance branch—or plugin lifecycle may invalidate reuse from the first changed prompt section; scoped schema restrictions do not remove it.
|
||||
|
||||
### Tool schemas
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
面向模型的 web 工具套件 `web_search` 与 `web_fetch`,构建于 [web 能力 seam](../web/README.md)(`ctx.web`)之上。它只负责面向模型的事项:工具名称、JSON Schema、snake_case 参数名称、提示词区段、结果数量上限、结果格式、HTML→markdown 呈现,以及 UI 呈现投影——`presentCall`、`presentResult`(以 `kind: 'search' | 'fetch'` 区分的 `card: 'web'` 结果卡片),以及承载有损渲染文本无法携带的结构化搜索来源或抓取摘要的 `output.presentationMeta`(见 [web-result-card Agent Note](../../../.agents/notes/implemented/feature/2026-07-30-web-result-card.md))。所有 web 访问都通过 `ctx.web`;该包(package)绝不导入具体提供方。两个工具都不公开面向模型的超时:每个工具的协作式工具调用超时预算通过配置在此声明(`fetchTimeoutMs`/`searchTimeoutMs`,附加为 `ToolDefinition.timeoutMs`),由 [`@deepseek-ai/dsh-timeout-policy`](../../timeout/timeout-policy/README.md)(`tools/execute` 包装层)强制执行;每个工具只把 `exec.signal` 转发给 seam。
|
||||
|
||||
每个工具独立注册;只需要其中一个工具的产品可以通过配置禁用另一个(`{ search: false }`/`{ fetch: false }`)。
|
||||
每个工具独立注册;只需要其中一个工具的产品可以通过配置禁用另一个(`{ search: false }`/`{ fetch: false }`)。仅当抓取也通过配置启用时,搜索指引才会提及 `web_fetch`;仅启用搜索的组合则会要求模型使用返回的 snippet 并引用其 URL。
|
||||
|
||||
## 工具
|
||||
|
||||
@@ -47,14 +47,20 @@
|
||||
|
||||
#### 模型看到的内容
|
||||
|
||||
搜索与抓取分别贡献以下 web-search 和 web-fetch 指引。scope 工具限制不会移除这些独立注册的区段。
|
||||
搜索与抓取分别贡献以下 web-search 和 web-fetch 指引。搜索会在注册时根据配置选用启用抓取或仅搜索的文本。scope 工具限制不会移除这些独立注册的区段。
|
||||
|
||||
##### Web 搜索指引
|
||||
##### 启用抓取时的 Web 搜索指引
|
||||
|
||||
```markdown
|
||||
Use the web_search tool to discover current information on the web. It returns an optional answer plus a list of source URLs. Follow up with web_fetch when you need the full content of a specific result, and cite the relevant URLs as markdown links.
|
||||
```
|
||||
|
||||
##### 仅搜索时的 Web 搜索指引
|
||||
|
||||
```markdown
|
||||
Use the web_search tool to discover current information on the web. It returns an optional answer plus a list of source URLs. Use the returned source snippets when available, and cite the relevant URLs as markdown links.
|
||||
```
|
||||
|
||||
##### Web 抓取指引
|
||||
|
||||
```markdown
|
||||
@@ -63,11 +69,11 @@ Use the web_fetch tool to retrieve the content of a specific HTTP(S) URL (for ex
|
||||
|
||||
#### Token 影响
|
||||
|
||||
每个通过配置启用的工具都会为每次请求增加固定的指引 token 开销,即使限制隐藏了其 schema。
|
||||
每个通过配置启用的工具都会为每次请求增加固定的指引 token 开销,即使限制隐藏了其 schema。切换抓取状态不仅会注册或移除抓取区段,也会更改搜索指引。
|
||||
|
||||
#### KV Cache 影响
|
||||
|
||||
只要启用工具、scope 与指引文本不变,前缀就保持稳定。配置启用状态或插件生命周期可能使从第一个变化的提示词区段起的复用失效;scope schema 限制不会移除该区段。
|
||||
只要启用工具、scope 与指引文本不变,前缀就保持稳定。配置启用状态(包括因切换抓取状态而改变搜索指引分支)或插件生命周期可能使从第一个变化的提示词区段起的复用失效;scope schema 限制不会移除该区段。
|
||||
|
||||
### 工具 schema
|
||||
|
||||
|
||||
@@ -84,6 +84,8 @@ export function apply(ctx: Context, config: Config): void {
|
||||
assertPositiveInteger('fetchTimeoutMs', resolved.fetchTimeoutMs)
|
||||
assertPositiveInteger('searchTimeoutMs', resolved.searchTimeoutMs)
|
||||
assertPositiveInteger('fetchMaxOutputChars', resolved.fetchMaxOutputChars)
|
||||
if (resolved.search) applyWebSearchTool(ctx, resolved.searchMaxResults, resolved.searchTimeoutMs)
|
||||
if (resolved.search) {
|
||||
applyWebSearchTool(ctx, resolved.searchMaxResults, resolved.searchTimeoutMs, resolved.fetch)
|
||||
}
|
||||
if (resolved.fetch) applyWebFetchTool(ctx, resolved.fetchTimeoutMs, resolved.fetchMaxOutputChars)
|
||||
}
|
||||
|
||||
@@ -204,12 +204,21 @@ export function presentSearchResult(args: { query: string }, result: ToolResult)
|
||||
* request's `maxResults`.
|
||||
* @param timeoutMs - the cooperative tool-call budget (ms) attached as the tool's
|
||||
* `ToolDefinition.timeoutMs` for `@deepseek-ai/dsh-timeout-policy` to enforce.
|
||||
* @param fetchEnabled - whether the same composition exposes `web_fetch`, which
|
||||
* controls whether search guidance may recommend that follow-up tool.
|
||||
*/
|
||||
export function applyWebSearchTool(ctx: Context, maxResults: number, timeoutMs: number): void {
|
||||
export function applyWebSearchTool(
|
||||
ctx: Context,
|
||||
maxResults: number,
|
||||
timeoutMs: number,
|
||||
fetchEnabled: boolean,
|
||||
): void {
|
||||
ctx.systemPrompt.section({
|
||||
name: 'tool:web_search',
|
||||
order: 110,
|
||||
text: 'Use the web_search tool to discover current information on the web. It returns an optional answer plus a list of source URLs. Follow up with web_fetch when you need the full content of a specific result, and cite the relevant URLs as markdown links.',
|
||||
text: fetchEnabled
|
||||
? 'Use the web_search tool to discover current information on the web. It returns an optional answer plus a list of source URLs. Follow up with web_fetch when you need the full content of a specific result, and cite the relevant URLs as markdown links.'
|
||||
: 'Use the web_search tool to discover current information on the web. It returns an optional answer plus a list of source URLs. Use the returned source snippets when available, and cite the relevant URLs as markdown links.',
|
||||
})
|
||||
|
||||
ctx.tools.register(defineTool({
|
||||
|
||||
@@ -483,8 +483,17 @@ describe('tool-web registration', () => {
|
||||
const { fiber, ctx } = await mountTools()
|
||||
const prompt = await ctx.systemPrompt.assemble()
|
||||
const text = prompt.sections.map(s => s.text).join('\n')
|
||||
expect(text).toContain('web_search')
|
||||
expect(text).toContain('web_fetch')
|
||||
expect(text).toContain('Use the web_search tool to discover current information on the web. It returns an optional answer plus a list of source URLs. Follow up with web_fetch when you need the full content of a specific result, and cite the relevant URLs as markdown links.')
|
||||
expect(text).toContain('Use the web_fetch tool to retrieve the content of a specific HTTP(S) URL')
|
||||
await fiber.dispose()
|
||||
})
|
||||
|
||||
it('does not advertise web_fetch in search-only prompt guidance', async () => {
|
||||
const { fiber, ctx } = await mountTools({ config: { search: true, fetch: false } })
|
||||
const prompt = await ctx.systemPrompt.assemble()
|
||||
const text = prompt.sections.map(s => s.text).join('\n')
|
||||
expect(text).toContain('Use the returned source snippets when available')
|
||||
expect(text).not.toContain('web_fetch')
|
||||
await fiber.dispose()
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user