refactor: apply repository naming contract
Apply the accepted pre-release package, service, type, directory, and role renames as one repository-wide change.
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: 6a7ca42773f4a62b75d6077c5cdd892b0ccfdbee
|
||||
README.zh.md: d8dd51dcc8cf5146c3bc8ae28715ddf08ca7721a
|
||||
README.md: 81dc4d3f3dbf9788e68b86513bfa09271fb99c84
|
||||
README.zh.md: 8e976f23f72347e12c6aea35f9b99c5d8ad31d85
|
||||
|
||||
@@ -2,7 +2,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`](../../guard/timeout-policy/README.md) (a `tools/execute` wrapper); each tool just forwards `exec.signal` to the seam.
|
||||
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-tool-call-timeout-policy`](../../guard/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 }`). 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.
|
||||
|
||||
@@ -11,7 +11,7 @@ Each tool is registered independently; a product that wants only one disables th
|
||||
| Tool | Args | Behavior |
|
||||
|---|---|---|
|
||||
| `web_search` | `query` (string) | Discovery. Returns an optional answer plus source URLs. `max_results` is **not** model-facing — the tool sets the bound (the `searchMaxResults` config, default 8) and passes it to the seam. |
|
||||
| `web_fetch` | `url` (string) | Retrieves a specific URL. HTML bodies are rendered to markdown (turndown with GFM tables/strikethrough); text bodies pass through. A non-2xx status is reported, not an error. The tool-call timeout is deployment policy (`dsh-timeout-policy`), not a model argument. |
|
||||
| `web_fetch` | `url` (string) | Retrieves a specific URL. HTML bodies are rendered to markdown (turndown with GFM tables/strikethrough); text bodies pass through. A non-2xx status is reported, not an error. The tool-call timeout is deployment policy (`dsh-tool-call-timeout-policy`), not a model argument. |
|
||||
|
||||
Both tools opt into concurrent scheduling because provider reads return content without mutating parent-agent state.
|
||||
|
||||
@@ -28,7 +28,7 @@ The normalized service results are also the canonical tool values: `WebSearchRes
|
||||
| `searchTimeoutMs` | `30000` | Cooperative tool-call timeout budget (ms) for `web_search`. |
|
||||
| `fetchMaxOutputChars` | `200000` | Cap on source characters converted synchronously and on one complete `web_fetch` output (header, rendered body, and footer); a cut body gets the truncation notice when it fits. |
|
||||
|
||||
`fetchTimeoutMs`/`searchTimeoutMs` declare each tool's cooperative timeout budget (attached as `ToolDefinition.timeoutMs`), enforced by [`@deepseek-ai/dsh-timeout-policy`](../../guard/timeout-policy/README.md); the model-facing schema exposes no timeout argument. `fetchMaxOutputChars` bounds both synchronous conversion work and the complete rendered result: only that many source characters are converted, and the header, converted prefix, and truncation notice are then capped together. The default leaves headroom above the local provider's 100,000-character body cap, but rendered expansion can still make the final bound truncate the result.
|
||||
`fetchTimeoutMs`/`searchTimeoutMs` declare each tool's cooperative timeout budget (attached as `ToolDefinition.timeoutMs`), enforced by [`@deepseek-ai/dsh-tool-call-timeout-policy`](../../guard/timeout-policy/README.md); the model-facing schema exposes no timeout argument. `fetchMaxOutputChars` bounds both synchronous conversion work and the complete rendered result: only that many source characters are converted, and the header, converted prefix, and truncation notice are then capped together. The default leaves headroom above the local provider's 100,000-character body cap, but rendered expansion can still make the final bound truncate the result.
|
||||
|
||||
```yaml
|
||||
- id: tool-web
|
||||
@@ -37,7 +37,7 @@ The normalized service results are also the canonical tool values: `WebSearchRes
|
||||
|
||||
## Stable registration
|
||||
|
||||
Tool registration follows product **enablement**, not backend availability. A tool stays visible even when its selected provider is missing, misconfigured, ambiguous, or temporarily unavailable; the seam resolves the provider at execution time and execution fails with a structured `WebError` (e.g. `WEB_PROVIDER_UNAVAILABLE`, `WEB_PROVIDER_AMBIGUOUS`), which `ToolRegistry.execute()` turns into an error tool result the model can read and hooks/UI can route on. This keeps the model schema stable without making plugin load order, credential state, or HMR timing part of the model-facing contract. To remove a web tool entirely, disable it here in config.
|
||||
Tool registration follows product **enablement**, not backend availability. A tool stays visible even when its selected provider is missing, misconfigured, ambiguous, or temporarily unavailable; the seam resolves the provider at execution time and execution fails with a structured `WebError` (e.g. `WEB_PROVIDER_UNAVAILABLE`, `WEB_PROVIDER_AMBIGUOUS`), which `ToolRuntime.execute()` turns into an error tool result the model can read and hooks/UI can route on. This keeps the model schema stable without making plugin load order, credential state, or HMR timing part of the model-facing contract. To remove a web tool entirely, disable it here in config.
|
||||
|
||||
The tool never calls a provider's `available()` and never enumerates providers — its only execution path is `ctx.web.search()` / `ctx.web.fetch()`, and provider unavailability reaches it as the structured `WebError` codes selection throws at execution time. Provider selection stays entirely inside the seam, with one owner.
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
[English](README.md) | 中文
|
||||
|
||||
面向模型的 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`;该包绝不导入具体提供方。两个工具都不公开面向模型的超时:每个工具的协作式工具调用超时预算通过配置在此声明(`fetchTimeoutMs`/`searchTimeoutMs`,附加为 `ToolDefinition.timeoutMs`),由 [`@deepseek-ai/dsh-timeout-policy`](../../guard/timeout-policy/README.md)(`tools/execute` 包装层)强制执行;每个工具只把 `exec.signal` 转发给 seam。
|
||||
面向模型的 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`;该包绝不导入具体提供方。两个工具都不公开面向模型的超时:每个工具的协作式工具调用超时预算通过配置在此声明(`fetchTimeoutMs`/`searchTimeoutMs`,附加为 `ToolDefinition.timeoutMs`),由 [`@deepseek-ai/dsh-tool-call-timeout-policy`](../../guard/timeout-policy/README.md)(`tools/execute` 包装层)强制执行;每个工具只把 `exec.signal` 转发给 seam。
|
||||
|
||||
每个工具独立注册;只需要其中一个工具的产品可以通过配置禁用另一个(`{ search: false }`/`{ fetch: false }`)。仅当抓取也通过配置启用时,搜索指引才会提及 `web_fetch`;仅启用搜索的组合则会要求模型使用返回的 snippet 并引用其 URL。
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
| 工具 | 参数 | 行为 |
|
||||
|---|---|---|
|
||||
| `web_search` | `query`(string) | 用于发现信息。返回可选答案与来源 URL。`max_results` **不**面向模型:工具设置上限(`searchMaxResults` 配置,默认 8)并传给 seam。 |
|
||||
| `web_fetch` | `url`(string) | 获取特定 URL。HTML 主体渲染为 markdown(turndown,带 GFM 表格/删除线);文本主体原样通过。非 2xx 状态会报告,而非报错。工具调用超时是部署策略(`dsh-timeout-policy`),不是模型参数。 |
|
||||
| `web_fetch` | `url`(string) | 获取特定 URL。HTML 主体渲染为 markdown(turndown,带 GFM 表格/删除线);文本主体原样通过。非 2xx 状态会报告,而非报错。工具调用超时是部署策略(`dsh-tool-call-timeout-policy`),不是模型参数。 |
|
||||
|
||||
两个工具都选择并发调度,因为提供方读取会返回内容,不会修改父 agent(智能体)的状态。
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
| `searchTimeoutMs` | `30000` | `web_search` 的协作式工具调用超时预算(ms)。 |
|
||||
| `fetchMaxOutputChars` | `200000` | 同步转换的源字符数与单次完整 `web_fetch` 输出的上限(状态头、渲染后的主体与页脚合并计算);主体被截断时,在能容纳的情况下附带截断提示。 |
|
||||
|
||||
`fetchTimeoutMs`/`searchTimeoutMs` 声明每个工具的协作式超时预算(附加为 `ToolDefinition.timeoutMs`),由 [`@deepseek-ai/dsh-timeout-policy`](../../guard/timeout-policy/README.md) 强制执行;面向模型的 schema 不公开超时参数。`fetchMaxOutputChars` 同时限制同步转换工作量和完整渲染结果:只转换至多该数量的源字符,随后对状态头、转换后的前缀和截断提示合并设限。默认值为本地提供方的 100,000 字符主体上限留出余量,但渲染膨胀仍可能使最终上限截断结果。
|
||||
`fetchTimeoutMs`/`searchTimeoutMs` 声明每个工具的协作式超时预算(附加为 `ToolDefinition.timeoutMs`),由 [`@deepseek-ai/dsh-tool-call-timeout-policy`](../../guard/timeout-policy/README.md) 强制执行;面向模型的 schema 不公开超时参数。`fetchMaxOutputChars` 同时限制同步转换工作量和完整渲染结果:只转换至多该数量的源字符,随后对状态头、转换后的前缀和截断提示合并设限。默认值为本地提供方的 100,000 字符主体上限留出余量,但渲染膨胀仍可能使最终上限截断结果。
|
||||
|
||||
```yaml
|
||||
- id: tool-web
|
||||
@@ -37,7 +37,7 @@
|
||||
|
||||
## 稳定注册
|
||||
|
||||
工具注册遵循产品**启用状态**,而非后端可用性。即使选中的提供方缺失、错误配置、存在歧义或暂时不可用,工具仍保持可见;seam 在执行时解析提供方,执行以结构化 `WebError`(例如 `WEB_PROVIDER_UNAVAILABLE`、`WEB_PROVIDER_AMBIGUOUS`)失败,`ToolRegistry.execute()` 会把它转为模型可读、钩子/UI 可路由的错误工具结果。这样无需把插件加载顺序、凭据状态或 HMR(热模块替换)时机纳入面向模型约定,也能保持模型 schema 稳定。要彻底移除 web 工具,请在此处通过配置将其禁用。
|
||||
工具注册遵循产品**启用状态**,而非后端可用性。即使选中的提供方缺失、错误配置、存在歧义或暂时不可用,工具仍保持可见;seam 在执行时解析提供方,执行以结构化 `WebError`(例如 `WEB_PROVIDER_UNAVAILABLE`、`WEB_PROVIDER_AMBIGUOUS`)失败,`ToolRuntime.execute()` 会把它转为模型可读、钩子/UI 可路由的错误工具结果。这样无需把插件加载顺序、凭据状态或 HMR(热模块替换)时机纳入面向模型约定,也能保持模型 schema 稳定。要彻底移除 web 工具,请在此处通过配置将其禁用。
|
||||
|
||||
工具绝不会调用提供方的 `available()`,也不会枚举提供方;唯一执行路径是 `ctx.web.search()`/`ctx.web.fetch()`,提供方不可用时,选择机制会在执行阶段抛出结构化 `WebError`,其错误码由工具接收。提供方选择完全留在 seam 内,由单一主体负责。
|
||||
|
||||
|
||||
@@ -53,10 +53,10 @@
|
||||
"@deepseek-ai/dsh-spill-local": "workspace:^",
|
||||
"@deepseek-ai/dsh-spill-policy": "workspace:^",
|
||||
"@deepseek-ai/dsh-system-prompt": "workspace:^",
|
||||
"@deepseek-ai/dsh-timeout-policy": "workspace:^",
|
||||
"@deepseek-ai/dsh-tool-call-timeout-policy": "workspace:^",
|
||||
"@deepseek-ai/dsh-tools": "workspace:^",
|
||||
"@deepseek-ai/dsh-web": "workspace:^",
|
||||
"@deepseek-ai/dsh-web-fetch-local": "workspace:^",
|
||||
"@deepseek-ai/dsh-web-fetch-http": "workspace:^",
|
||||
"@deepseek-ai/dsh-web-search-exa": "workspace:^",
|
||||
"@deepseek-ai/cordis": "workspace:^"
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ turndown.addRule('tableRowWithoutSpanExpansion', {
|
||||
* Validate value constraints the schema DSL can't express: a non-blank `url`.
|
||||
* Throws a plain `Error` otherwise. No timeout parameter — the tool-call budget
|
||||
* is deployment policy declared via `fetchTimeoutMs` config and enforced by
|
||||
* `@deepseek-ai/dsh-timeout-policy`, not a model argument.
|
||||
* `@deepseek-ai/dsh-tool-call-timeout-policy`, not a model argument.
|
||||
*
|
||||
* @param args - the schema-validated `web_fetch` arguments.
|
||||
* @returns the arguments as the seam's request fields.
|
||||
@@ -422,7 +422,7 @@ export function presentFetchResult(args: { url: string }, result: ToolResult): W
|
||||
* @param ctx - context whose `tools` and `systemPrompt` registries receive the
|
||||
* registrations; both are effect-scoped and unregister on plugin dispose.
|
||||
* @param timeoutMs - the cooperative tool-call budget (ms) attached as the tool's
|
||||
* `ToolDefinition.timeoutMs` for `@deepseek-ai/dsh-timeout-policy` to enforce.
|
||||
* `ToolDefinition.timeoutMs` for `@deepseek-ai/dsh-tool-call-timeout-policy` to enforce.
|
||||
* @param maxOutputChars - cap on the complete rendered tool output (see
|
||||
* {@link formatFetchOutput}) and on source characters converted synchronously.
|
||||
*/
|
||||
|
||||
@@ -73,7 +73,7 @@ function assertPositiveInteger(name: string, value: number): void {
|
||||
* that wants only one disables the other in config. Each tool's cooperative
|
||||
* timeout budget (`fetchTimeoutMs`/`searchTimeoutMs`, default 30000) is resolved
|
||||
* here and attached to the tool as `ToolDefinition.timeoutMs` for
|
||||
* `@deepseek-ai/dsh-timeout-policy` to enforce. The tools' disposers are
|
||||
* `@deepseek-ai/dsh-tool-call-timeout-policy` to enforce. The tools' disposers are
|
||||
* fiber-scoped (the effect-based registries clean up on dispose), so no manual
|
||||
* teardown is needed.
|
||||
*/
|
||||
|
||||
@@ -203,7 +203,7 @@ export function presentSearchResult(args: { query: string }, result: ToolResult)
|
||||
* @param maxResults - the deployment's source cap, sent as every seam
|
||||
* 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.
|
||||
* `ToolDefinition.timeoutMs` for `@deepseek-ai/dsh-tool-call-timeout-policy` to enforce.
|
||||
* @param fetchEnabled - whether the same composition exposes `web_fetch`, which
|
||||
* controls whether search guidance may recommend that follow-up tool.
|
||||
*/
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* Integration: the real fetch backend (`dsh-web-fetch-local`) + a real search provider
|
||||
* Integration: the real fetch backend (`dsh-web-fetch-http`) + a real search provider
|
||||
* (`dsh-web-search-exa`) + the real seam (`dsh-web`) + the model tool (`dsh-tool-web`) + the
|
||||
* tool-call timeout policy (`dsh-timeout-policy`), exercised through `ctx.tools.execute()` —
|
||||
* tool-call timeout policy (`dsh-tool-call-timeout-policy`), exercised through `ctx.tools.execute()` —
|
||||
* nothing bypasses the tool registry. Fetch verifies world effects against loopback HTTP; search
|
||||
* uses the real Exa provider with only its network boundary stubbed.
|
||||
*/
|
||||
@@ -12,12 +12,12 @@ import { AddressInfo } from 'node:net'
|
||||
import { Context } from '@deepseek-ai/cordis'
|
||||
import { CallId } from '@deepseek-ai/dsh-llm'
|
||||
import SystemPrompt from '@deepseek-ai/dsh-system-prompt'
|
||||
import ToolRegistry, { type ToolExecutionResult } from '@deepseek-ai/dsh-tools'
|
||||
import WebService from '@deepseek-ai/dsh-web'
|
||||
import * as WebFetchLocal from '@deepseek-ai/dsh-web-fetch-local'
|
||||
import ToolRuntime, { type ToolExecutionResult } from '@deepseek-ai/dsh-tools'
|
||||
import WebRuntime from '@deepseek-ai/dsh-web'
|
||||
import * as WebFetchLocal from '@deepseek-ai/dsh-web-fetch-http'
|
||||
import * as WebSearchExa from '@deepseek-ai/dsh-web-search-exa'
|
||||
import * as ToolWeb from '@deepseek-ai/dsh-tool-web'
|
||||
import * as TimeoutPolicy from '@deepseek-ai/dsh-timeout-policy'
|
||||
import * as TimeoutPolicy from '@deepseek-ai/dsh-tool-call-timeout-policy'
|
||||
|
||||
const testToolSignal = new AbortController().signal
|
||||
|
||||
@@ -37,8 +37,8 @@ beforeEach(async () => {
|
||||
|
||||
ctx = new Context()
|
||||
await ctx.plugin(SystemPrompt)
|
||||
await ctx.plugin(ToolRegistry)
|
||||
await ctx.plugin(WebService, { searchProvider: WebSearchExa.EXA_PROVIDER_ID, fetchProvider: WebFetchLocal.LOCAL_FETCH_PROVIDER_ID })
|
||||
await ctx.plugin(ToolRuntime)
|
||||
await ctx.plugin(WebRuntime, { searchProvider: WebSearchExa.EXA_PROVIDER_ID, fetchProvider: WebFetchLocal.LOCAL_FETCH_PROVIDER_ID })
|
||||
await ctx.plugin(WebFetchLocal, {})
|
||||
await ctx.plugin(WebSearchExa, { apiKey: 'exa-key', baseURL: 'https://api.exa.test' })
|
||||
// The shipped deployment shape: the tool-call budget is declared by tool-web
|
||||
@@ -132,8 +132,8 @@ describe('tool-call timeout returns TOOL_TIMEOUT (deadline wins over a slow fetc
|
||||
|
||||
tctx = new Context()
|
||||
await tctx.plugin(SystemPrompt)
|
||||
await tctx.plugin(ToolRegistry)
|
||||
await tctx.plugin(WebService, { fetchProvider: WebFetchLocal.LOCAL_FETCH_PROVIDER_ID })
|
||||
await tctx.plugin(ToolRuntime)
|
||||
await tctx.plugin(WebRuntime, { fetchProvider: WebFetchLocal.LOCAL_FETCH_PROVIDER_ID })
|
||||
// Provider backstop well ABOVE the tool-call budget, so the policy wins.
|
||||
await tctx.plugin(WebFetchLocal, { timeoutMs: 30_000 })
|
||||
await tctx.plugin(TimeoutPolicy)
|
||||
@@ -150,7 +150,7 @@ describe('tool-call timeout returns TOOL_TIMEOUT (deadline wins over a slow fetc
|
||||
it('returns a structured TOOL_TIMEOUT (not the provider WEB_FETCH_TIMEOUT) when the tool-call budget wins', async () => {
|
||||
const out = await tctx.tools.execute({ signal: testToolSignal, callId: CallId('slow-1'), name: 'web_fetch', arguments: { url: slowBase } })
|
||||
expect(out.isError).toBe(true)
|
||||
// The outer tool-call deadline won: TOOL_TIMEOUT, owned by dsh-timeout-policy,
|
||||
// The outer tool-call deadline won: TOOL_TIMEOUT, owned by dsh-tool-call-timeout-policy,
|
||||
// NOT the provider's own WEB_FETCH_TIMEOUT (its 30s backstop never fired).
|
||||
expect(out.error?.info?.code).toBe('TOOL_TIMEOUT')
|
||||
const text = out.content.map(b => (b.type === 'text' ? b.text : '')).join('')
|
||||
@@ -160,7 +160,7 @@ describe('tool-call timeout returns TOOL_TIMEOUT (deadline wins over a slow fetc
|
||||
it('the provider backstop still protects a direct provider call (no tool-call policy in that path)', async () => {
|
||||
// A direct provider caller bypasses tools/execute, so a short configured backstop
|
||||
// must produce provider-owned WEB_FETCH_TIMEOUT rather than TOOL_TIMEOUT.
|
||||
const direct = new WebFetchLocal.LocalFetchProvider({
|
||||
const direct = new WebFetchLocal.HttpFetchProvider({
|
||||
maxUrlLength: 2048,
|
||||
maxResponseBytes: 5_000_000,
|
||||
maxBodyChars: 100_000,
|
||||
|
||||
@@ -9,8 +9,8 @@ import { describe, expect, it } from 'vitest'
|
||||
import { Context } from '@deepseek-ai/cordis'
|
||||
import Loader from '@deepseek-ai/cordis-plugin-loader'
|
||||
import SystemPrompt from '@deepseek-ai/dsh-system-prompt'
|
||||
import ToolRegistry from '@deepseek-ai/dsh-tools'
|
||||
import WebService from '@deepseek-ai/dsh-web'
|
||||
import ToolRuntime from '@deepseek-ai/dsh-tools'
|
||||
import WebRuntime from '@deepseek-ai/dsh-web'
|
||||
import * as toolWeb from '@deepseek-ai/dsh-tool-web'
|
||||
|
||||
describe('dsh-tool-web real-load-path guard', () => {
|
||||
@@ -28,8 +28,8 @@ describe('dsh-tool-web real-load-path guard', () => {
|
||||
it('boots over ctx.web through the unwrapped module without an inject error', async () => {
|
||||
const ctx = new Context()
|
||||
await ctx.plugin(SystemPrompt)
|
||||
await ctx.plugin(ToolRegistry)
|
||||
await ctx.plugin(WebService, {})
|
||||
await ctx.plugin(ToolRuntime)
|
||||
await ctx.plugin(WebRuntime, {})
|
||||
|
||||
const loader = Object.create(Loader.prototype) as Loader
|
||||
const unwrapped = loader.unwrapExports(toolWeb) as Parameters<Context['plugin']>[0]
|
||||
|
||||
@@ -17,12 +17,12 @@ import { Context } from '@deepseek-ai/cordis'
|
||||
import { CallId } from '@deepseek-ai/dsh-llm'
|
||||
import { SessionId } from '@deepseek-ai/dsh-session'
|
||||
import SystemPrompt from '@deepseek-ai/dsh-system-prompt'
|
||||
import ToolRegistry from '@deepseek-ai/dsh-tools'
|
||||
import ToolRuntime from '@deepseek-ai/dsh-tools'
|
||||
import type { ToolExecution } from '@deepseek-ai/dsh-tools'
|
||||
|
||||
const testToolSignal = new AbortController().signal
|
||||
import WebService from '@deepseek-ai/dsh-web'
|
||||
import * as WebFetchLocal from '@deepseek-ai/dsh-web-fetch-local'
|
||||
import WebRuntime from '@deepseek-ai/dsh-web'
|
||||
import * as WebFetchLocal from '@deepseek-ai/dsh-web-fetch-http'
|
||||
import LocalSpillStore from '@deepseek-ai/dsh-spill-local'
|
||||
import * as SpillPolicy from '@deepseek-ai/dsh-spill-policy'
|
||||
import * as ToolWeb from '@deepseek-ai/dsh-tool-web'
|
||||
@@ -47,8 +47,8 @@ beforeEach(async () => {
|
||||
|
||||
ctx = new Context()
|
||||
await ctx.plugin(SystemPrompt)
|
||||
await ctx.plugin(ToolRegistry)
|
||||
await ctx.plugin(WebService, { fetchProvider: WebFetchLocal.LOCAL_FETCH_PROVIDER_ID })
|
||||
await ctx.plugin(ToolRuntime)
|
||||
await ctx.plugin(WebRuntime, { fetchProvider: WebFetchLocal.LOCAL_FETCH_PROVIDER_ID })
|
||||
// Provider cap generous so the tool returns a large formatted result; the
|
||||
// policy cap is what triggers the spill (the Agent Note's separation of concerns).
|
||||
await ctx.plugin(WebFetchLocal, { maxBodyChars: 500_000 })
|
||||
|
||||
@@ -3,8 +3,8 @@ import { Context } from '@deepseek-ai/cordis'
|
||||
import TurndownService from 'turndown'
|
||||
import { CallId } from '@deepseek-ai/dsh-llm'
|
||||
import SystemPrompt from '@deepseek-ai/dsh-system-prompt'
|
||||
import ToolRegistry, { type ToolExecutionResult } from '@deepseek-ai/dsh-tools'
|
||||
import WebService from '@deepseek-ai/dsh-web'
|
||||
import ToolRuntime, { type ToolExecutionResult } from '@deepseek-ai/dsh-tools'
|
||||
import WebRuntime from '@deepseek-ai/dsh-web'
|
||||
import type { WebSearchProvider, WebSearchResult } from '@deepseek-ai/dsh-web'
|
||||
import * as ToolWeb from '@deepseek-ai/dsh-tool-web'
|
||||
import {
|
||||
@@ -36,14 +36,14 @@ function searchProvider(result: WebSearchResult, isAvailable = available): WebSe
|
||||
/** Mount the real registry, seam, and tool-web; return an executor helper. */
|
||||
async function mountTools(opts: {
|
||||
config?: ToolWeb.Config
|
||||
webConfig?: ConstructorParameters<typeof WebService>[1]
|
||||
webConfig?: ConstructorParameters<typeof WebRuntime>[1]
|
||||
search?: WebSearchProvider
|
||||
fetchProvider?: import('@deepseek-ai/dsh-web').WebFetchProvider
|
||||
} = {}): Promise<{ ctx: Context; fiber: Awaited<ReturnType<Context['plugin']>>; call: (name: string, args: unknown) => Promise<ToolExecutionResult> }> {
|
||||
const ctx = new Context()
|
||||
await ctx.plugin(SystemPrompt)
|
||||
await ctx.plugin(ToolRegistry)
|
||||
await ctx.plugin(WebService, opts.webConfig ?? {})
|
||||
await ctx.plugin(ToolRuntime)
|
||||
await ctx.plugin(WebRuntime, opts.webConfig ?? {})
|
||||
if (opts.search) ctx.web.registerSearchProvider(opts.search)
|
||||
if (opts.fetchProvider) ctx.web.registerFetchProvider(opts.fetchProvider)
|
||||
const fiber = await ctx.plugin(ToolWeb, opts.config ?? {})
|
||||
@@ -595,7 +595,7 @@ describe('tool-web execution through the real registry', () => {
|
||||
truncated: false,
|
||||
})
|
||||
// The model schema exposes no timeout: the tool forwards only the url; the
|
||||
// tool-call budget is owned by dsh-timeout-policy over exec.signal.
|
||||
// tool-call budget is owned by dsh-tool-call-timeout-policy over exec.signal.
|
||||
expect(seen.request).toEqual({ url: 'https://a.test' })
|
||||
expect(seen.signal).toBe(controller.signal)
|
||||
await fiber.dispose()
|
||||
@@ -679,8 +679,8 @@ describe('searchMaxResults is plugin config', () => {
|
||||
])('rejects a %s searchMaxResults at load', async (_label, value) => {
|
||||
const ctx = new Context()
|
||||
await ctx.plugin(SystemPrompt)
|
||||
await ctx.plugin(ToolRegistry)
|
||||
await ctx.plugin(WebService, {})
|
||||
await ctx.plugin(ToolRuntime)
|
||||
await ctx.plugin(WebRuntime, {})
|
||||
await expect(ctx.plugin(ToolWeb, { searchMaxResults: value }))
|
||||
.rejects.toThrow(/tool-web: searchMaxResults must be a positive integer/)
|
||||
})
|
||||
@@ -707,8 +707,8 @@ describe('tool-call timeout budget is plugin config', () => {
|
||||
])('rejects a non-positive-integer %s at load', async (key, config) => {
|
||||
const ctx = new Context()
|
||||
await ctx.plugin(SystemPrompt)
|
||||
await ctx.plugin(ToolRegistry)
|
||||
await ctx.plugin(WebService, {})
|
||||
await ctx.plugin(ToolRuntime)
|
||||
await ctx.plugin(WebRuntime, {})
|
||||
await expect(ctx.plugin(ToolWeb, config))
|
||||
.rejects.toThrow(new RegExp(`tool-web: ${key} must be a positive integer`))
|
||||
})
|
||||
@@ -739,8 +739,8 @@ describe('fetchMaxOutputChars is plugin config', () => {
|
||||
it.each([0, -1, 1.5])('rejects an invalid fetchMaxOutputChars value %s at load', async (value) => {
|
||||
const ctx = new Context()
|
||||
await ctx.plugin(SystemPrompt)
|
||||
await ctx.plugin(ToolRegistry)
|
||||
await ctx.plugin(WebService, {})
|
||||
await ctx.plugin(ToolRuntime)
|
||||
await ctx.plugin(WebRuntime, {})
|
||||
await expect(ctx.plugin(ToolWeb, { fetchMaxOutputChars: value }))
|
||||
.rejects.toThrow(/tool-web: fetchMaxOutputChars must be a positive integer/)
|
||||
})
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
"path": "../web"
|
||||
},
|
||||
{
|
||||
"path": "../../support/invariants"
|
||||
"path": "../../runtime-diagnostics/invariants"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user