docs: translate remaining READMEs

This commit is contained in:
Tianyi Cui
2026-07-26 05:03:53 +08:00
parent 37bfac749b
commit 226dc7a249
559 changed files with 11227 additions and 1 deletions

View File

@@ -0,0 +1,6 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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
README.md: 8cd173b922ead32219ffab2b2d6b6428b3ce375c
README.zh.md: b10849bbddf6d62701d72b064a58c728ffb1e1b7

View File

@@ -1,5 +1,7 @@
# web/ - web capability family
English | [中文](README.zh.md)
The web access capability seam: an abstract web interface, search/fetch provider implementations, and the model-facing web tools. All **product** packages.
| Package | Role | ctx key |

18
packages/web/README.zh.md Normal file
View File

@@ -0,0 +1,18 @@
# web/ - web 能力家族
[English](README.md) | 中文
web 访问能力 seam抽象 web 接口、搜索/抓取提供方实现,以及面向模型的 web 工具。这些全是**产品** 包。
| 包 | 职责 | ctx key |
|---|---|---|
| `web/` | 抽象 web seam搜索抓取提供方注册表 + 选择 + 词汇 + `WebError` | `ctx.web` |
| `web-search-exa/` | Exa 支持的 `WebSearchProvider` | (注册到 `ctx.web` |
| `web-search-perplexity/` | Perplexity 支持的 `WebSearchProvider` | (注册到 `ctx.web` |
| `web-search-deepseek/` | DeepSeek 支持的 `WebSearchProvider`,通过 Anthropic 兼容 API 使用原生 `web_search` | (注册到 `ctx.web` |
| `web-fetch-local/` | 匿名公共 HTTP(S) `WebFetchProvider` | (注册到 `ctx.web` |
| `tool-web/` | 面向模型的 `web_search``web_fetch` 工具 schema | (注册到 `ctx.tools` |
接口位于 `web/web/`。与 bash/fs 不同,该 seam 跨越**两种能力**(搜索和抓取),每种能力都可能有多个提供方:`ctx.web` 是单一的 web 访问中间层,拥有一项提供方选择策略、一套中止/错误词汇,以及一个面向产品的「该 harness 如何访问 web」配置表层。提供方注册的是**能力** 而非工具;`tool-web` 是面向模型名称、schema、提示词指引和呈现的唯一 owner。替换搜索提供方不会改变模型提出查询的方式替换抓取实现也不会改变模型请求 URL 的方式。
设计原理见 [web 能力 seam Agent Note](../../.agents/notes/implemented/architecture/2026-06-24-web-capability-seam.md),其中也解释了搜索与抓取为何有意合并为一个 seam以及为何暂缓实现 `web_fetch` 的 SSRF 防护。

View File

@@ -0,0 +1,6 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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
README.md: 5e567115c386d14b7e412ed2502e7290826a5e5e
README.zh.md: b17fe4107908381806d4029481bbf03696c4f313

View File

@@ -1,5 +1,7 @@
# @deepseek-ai/dsh-tool-web
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 `presentCall`. 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 }`).

View File

@@ -0,0 +1,131 @@
# @deepseek-ai/dsh-tool-web
[English](README.md) | 中文
面向模型的 web 工具套件 `web_search``web_fetch`,构建于 [web 能力 seam](../web/README.md)`ctx.web`之上。它只拥有面向模型的事项工具名称、JSON schema、snake_case 参数名称、提示词区段、结果数量上限、结果格式、HTML→markdown 呈现,以及 `presentCall`。所有 web 访问都通过 `ctx.web`;该包绝不导入具体提供方。两个工具都不公开面向模型的超时:每个工具的协作式工具调用预算通过配置在此声明(`fetchTimeoutMs``searchTimeoutMs`,附加为 `ToolDefinition.timeoutMs`),由 [`@deepseek-ai/dsh-timeout-policy`](../../timeout/timeout-policy/README.md)`tools/execute` 包装层)强制执行;每个工具只把 `exec.signal` 转发给 seam。
每个工具独立注册;只需要其中一个工具的产品可以通过配置禁用另一个(`{ search: false }``{ fetch: false }`)。
## 工具
| 工具 | 参数 | 行为 |
|---|---|---|
| `web_search` | `query`string | 发现。返回可选答案与源 URL。`max_results` **不** 面向模型:工具设置上限(`searchMaxResults` 配置,默认 8并传给 seam。 |
| `web_fetch` | `url`string | 获取特定 URL。HTML 主体渲染为近似 markdown 的文本;文本主体原样通过。非 2xx 状态会报告,而非报错。工具调用超时是部署策略(`dsh-timeout-policy`),不是模型参数。 |
两个工具都选择并发调度,因为提供方读取会返回内容,不会修改父 agent 状态。
规范化 seam 结果也是规范工具值:`WebSearchResult``WebFetchResult`。原生 renderer 保留下述答案/源与抓取主体文本;提供方搜索/主体上限仍是获取限制,而非仅呈现截断。
## 配置
| Key | 默认值 | 含义 |
|---|---|---|
| `search` | `true` | 注册 `web_search`。 |
| `fetch` | `true` | 注册 `web_fetch`。 |
| `searchMaxResults` | `8` | 一次 `web_search` 调用返回的源数量上限seam 截断更长的提供方列表并标记)。 |
| `fetchTimeoutMs` | `30000` | `web_fetch` 的协作式工具调用超时预算ms。 |
| `searchTimeoutMs` | `30000` | `web_search` 的协作式工具调用超时预算ms。 |
`fetchTimeoutMs``searchTimeoutMs` 声明每个工具的协作式超时预算(附加为 `ToolDefinition.timeoutMs`),由 [`@deepseek-ai/dsh-timeout-policy`](../../timeout/timeout-policy/README.md) 强制执行;面向模型的 schema 不公开超时参数。
```yaml
- id: tool-web
name: '@deepseek-ai/dsh-tool-web'
```
## 稳定注册
工具注册遵循产品**启用状态**而非后端可用性。即使选中的提供方缺失、错误配置、存在歧义或暂时不可用工具仍保持可见seam 在执行时解析提供方,执行以结构化 `WebError`(例如 `WEB_PROVIDER_UNAVAILABLE``WEB_PROVIDER_AMBIGUOUS`)失败,`ToolRegistry.execute()` 会把它转为模型可读、hookUI 可路由的错误工具结果。这样无需把插件加载顺序、credential 状态或 HMR 时机纳入面向模型契约,也能保持模型 schema 稳定。要彻底移除 web 工具,请在此处通过配置将其禁用。
工具绝不会调用提供方的 `available()`,也不会枚举提供方;唯一执行路径是 `ctx.web.search()``ctx.web.fetch()`,提供方不可用会作为选择机制在执行时抛出的结构化 `WebError` code 到达工具。提供方选择完全留在 seam 内,只有一个 owner。
## 模型体验
### 系统提示词
#### 模型看到的内容
搜索与抓取分别贡献以下 web-search 和 web-fetch 指引。scope 工具限制不会移除这些独立注册的区段。
##### 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_fetch tool to retrieve the content of a specific HTTP(S) URL (for example a result from web_search). It returns the page content decoded to text. Cite the URL as a markdown link when you use its content.
```
#### Token 影响
每个通过配置启用的工具会为每次请求增加固定指引成本,即使限制隐藏了其 schema。
#### KV Cache 影响
只要启用工具、scope 与指引文本不变前缀就保持稳定。配置启用状态或插件生命周期可能使从第一个变化的提示词区段起的复用失效scope schema 限制不会移除该区段。
### 工具 schema
#### 模型看到的内容
模型会看到生成的 [`web_search` 与 `web_fetch` schema](../../../docs/tool-catalog.md#deepseek-aidsh-tool-web)。结果数量与超时预算属于部署设置,不是模型参数。
#### Token 影响
每次请求承担固定 schema 成本;通过配置禁用会同时移除 schema 与指引scope 限制只移除 schema。
#### KV Cache 影响
只要定义与可见性不变,前缀就保持稳定。配置启用状态、插件生命周期或 scope 限制可能使从第一个变化的 schema token 起的复用失效。
### 搜索结果
#### 模型看到的内容
可选的提供方答案之后是 `Sources:`,再跟随数据相关、形状精确为 `- [<title-or-url>](<url>)` 的行,并可添加后缀 ` — <snippet> (<publishedAt>)`。既无答案也无源时,结果显示 `No results found.`。列表达到上限时会添加 `(Showing the first <count> sources. Refine the query for more.)`;每项结果都以 `Cite the relevant URLs above as markdown links in your answer.` 结尾。
#### Token 影响
数据相关结果会重复发送直到压缩,源数量由 `searchMaxResults` 限制。
#### KV Cache 影响
仅追加;新可见内容位于可复用请求前缀之后,不会使现有 KV-cache 配置项失效。
### 抓取结果
#### 模型看到的内容
成功抓取的精确形状是 `Fetched <finalUrl> (HTTP <statusCode>)`、一个空行,以及提供方拥有的解码主体。发生截断时会再添加一个空行和 `(Content truncated. Fetch a more specific URL or section for the full text.)`;失败变为 `Error: <message>`。查询与 URL 保留在调用历史中。
#### Token 影响
提供方上限限制主体大小;保留的调用参数与结果会重复发送直到压缩,超时策略可以把迟到结果替换为简短错误。
#### KV Cache 影响
仅追加;新可见内容位于可复用请求前缀之后,不会使现有 KV-cache 配置项失效。
### 参数错误
#### 模型看到的内容
空输入精确地变为 `Error: query must be a non-empty string``Error: url must be a non-empty string`
#### Token 影响
只有失败调用会增加这些保留 token。
#### KV Cache 影响
仅追加;新可见内容位于可复用请求前缀之后,不会使现有 KV-cache 配置项失效。
## 已知限制与暂缓事项
- **`htmlToMarkdown` 是最小正则转换器,不是 HTML parser**:它会移除 script/style/noscript保留标题项目符号链接并解码约十余个命名 entity表格、图片与嵌套格式会丢失。
- **面向模型的表层有意保持最小,提升项暂缓**`max_results` 保持为配置上限(不是模型参数),`web_fetch` 只接受 `url`(没有 `format``prompt`LLM 摘要模式);两项都列为 [seam Agent Note](../../../.agents/notes/implemented/architecture/2026-06-24-web-capability-seam.md) 中的后续步骤。
- **没有 web 专用权限策略**:两个工具都不会请求 `ctx.approval` 就直接执行;需要确认的部署必须添加 `tools/pre-execute` 策略,该包不定义持久 URLdomain 授权。

View File

@@ -0,0 +1,6 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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
README.md: 8cadba2de7a2708252ebc7143840825fd4fe4549
README.zh.md: bd6257b41736153a608df93c5baa74eac38d50e3

View File

@@ -1,5 +1,7 @@
# @deepseek-ai/dsh-web-fetch-local
English | [中文](README.zh.md)
An anonymous public HTTP(S) `WebFetchProvider` for the harness [web capability seam](../web/README.md) (`ctx.web`). It retrieves a concrete URL and returns a status code plus bounded decoded content.
This is an **implementation** package: it registers a provider into `ctx.web`, it does not own the key and it does not register a model-facing tool. It is a function/namespace plugin (`inject: ['web']`).

View File

@@ -0,0 +1,51 @@
# @deepseek-ai/dsh-web-fetch-local
[English](README.md) | 中文
一个匿名公共 HTTP(S) `WebFetchProvider`,用于 harness [web 能力 seam](../web/README.md)`ctx.web`)。它获取具体 URL返回状态码与有界解码内容。
这是一个**实现** 包:它向 `ctx.web` 注册提供方,不拥有该 key也不注册面向模型的工具。它是函数namespace 插件(`inject: ['web']`)。
## 职责拆分
提供方拥有**安全资源获取**URL 验证、HTTP 传输、重定向策略、资源兜底超时、中止传播、字节上限、charset 解码、内容类型分类与二进制拒绝。`@deepseek-ai/dsh-tool-web` 拥有**呈现**HTML→markdown、截断格式。非 2xx HTTP 响应是*结果*(状态码 + 解码主体),不是错误;`WebError` 只用于无法安全获取或表示资源的失败。
提供方的 `timeoutMs` 是直接 `ctx.web.fetch()` 调用方与错误配置部署的资源兜底,不是面向模型的工具调用预算。[`dsh-timeout-policy`](../../timeout/timeout-policy/README.md) 拥有 `web_fetch` 工具调用预算,并通过武装 `exec.signal` 强制执行该预算。
已交付的 web 工具部署会把提供方兜底设为高于工具预算,因此模型调用通常返回 `TOOL_TIMEOUT`。如果外层 deadline 先到达提供方,提供方报告 `WEB_ABORTED`,外层策略再将其替换为 `TOOL_TIMEOUT`。因此,`WEB_FETCH_TIMEOUT` 标识提供方预算已经耗尽的直接 seam 调用方。
## 传输卫生
- 只接受 `http:``https:` URL拒绝 URL 中的 credential`WEB_BLOCKED_URL`)以及过长/格式错误的 URL`WEB_INVALID_URL`)。
- 强制执行 URL 最大长度、响应字节上限(`WEB_FETCH_TOO_LARGE`)、解码主体字符上限、超时(`WEB_FETCH_TIMEOUT`)和重定向跳数上限。
- 把调用方的中止信号(`WEB_ABORTED`)传播到网络请求与流式读取。
- 只跟随**同源** 重定向;跨源重定向以 `WEB_REDIRECT_BLOCKED` 失败,要求发起新的工具调用(沿用 Claude Code 的 WebFetch 模型)。
- 发送显式的产品 `User-Agent`,绝不伪装成浏览器。
- 不受支持的内容类型(例如二进制)以 `WEB_UNSUPPORTED_CONTENT_TYPE` 拒绝。
## 配置
| Key | 默认值 | 含义 |
|---|---|---|
| `maxUrlLength` | `2048` | 接受的请求 URL 最大长度。 |
| `maxResponseBytes` | `5_000_000` | 响应主体最大字节数。 |
| `maxBodyChars` | `100_000` | 解码主体最大字符数。 |
| `timeoutMs` | `30_000` | Node 定时器范围内的抓取超时:直接 `ctx.web.fetch()` 调用方的资源兜底,而非面向模型的工具调用预算(后者属于 `dsh-timeout-policy`)。 |
| `maxRedirects` | `5` | 同源重定向最大跳数(`0` 表示完全不跟随)。 |
| `userAgent` | `deepseek-harness/…` | `User-Agent` 标头。 |
数值限制会在插件构造时验证:除 `maxRedirects` 外,每个上限都必须是正的有限数;`maxRedirects` 必须是非负整数。无效值会抛出异常,不会静默构造限制荒谬的提供方。
## 模型体验
通过 [`dsh-tool-web`](../tool-web/README.md) 间接影响;该工具把此提供方经 `maxBodyChars` 限制的解码文本或 markdown 形状 HTML 置于抓取结果包装中,并保留提供方失败;重定向、标头与传输机制保持隐藏。
#### KV Cache 影响
不会直接失效;请求前缀变更由命名消费方负责。
## 已知限制与暂缓事项
- **SSRF私有网络防护暂缓**不会阻止私有、loopback、link-local、multicast 或其他非公开目标,也不进行 DNS 解析后验证或逐跳重新验证(见 [web 能力 seam Agent Note](../../../.agents/notes/implemented/architecture/2026-06-24-web-capability-seam.md))。在此功能落地前,该提供方是 SSRF 原语;能够访问敏感内部网络目标的部署**禁止启用它**。
- **只解码文本内容**:包括 html/xhtml 与 `text/*` 加 JSON/XML 家族;缺少 `Content-Type` 或任何二进制类型都会抛出 `WEB_UNSUPPORTED_CONTENT_TYPE`,可提取文本的 PDF 解码属于明确的暂缓工作。
- **charset 只来自 `Content-Type` 标头**(默认为 UTF-8HTML `<meta charset>` 声明会被忽略;声明但无法识别的 charset label 会抛出异常,而非回退。

View File

@@ -0,0 +1,6 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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
README.md: 54eb7561b9d81a9e2da565e3870abe094dbe984d
README.zh.md: 5ce5f46882efb94c7d12fd137b77b167a0088741

View File

@@ -1,5 +1,7 @@
# @deepseek-ai/dsh-web-search-deepseek
English | [中文](README.zh.md)
A [DeepSeek](https://deepseek.com)-backed `WebSearchProvider` for the harness [web capability seam](../web/README.md) (`ctx.web`). It calls DeepSeek's **Anthropic-compatible Messages API** (`POST {baseURL}/messages`) with the native `web_search_20250305` server tool enabled, and maps the structured `web_search_tool_result` blocks DeepSeek returns into the seam's normalized `WebSearchResult`.
This is an **implementation** package: it registers a provider into `ctx.web`, it does not own the key and it does not register a model-facing tool. Like `@deepseek-ai/dsh-llm-deepseek`, it is a function/namespace plugin (`inject: ['web']`). The Anthropic wire shape is a provider-private detail — it does **not** make this provider depend on `ctx.llm`.

View File

@@ -0,0 +1,79 @@
# @deepseek-ai/dsh-web-search-deepseek
[English](README.md) | 中文
由 [DeepSeek](https://deepseek.com) 支持的 `WebSearchProvider`,用于 harness [web 能力 seam](../web/README.md)`ctx.web`)。它调用 DeepSeek 的 **Anthropic 兼容 Messages API**`POST {baseURL}/messages`),启用原生 `web_search_20250305` 服务器工具,并把 DeepSeek 返回的结构化 `web_search_tool_result` 块映射为 seam 规范化的 `WebSearchResult`
这是一个**实现** 包:它向 `ctx.web` 注册提供方,不拥有该 key也不注册面向模型的工具。与 `@deepseek-ai/dsh-llm-deepseek` 一样它是函数namespace 插件(`inject: ['web']`。Anthropic 协议形状是提供方私有细节,并**不** 使该提供方依赖 `ctx.llm`
## 与专用搜索端点的区别
Exa 和 Perplexity 提供专用搜索端点DeepSeek 则没有。该提供方改为发起一次携带 `web_search` 服务器工具的**完整 Messages 模型调用**,因此一次搜索会消耗完整模型轮次的延迟与 token比纯检索端点更重。DeepSeek 在服务器侧执行搜索,返回**结构化** `web_search_tool_result` 块;提供方解析这些块,**绝不会从模型文本中抓取 URL**。
**严格模式**:如果响应不含 `web_search_tool_result` 块(未触发原生搜索),提供方会抛出 `WebError` `WEB_PROVIDER_ERROR`,而非降级为文本抓取;这种行为诚实且可诊断。
它复用 `$DEEPSEEK_API_KEY`(不增加 secret但**不会** 复用 `$DEEPSEEK_BASE_URL`:搜索端点使用 Anthropic 兼容基址(`https://api.deepseek.com/anthropic/v1`),不同于 LLM 适配器使用的 chat-completions 基址(`https://api.deepseek.com`)。
## 配置
| Key | 默认值 | 含义 |
|---|---|---|
| `apiKey` | `$DEEPSEEK_API_KEY` | DeepSeek API key。为空缺失时提供方不可用。同时作为 `x-api-key``Authorization: Bearer` 发送(官方与 Anthropic 兼容 proxy。 |
| `baseURL` | `https://api.deepseek.com/anthropic/v1` | Anthropic 兼容端点基址;追加 `/messages`。覆盖时使用 `$DEEPSEEK_SEARCH_BASE_URL` 等独立环境变量;禁止复用属于 chat-completions LLM 适配器的 `$DEEPSEEK_BASE_URL`。无法解析时提供方不可用。 |
| `model` | `deepseek-v4-flash` | Anthropic 格式模型名称。 |
| `apiVersion` | `2023-06-01` | `anthropic-version` 标头值。 |
| `maxTokens` | `4096` | Messages 请求生成 token 的正整数上限。 |
| `maxUses` | `5` | 每次请求使用 `web_search` 服务器工具的正整数上限。 |
```yaml
- id: web-search-deepseek
name: '@deepseek-ai/dsh-web-search-deepseek'
config:
apiKey: !!js process.env.DEEPSEEK_API_KEY
baseURL: !!js process.env.DEEPSEEK_SEARCH_BASE_URL
```
## 映射
DeepSeek 不返回该提供方可作为 `content` 信任的提供方生成答案表层,因此省略 `content``sources[]` 来自 `web_search_result` 配置项,这些配置项位于 `web_search_tool_result` 块内:`url``url``title``title``publishedAt``page_age``cited_text` 配置项按 URL 标识,单独位于文本块的 `citations[]` 中;提供方会将其作为 snippet 连接,没有摘录时省略 `snippet`
结果按 URL 去重因为一次请求可能在多次搜索中呈现同一页面。DeepSeek 公开 `maxUses` 而非结果数量旋钮,因此 seam 会强制执行 `maxResults`:截断 `sources[]` 并设置 `truncated`
提供方失败变为 `WEB_PROVIDER_ERROR`;调用方取消变为 `WEB_ABORTED`。HTTP 重定向会在接触 `Location` 目标前被拒绝,并以 `WEB_PROVIDER_ERROR` 呈现。
## 模型体验
### 辅助 DeepSeek 搜索请求
#### 模型看到的内容
独立的 DeepSeek 模型会接收精确的 `Perform a web search for the query: <query>` 作为 user 文本,并收到一个原生 `web_search` 服务器工具定义。该请求不属于会话模型上下文。
#### Token 影响
每次搜索都会产生独立的提供方输入与输出 token`maxTokens` 限制生成输出,`maxUses` 限制原生搜索次数。
#### KV Cache 影响
与会话请求 cache 相互独立。辅助指令与原生工具定义可以形成稳定前缀,但查询或模型路由的每次变化都会阻止从首个差异起的复用。
### 间接的会话工具结果
#### 模型看到的内容
通过 [`dsh-tool-web`](../tool-web/README.md),会话模型会看到结构化搜索块中去重后的 URL、标题、日期与引用 snippet提供方文本不会作为答案受到信任。该提供方的精确失败是 `DeepSeek search aborted``DeepSeek search request failed: <error>``DeepSeek returned no web_search_tool_result blocks; the request may not have triggered native web search``DeepSeek returned an unprocessable response body: <error>`HTTP 失败保留提供方消息。错误包装属于消费方。
#### Token 影响
注册不会直接产生会话 token。结果 token 随返回源与 snippet 增长,随后 seam 会强制执行请求的源数量上限。
#### KV Cache 影响
仅追加;新可见内容位于可复用请求前缀之后,不会使现有 KV-cache 配置项失效。
## 已知限制与暂缓事项
- **一次搜索需要完整的 Messages 模型轮次**:会产生延迟与生成 token并且最多执行 `maxUses` 次服务器侧搜索DeepSeek 不公开专用检索端点。
- **超量返回的源仍消耗 token**:协议没有结果数量旋钮,`maxResults` 只能由 seam 在事后截断。
- **未引用的结果没有 `snippet`**:只有 `text` 块中的引用(`cited_text`)匹配其 URL 时,源才会获得 snippet。
- **按错误形状分类中止**:只有 `DOMException` 且名为 `AbortError` 时才映射为 `WEB_ABORTED`;携带自定义原因的中止(例如 `dsh-timeout``TimeoutReason`)会呈现为 `WEB_PROVIDER_ERROR`

View File

@@ -0,0 +1,6 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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
README.md: c24f952eede90aae6fa23eec976255cb99625c19
README.zh.md: 39b6fb9ffc0ce9ba3291c17aa88781e90ed18e08

View File

@@ -1,5 +1,7 @@
# @deepseek-ai/dsh-web-search-exa
English | [中文](README.zh.md)
An [Exa](https://exa.ai)-backed `WebSearchProvider` for the harness [web capability seam](../web/README.md) (`ctx.web`). It calls Exa's `POST /search` endpoint with highlight contents and maps the flat `results[]` into the seam's normalized `WebSearchResult`.
This is an **implementation** package: it registers a provider into `ctx.web`, it does not own the `ctx.web` key and it does not register a model-facing tool (that is `@deepseek-ai/dsh-tool-web`). Like `@deepseek-ai/dsh-llm-deepseek`, it is a function/namespace plugin (`inject: ['web']`) that registers its backend, not a default-export service.

View File

@@ -0,0 +1,42 @@
# @deepseek-ai/dsh-web-search-exa
[English](README.md) | 中文
由 [Exa](https://exa.ai) 支持的 `WebSearchProvider`,用于 harness [web 能力 seam](../web/README.md)`ctx.web`)。它调用 Exa 的 `POST /search` 端点并请求 highlight 内容,把扁平 `results[]` 映射为 seam 规范化的 `WebSearchResult`
这是一个**实现** 包:它向 `ctx.web` 注册提供方,不拥有 `ctx.web` key也不注册面向模型的工具后者属于 `@deepseek-ai/dsh-tool-web`)。与 `@deepseek-ai/dsh-llm-deepseek` 一样它是函数namespace 插件(`inject: ['web']`),负责注册后端,而非默认导出服务。
## 配置
| Key | 默认值 | 含义 |
|---|---|---|
| `apiKey` | `$EXA_API_KEY` | Exa API key。为空缺失时提供方不可用。 |
| `baseURL` | `https://api.exa.ai` | 端点基址;追加 `/search`。无法解析时提供方不可用。 |
| `searchType` | `auto` | 以 Exa `type` 发送的检索模式:`auto`(由 Exa 决定)、`keyword``neural`。 |
| `numResults` | (未设置) | 请求不含 `maxResults` 时使用的默认结果数。未设置时不发送默认值。必须是正整数。 |
| `highlightsPerResult` | `1` | 每个结果请求的 highlight 句子数Exa `highlightsPerUrl`)。必须是正整数。 |
```yaml
- id: web-search-exa
name: '@deepseek-ai/dsh-web-search-exa'
config:
apiKey: !!js process.env.EXA_API_KEY
```
## 映射
Exa 返回扁平 `results[]`,不返回生成答案,因此省略 `content`。每项结果映射为 `WebSearchSource``url``url``title``title``snippet` ← 第一个非空 `highlights[]` 配置项(没有 highlight 的结果缺少可移植 snippet会被丢弃`publishedAt``publishedDate`。请求的 `maxResults` 优先于已配置的默认 `numResults`,并作为 Exa `numResults` 发送,以优化成本/延迟;最终边界由 seam 强制执行。提供方失败HTTP 错误、网络失败、无法解析或形状错误的主体)以 `WebError` `WEB_PROVIDER_ERROR` 呈现;中止请求以 `WEB_ABORTED` 呈现。HTTP 重定向会在接触 `Location` 目标前被拒绝,并以 `WEB_PROVIDER_ERROR` 呈现。
## 模型体验
通过 [`dsh-tool-web`](../tool-web/README.md) 间接影响;该工具保留此提供方经 `maxResults` 限制的 URL、标题、首条 highlight 与发布日期,或将精确的 `Exa search aborted``Exa search request failed: <error>``Exa returned an unprocessable response body: <error>` 失败置于消费方错误包装内;生成答案与提供方私有字段不进入上下文。
#### KV Cache 影响
不会直接失效;请求前缀变更由命名消费方负责。
## 已知限制与暂缓事项
- **没有非空 highlight 的结果会被整个丢弃**:没有可映射的可移植 snippet因此返回源可能少于请求数量。
- **只公开 `searchType``numResults``highlightsPerResult`**Exa 的其他控制项livecrawl、category、domain/date filter、全文内容等待提供方无关 seam 字段(见 [seam Agent Note](../../../.agents/notes/implemented/architecture/2026-06-24-web-capability-seam.md))。
- **按错误形状分类中止**:只有 `DOMException` 且名为 `AbortError` 时才映射为 `WEB_ABORTED`;携带自定义原因的中止(例如 `dsh-timeout``TimeoutReason`)会呈现为 `WEB_PROVIDER_ERROR`

View File

@@ -0,0 +1,6 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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
README.md: 80f6d34d63ddf0cc7d1f0d4f6744d64c91f9a269
README.zh.md: 2e631c11f99d9b24ba44fe1fe5f5238916ecc175

View File

@@ -1,5 +1,7 @@
# @deepseek-ai/dsh-web-search-perplexity
English | [中文](README.zh.md)
A [Perplexity](https://perplexity.ai)-backed `WebSearchProvider` for the harness [web capability seam](../web/README.md) (`ctx.web`). It calls Perplexity's OpenAI-compatible `POST /chat/completions` endpoint and maps the generated answer plus citations into the seam's normalized `WebSearchResult`.
This is an **implementation** package: it registers a provider into `ctx.web`, it does not own the key and it does not register a model-facing tool. Like `@deepseek-ai/dsh-llm-deepseek`, it is a function/namespace plugin (`inject: ['web']`). The OpenAI-compatible wire shape is a provider-private detail — it does **not** make this provider depend on `ctx.llm`.

View File

@@ -0,0 +1,65 @@
# @deepseek-ai/dsh-web-search-perplexity
[English](README.md) | 中文
由 [Perplexity](https://perplexity.ai) 支持的 `WebSearchProvider`,用于 harness [web 能力 seam](../web/README.md)`ctx.web`)。它调用 Perplexity 的 OpenAI 兼容 `POST /chat/completions` 端点,把生成答案与引用映射为 seam 规范化的 `WebSearchResult`
这是一个**实现** 包:它向 `ctx.web` 注册提供方,不拥有该 key也不注册面向模型的工具。与 `@deepseek-ai/dsh-llm-deepseek` 一样它是函数namespace 插件(`inject: ['web']`。OpenAI 兼容协议形状是提供方私有细节,并**不** 使该提供方依赖 `ctx.llm`
## 配置
| Key | 默认值 | 含义 |
|---|---|---|
| `apiKey` | `$PERPLEXITY_API_KEY` | Perplexity API key。为空缺失时提供方不可用。 |
| `baseURL` | `https://api.perplexity.ai` | 端点基址;追加 `/chat/completions`。无法解析时提供方不可用。 |
| `model` | `sonar` | 搜索模型名称。 |
| `maxTokens` | `1024` | 生成答案 token 上限(`max_tokens`)。必须是正整数。 |
| `searchRecency` | (未设置) | 以 `search_recency_filter` 发送的新近程度窗口:`day``week``month``year`。未设置时不发送 filter。 |
```yaml
- id: web-search-perplexity
name: '@deepseek-ai/dsh-web-search-perplexity'
config:
apiKey: !!js process.env.PERPLEXITY_API_KEY
```
## 映射
`content``choices[0].message.content`(生成答案)。`sources[]` 优先使用结构化 `search_results[]``url``title``snippet``publishedAt``date`),否则回退到只含 URL 的 `citations[]` 数组;仅当不存在 `search_results` 时才采取这条回退路径。这些源只携带 `url`,因此 seam 上的 `title``snippet``publishedAt` 是可选字段。提供方失败以 `WebError` `WEB_PROVIDER_ERROR` 呈现;中止请求以 `WEB_ABORTED` 呈现。HTTP 重定向会在接触 `Location` 目标前被拒绝,并以 `WEB_PROVIDER_ERROR` 呈现。Perplexity 没有结果数量控制,因此 seam 会强制执行 `maxResults`(截断 `sources[]` 并设置 `truncated`)。
## 模型体验
### 辅助 Perplexity 请求
#### 模型看到的内容
独立的 Perplexity 模型通过 chat-completions 端点接收逐字的 `<query>` 作为唯一 user 消息。该请求不属于会话模型上下文。
#### Token 影响
每次搜索会产生独立的提供方 token`maxTokens` 限制生成答案。
#### KV Cache 影响
与会话请求 cache 相互独立。同一模型路由下的相同查询可能复用提供方 cache查询或路由改变会建立不同前缀。
### 间接的会话工具结果
#### 模型看到的内容
通过 [`dsh-tool-web`](../tool-web/README.md),会话模型会看到生成答案及结构化结果元数据,或只含 URL 的引用。该提供方的精确失败是 `Perplexity search aborted``Perplexity search request failed: <error>``Perplexity returned an unprocessable response body: <error>`HTTP 失败保留提供方消息。错误包装属于消费方。
#### Token 影响
注册不会直接产生会话 token。答案与源 token 取决于数据,源数量受 seam 限制;保留的结果或错误会重复发送直到压缩。
#### KV Cache 影响
仅追加;新可见内容位于可复用请求前缀之后,不会使现有 KV-cache 配置项失效。
## 已知限制与暂缓事项
- **引用回退源只含 URL**Perplexity 省略结构化 `search_results[]` 时,源不含 `title``snippet``publishedAt`,因此工具只渲染裸 hostname label。
- **超量返回的源仍消耗 token 与延迟**:协议没有结果数量控制,`maxResults` 只能由 seam 在事后截断。
- **只公开 `model``maxTokens``searchRecency`**Perplexity 的其他搜索控制项domain filter、`web_search_options` 上下文大小、图片)等待提供方无关 seam 字段(见 [seam Agent Note](../../../.agents/notes/implemented/architecture/2026-06-24-web-capability-seam.md))。
- **按错误形状分类中止**:只有 `DOMException` 且名为 `AbortError` 时才映射为 `WEB_ABORTED`;携带自定义原因的中止(例如 `dsh-timeout``TimeoutReason`)会呈现为 `WEB_PROVIDER_ERROR`

View File

@@ -0,0 +1,6 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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
README.md: 471725f7368f480cfb255767376e3b1918bd68cf
README.zh.md: 2ed9c80682b2ff430ddd39662ea73cdf06374805

View File

@@ -1,5 +1,7 @@
# @deepseek-ai/dsh-web
English | [中文](README.zh.md)
The **web access seam**: an abstract `WebService` (`ctx.web`) defining WHAT web access the harness has — search the web, fetch a URL — over multiple providers, without binding the model contract to one vendor's API shape.
This package is the interface third of the web capability. Unlike bash/fs it spans two capabilities (search and fetch) on one seam, with potentially multiple providers each:

View File

@@ -0,0 +1,61 @@
# @deepseek-ai/dsh-web
[English](README.md) | 中文
**web 访问 seam**:抽象 `WebService``ctx.web`)定义 harness 具备哪些 web 访问能力(搜索 web、抓取 URL并通过多个提供方实现不把模型契约绑定到某个厂商的 API 形状。
该包是 web 能力中负责接口的三分之一。与 bash/fs 不同,它在一个 seam 上跨越搜索与抓取两种能力,每种能力都可能有多个提供方:
| 包 | 职责 |
|---|---|
| `@deepseek-ai/dsh-web`(本包) | 接口:服务、提供方注册表、选择策略、请求/结果词汇、`WebError` 分类体系 |
| `@deepseek-ai/dsh-web-search-exa` | 搜索实现Exa |
| `@deepseek-ai/dsh-web-search-perplexity` | 搜索实现Perplexity |
| `@deepseek-ai/dsh-web-fetch-local` | 抓取实现:匿名公共 HTTP(S) |
| `@deepseek-ai/dsh-tool-web` | 面向模型的 `web_search``web_fetch` 工具 schema构建于 `ctx.web` 之上 |
搜索与抓取没有共享请求 schema 或业务逻辑,但有意共用一个 seam`ctx.web` 是单一 web 访问中间层,拥有一项提供方选择策略、一套中止/错误词汇和一个面向产品的「该 harness 如何访问 web」配置表层。代价是成对的并行 `Search``Fetch` 方法;这种并行是有意设计,不是遗漏提取。
## 服务 API`ctx.web`
| 成员 | 语义 |
|---|---|
| `registerSearchProvider(provider)``registerFetchProvider(provider)` | 注册后端。同一能力 kind 下 id 重复时抛出 `WebError` `WEB_DUPLICATE_PROVIDER`。返回 disposer。随调用 fiber 释放。 |
| `search(request, signal?)` | 解析搜索提供方并运行一次搜索。在结果上强制执行 `request.maxResults`(截断 `sources[]`,设置 `truncated`)。能力无法运行时抛出 `WebError`。 |
| `fetch(request, signal?)` | 解析抓取提供方并获取一个 URL。非 2xx 响应是结果,不会抛出异常。无法安全获取或表示资源时抛出 `WebError`。 |
提供方注册的是**能力** 而非工具。`dsh-tool-web` 是面向模型名称、描述、提示词指引、JSON schema 和呈现的唯一 owner。
## 选择
选择绝不依赖注册、配置或 HMR 顺序。能力要么具有显式提供方 id配置 `searchProvider``fetchProvider`,或由环境变量 `$DSH_WEB_SEARCH_PROVIDER``$DSH_WEB_FETCH_PROVIDER` 提供相同字段),要么在恰好只注册一个可用提供方时自动选择。`search()``fetch()` 会在执行时解析提供方:
| 情况 | 执行 |
|---|---|
| 已配置 id 已注册且 `available()` | 运行该提供方 |
| 已配置 id 未注册 | `WEB_PROVIDER_CONFIGURED_MISSING` |
| 已配置 id 已注册但不可用 | `WEB_PROVIDER_CONFIGURED_UNAVAILABLE` |
| 无 id恰好一个已注册的可用提供方 | 运行该提供方 |
| 无 id没有可用提供方 | `WEB_PROVIDER_UNAVAILABLE` |
| 无 id多个可用提供方 | `WEB_PROVIDER_AMBIGUOUS` |
失败分支会抛出 `WebError`;调用方按其结构化 code加消息细节缺失 id、歧义候选集合路由。提供方自身的 `available()` 是便宜的局部检查credential 是否存在、配置是否可解析),供执行时选择使用,且**禁止发起网络调用**`dsh-tool-web` 永远不会调用它。工具通过 `ctx.web.search()``fetch()` 执行,并按抛出的 code 路由,因此提供方选择只有一个 owner。
## 词汇
`WebSearchRequest``query``maxResults?`)→ `WebSearchResult``content?``sources[]``truncated`);每个 `WebSearchSource` 都有必填 `url` 与可选 `title``snippet``publishedAt`Perplexity 引用可能只含 URL`WebFetchRequest``url`)→ `WebFetchResult`(最终 `url``statusCode``body``truncated`);取消作为可选的直接 `AbortSignal` 参数传给 `search()``fetch()``WebFetchBody` 是这里拥有的封闭判别联合(`html` | `text`);消费方使用 `switch` 实现穷尽检查,因此新增 kind 会破坏编译,直到处理完毕。完整契约见 `src/types.ts`,其中也包含 `WebError` code 分类体系。
## 模型体验
通过 `dsh-tool-web` 间接影响;该工具保留有界的规范化提供方数据,或精确的已配置提供方、提供方不可用、无提供方、多提供方及 `Error: <message>` 失败,本注册表自身不贡献提示词或 schema。
#### KV Cache 影响
不会直接失效;请求前缀变更由命名消费方负责。
## 已知限制与暂缓事项
- **没有观测表层**:没有提供方变更事件或能力状态查询;可用性只能通过执行 `search()``fetch()` 并按抛出的 `WebError` code 路由来观测,无提供方失败是通用的 `WEB_PROVIDER_UNAVAILABLE`,不会枚举逐提供方原因(见 [Agent Note](../../../.agents/notes/implemented/simplification/2026-07-04-drop-unconsumed-web-observation-surface.md))。
- **`WebSearchRequest` 只携带 `query` + `maxResults`**提供方无关的控制项新近程度、domain filter、区域提示、搜索深度暂缓至 Exa 与 Perplexity 都能诚实支持时(见 [seam Agent Note](../../../.agents/notes/implemented/architecture/2026-06-24-web-capability-seam.md))。
- **`WebFetchBody` 没有 `pdf` 分支**:可提取文本的 PDF 支持属于明确的暂缓工作;封闭联合会使新增该分支成为三个 web 包中由编译强制执行的变更。
- **提供方支持的页面提取不属于 `fetch()` 范围**Firecrawl/Tavily 风格的 `web_extract` 能力暂缓,而不会扩宽抓取 seam。