docs(i18n): re-translate cds/postmortem batch with the prompt-v4 pipeline

22 篇(core-data-structures 18、postmortem 3、rfc/README)译文按
v4 基线重出;机械核对零异常;rfc/README.zh 页内锚点按门禁规则改回
英文侧锚名。
This commit is contained in:
ZiyaZhang
2026-07-22 03:06:01 -07:00
parent 03e25be831
commit e38955b2fa
44 changed files with 299 additions and 299 deletions

View File

@@ -2,13 +2,13 @@
[English](tools.md) | 中文
[dsh-tools](../../packages/core/tools) 的工具流水线。[core.md](core.md) 介绍了 `ToolDefinition` 作为唯一被提升到主干的流水线编写类型,以及 `ToolSchema` 作为面向模型的协议格式wire format。本页拥有完整的 `ToolDefinition`、构建它的类型化 schema DSL、带守卫的执行形状,以及 UI 展示词汇。
[dsh-tools](../../packages/core/tools) 的工具流水线。[core.md](core.md) 介绍了 `ToolDefinition`唯一被提升到主干的流水线编写类型)和 `ToolSchema`面向模型的协议格式wire format形状)。本页拥有完整的 `ToolDefinition`用于构建它的类型化 schema DSL、受保护的执行形状,以及 UI 展示词汇。
源码:[`packages/core/tools/src/index.ts`](../../packages/core/tools/src/index.ts) · [`packages/core/tools/src/schema.ts`](../../packages/core/tools/src/schema.ts) · [`packages/core/tools/src/presentation.ts`](../../packages/core/tools/src/presentation.ts)
## `ToolDefinition`一个已注册的工具
## `ToolDefinition`一个已注册的工具
一个 `ToolSchema`(面向模型的字段)加上 `execute` 函数可选的 UI 展示器。注册表持有这些定义agent loop智能体循环通过它们分调用。注册表的 `schemas()` 通过显式白名单构建面向模型的 `ToolSchema[]``execute`/`presentCall`/`presentResult` 绝不能泄漏到模型请求中。
一个 `ToolSchema`(面向模型的字段)加上 `execute` 函数可选的 UI 展示器。注册表持有这些定义agent loop智能体循环通过它们分调用。注册表的 `schemas()` 通过显式白名单构建面向模型的 `ToolSchema[]`——`execute`/`presentCall`/`presentResult` 绝不能泄漏到模型请求中。
```ts type-equiv
interface ToolDefinition extends ToolSchema {
@@ -42,11 +42,11 @@ interface ToolDefinition extends ToolSchema {
}
```
`execute` 接收 `args: unknown`原始的 `ToolDefinition` 自行校验输入。第一方工具不需要手写校验;它们使用 `defineTool`,由后者代为校验收窄类型。
`execute` 接收 `args: unknown`——原始的 `ToolDefinition` 自行校验输入。第一方工具不需要手写校验;它们使用 `defineTool`,由后者代为校验收窄类型。
## 类型化 schema DSL
插件作者为每个属性编写带有布尔值 `required: true` 的规格,类型层面的辅助工具将规格映射为 `execute` 的参数类型——零类型断言。该 DSL 是为 `ToolDefinition` *提供类型*的机制;它有意作为子页面细节,不属于核心
插件作者为每个属性编写带有布尔值 `required: true` 的规格,类型层面的辅助工具将规格映射为 `execute` 的参数类型——零类型断言。该 DSL 是为 `ToolDefinition` 提供类型的*机制*;它有意作为子页面细节,而非核心内容
源码:[`packages/core/tools/src/schema.ts`](../../packages/core/tools/src/schema.ts)
@@ -72,7 +72,7 @@ interface SchemaProp {
type SchemaSpec = Record<string, SchemaProp>
```
`SchemaType` 是原始联合类型 `'string' | 'number' | 'boolean' | 'object' | 'array'`。`InferArgs<S>` 将一个 `SchemaSpec` 映射为 TS 参数类型`required: true` 的属性成为必选键,其余为真正的可选:
`SchemaType` 是原始联合类型 `'string' | 'number' | 'boolean' | 'object' | 'array'`。`InferArgs<S>` 将一个 `SchemaSpec` 映射为 TS 参数类型——`required: true` 的属性成为必选键,其余为真正的可选:
```ts type-equiv
type InferArgs<S extends SchemaSpec> = Simplify<
@@ -81,11 +81,11 @@ type InferArgs<S extends SchemaSpec> = Simplify<
>
```
`defineTool({ name, description, parameters, execute, … })` 将各部分串联:`parameters` 是一个 `SchemaSpec``execute(args, exec)` 得 `args: InferArgs<typeof parameters>`,辅助函数将规格转换为 JSON Schema`schemaSpecToJsonSchema`)用于协议传输,并在类型化函数体运行前校验模型生成的参数(`validateArgs`)。不匹配时抛出 `ToolArgsError``code: 'INVALID_ARGS'`),注册表将其转为 `isError` 结果以便模型自修正。为什么用自定义 DSL 而非 schemastery工具参数需要的是 JSON SchemaLLM大语言模型协议格式不是校验/转换——轻量 DSL 以最小面积提供最佳编写体验。
`defineTool({ name, description, parameters, execute, … })` 将各部分串联:`parameters` 是一个 `SchemaSpec``execute(args, exec)` 得 `args: InferArgs<typeof parameters>`,辅助函数将规格转换为 JSON Schema`schemaSpecToJsonSchema`)用于协议传输,并在类型化函数体运行前校验模型生成的参数(`validateArgs`)。校验不通过时抛出 `ToolArgsError``code: 'INVALID_ARGS'`),注册表将其转为 `isError` 结果以便模型自修正。为用自定义 DSL 而非 schemastery工具参数需要 JSON SchemaLLM大语言模型协议格式),而非校验/转换——轻量 DSL 以最小的接口面积提供最佳编写体验。
注册是受信的同进程契约。注册表以 readonly 方式借用类型化定义作为输入,仅校验语义要求(如 `timeoutMs` 必须为正有限值);`schemas()` 在模型边界处具象化显式的面向模型投影,使执行展示共享同一份已解析定义,而不会将回调泄漏到协议上。
注册是一个受信的同进程契约。注册表以 readonly 输入借用类型化定义,仅校验语义要求(如 `timeoutMs` 必须为正有限值);`schemas()` 在模型边界处化显式的面向模型投影,使执行展示共享同一份已解析定义,而不会将回调泄漏到协议上。
## `ToolRestriction`单个作用域的实时全局过滤器
## `ToolRestriction`单个作用域的实时全局过滤器
`ToolRestriction` 仅作用于实时的部署全局工具层。注册表将 readonly 名称编译为私有集合,对多个限制取交集,再叠加作用域本地工具。仅 deny 的过滤器允许后续未列出的全局工具通过,而 allow 列表则排除它们。
@@ -98,7 +98,7 @@ interface ToolRestriction {
## 执行:可扩展的 waterfall瀑布式事件加单调策略
`ctx.tools.execute()` 接调用方拥有的 `ToolExecutionInput`,将其解析后的 JSON 参数一次性具象化为流水线拥有的 `ToolExecution`,然后将该调用依次通过 `tools/pre-execute`(可重排的 allow/deny/ask waterfall→ 已注册的单调守卫 → `tools/execute`around-dispatch 包装层)→ `tools/post-execute`(检查/替换结果)→ `tools/result`(不可变的权威结果)。最终结果是一个 `ToolExecutionResult`。
`ctx.tools.execute()` 接调用方拥有的 `ToolExecutionInput`,将其解析后的 JSON 参数一次性化为流水线拥有的 `ToolExecution`,然后依次通过 `tools/pre-execute`(可重排的 allow/deny/ask waterfall→ 已注册的单调 guard → `tools/execute`around-dispatch 包装层)→ `tools/post-execute`(检查/替换结果)→ `tools/result`(不可变的权威结果)。最终产出为 `ToolExecutionResult`。
```ts type-equiv
type ToolExecutionToken = symbol & { readonly [toolExecutionTokenBrand]: true }
@@ -129,9 +129,9 @@ interface ToolExecution extends ToolExecutionInput {
}
```
`ToolExecutionToken` 是一个不透明的运行时 `Symbol`,仅用于身份比较。在策略执行之前,`execute()` 具象化并冻结参数、拒绝非 JSON 输入、分配 token。身份字段和可选的 parent token 保持 readonly只有 `signal` 可在 dispatch 前后变化。最终观察者接收到的是冻结的执行身份。
`ToolExecutionToken` 是一个不透明的运行时 `Symbol`,仅用于身份比较。在策略执行之前,`execute()` 化并冻结参数、拒绝非 JSON 输入、分配 token。身份字段和可选的 parent token 保持 readonly只有 `signal` 可以在分派前后变化。最终观察者接收到的是冻结的执行身份。
`ToolGuard` 是感知作用域的最终 pre-dispatch 策略。其形状有意不包含 allow 结果:`undefined` 保留 waterfall 的决策,而返回的 reason 只能缩减权限,因此后续监听器无法撤销它。
`ToolGuard` 是感知作用域的最终预分派策略。其形状有意不包含 allow 结果:`undefined` 保留 waterfall 的决策,而返回的 reason 只能缩减权限,因此后续监听器无法撤销它。
```ts type-equiv
type ToolGuard = (execution: Readonly<ToolExecution>) => string | undefined
@@ -168,9 +168,9 @@ interface ToolExecutionResult {
}
```
结果仅承载结果本身。调用身份保留在不可变的 `ToolExecution` 上,后者伴随结果过每个钩子,也保留在持久化的 `tool/call` / `tool/result` 会话事件上,因此包装层无法创建第二个相互矛盾的身份。
结果仅承载产出。调用身份保留在不可变的 `ToolExecution` 上,后者伴随结果过每个钩子,并出现在持久化的 `tool/call` / `tool/result` 会话事件上,因此包装层无法创建第二个相互矛盾的身份。
注册表在 `tools/result` 之前立即具象化并冻结最终接受的结果。其 content、结构化错误、附加上下文和展示元数据必须通过 JSON 无损往返;无效结果会被转为 JSON 安全的 `isError` 结果,确保被观察到的实时结果对后续持久化的 `tool/result` 追加是安全的。
注册表在 `tools/result` 之前立即化并冻结最终接受的结果。其内容、结构化错误、附加上下文和展示元数据必须通过 JSON 无损往返;无效的产出会被转为 JSON 安全的 `isError` 结果,从而保证被观察到的实时产出对后续持久化的 `tool/result` 追加是安全的。
每个拦截 waterfall 返回一个类型化的 **Decision**(与 `agent/*` seam 共享的惯用模式)。`tools/pre-execute` 监听器接收 `(exec, next)` 并返回 `PreToolDecision``tools/execute` 包装层返回 `ToolExecutionResult``tools/post-execute` 监听器接收 `(exec, result, next)` 并返回 `PostToolDecision`
@@ -187,13 +187,13 @@ type PostToolDecision =
| { kind: 'block'; feedback: ContentBlock[]; additionalContext?: HookContext }
```
调用 `next()` 走默认路径,或返回 decision 以短路。Pre-policy 可以 deny 或 ask只有 `allowed-once` 才继续执行,而 non-grant、缺少审批通道或服务、或无 agent 的请求都会变为 denial。守卫仍可施加最终 denial。参数不可被改写因为历史记录、审计、UI 和执行必须一致。
调用 `next()` 获取默认决策,或直接返回一个决策以短路。前置策略可以 deny 或 ask只有 `allowed-once` 才继续执行,而未授权、缺少审批通道或服务、或无 agent 的请求都会变为拒绝。Guard 仍可施加最终拒绝。参数不可被改写因为历史记录、审计、UI 和执行必须保持一致。
Post-policy 可以替换 contentblock 会变为包含纠正反馈的 `isError` 结果。`tools/result` 在归一化后接收冻结的执行和结果;观察者无法转换它们,观察者的失败被隔离。未知工具和抛出异常的工具都变为结构化错误(`ToolNotFoundError` 映射为 `UNKNOWN_TOOL`),调用失败但不终止当前轮次。
后置策略可以替换内容block 会变为包含纠正反馈的 `isError` 结果。`tools/result` 在归一化后接收冻结的执行和结果;观察者无法对其进行变换,观察者的失败也会被隔离。未知工具和抛出异常的工具都变为结构化错误(`ToolNotFoundError` 映射为 `UNKNOWN_TOOL`),调用失败但不终止当前轮次。
## 结构化输出 schema 子集
调用方用来向 subagent 要求机器可读结果的词汇(`SubagentStartRequest.outputSchema`,见 [subagent.md](subagent.md#the-start-request)),或工作流 `agent()` 调用使用的词汇。它有意**不是**完整的 JSON Schemaschema 原样传给模型作为强制工具的 `parameters`,产出的值由客户端的 `validateStructuredValue` 校验——因此每个被接受的关键字都必须是校验器实际执行的,`assertSupportedOutputSchema` 会大声拒绝其他任何内容(`OutputSchemaError`,列出所有违规)。两个遍历器都只处理自有可枚举属性JSON 不携带其他东西),并拒绝会有损序列化的非普通对象(`Date`、`Map`)。
调用方用来向 subagent 要求机器可读结果的词汇(`SubagentStartRequest.outputSchema`,见 [subagent.md](subagent.md#the-start-request)),或工作流 `agent()` 调用使用的词汇。它有意**不是**完整的 JSON Schemaschema 原样传给模型作为强制工具的 `parameters`,产出的值由 `validateStructuredValue` 在客户端校验——因此每个被接受的关键字都必须是校验器实际执行的,`assertSupportedOutputSchema` 会大声拒绝其他任何内容(`OutputSchemaError`,列出所有违规)。两个遍历器仅推理自有可枚举属性JSON 不携带其他内容),并拒绝会有损序列化的非对象(`Date`、`Map`)。
```ts type-equiv
type StructuredScalar = string | number | boolean | null
@@ -219,7 +219,7 @@ interface StructuredSchemaNode {
}
```
schema 是一个以 object 为根的节点(`enum`/`const` 仅限标量;`description`/`title`/`default`/`examples` 是注解,允许但忽略,仍要求为 JSON 数据——它们随协议传输):
schema 是一个以 object 为根的节点(`enum`/`const` 仅限标量;`description`/`title`/`default`/`examples` 是注解,允许但忽略,仍要求为 JSON 数据——它们随协议传输):
```ts type-equiv
type StructuredOutputSchema = StructuredSchemaNode & { type: 'object' }
@@ -227,11 +227,11 @@ type StructuredOutputSchema = StructuredSchemaNode & { type: 'object' }
## 工具展示 UI 词汇
工具希望其调用在 UI 中如何呈现编辑器工具调用卡片、CLI 日志行),提供方无关,使工具无需依赖任何客户端协议即可描述自身。`presentCall`/`presentResult` 返回一个 **`card` 标签的渲染意图**——一个可辨识联合类型UI 桥接层据此分发:
工具希望其调用在 UI 中如何呈现编辑器工具调用卡片、CLI 日志行),提供方无关,使工具在不依赖任何客户端协议的情况下描述自身。`presentCall`/`presentResult` 返回一个 **`card` 标签的渲染意图**——一个可辨识联合类型UI 桥接层据此分发:
- `ToolCallView`pending 状态`{ card: 'generic', title, kind?, rawInput?, content?, locations? }`(默认卡片;`locations` 是 `{ path, line? }[]`,表示调用读取/修改的文件,供编辑器跟随定位)、`{ card: 'terminal', title, description?, cwd? }`shell 命令终端卡片)、或 `{ card: 'diff', title, diffs, locations? }`(文件创建/修改 → 内联 diff 卡片;`diffs` 是 `{ path, oldText, newText }[]``oldText: null` 表示新文件)。
- `ToolResultView`completed 状态`{ card: 'generic', title?, content? }`、`{ card: 'terminal', title?, output?, exitCode?, signal? }`(捕获的运行输出 + 退出状态;有能力的 UI 显示退出状态标签,无能力的 UI 获得桥接层从 `output` 派生的围栏 ` ```console ` 回退)、或 `{ card: 'diff', title?, diffs }`(已完成的文件变更要展示的变更,通常是从 before/after 内容计算出带上下文行的已应用 hunk或在没有 before-image 时的整文件 diff——如文件创建。`tool_call_update` content 会**替换**调用的 content,因此变更工具即使与调用时的片段重复也要返回此,以防结果文本覆盖 diff
- `ToolCallView`待执行`{ card: 'generic', title, kind?, rawInput?, content?, locations? }`(默认卡片;`locations` 是 `{ path, line? }[]`,表示调用读取/修改的文件,供编辑器跟随)、`{ card: 'terminal', title, description?, cwd? }`shell 命令终端卡片)、或 `{ card: 'diff', title, diffs, locations? }`(文件创建/修改→行内 diff 卡片;`diffs` 是 `{ path, oldText, newText }[]`新文件时 `oldText: null`)。
- `ToolResultView`已完成`{ card: 'generic', title?, content? }`、`{ card: 'terminal', title?, output?, exitCode?, signal? }`(捕获的运行输出 + 退出状态;有能力的 UI 显示退出状态标签,无能力的 UI 获得桥接层从 `output` 派生的围栏 ` ```console ` 回退)、或 `{ card: 'diff', title?, diffs }`(已完成的文件变更要展示的变更,通常是从变更前后内容计算出带上下文行的已应用 hunk或在没有前像时的整文件 diff——如文件创建。`tool_call_update`内容会**替换**调用的内容,因此变更工具即使与调用时的片段重复也要返回此卡片,以防结果文本覆盖 diff
`ToolCallKind``'read' | 'edit' | 'delete' | 'move' | 'search' | 'execute' | 'fetch' | 'other'`)为 generic 卡片选择图标。`FileLocation``{ path, line? }`)和 `FileDiff``{ path, oldText, newText }`)是共享的文件卡片词汇。该设计固定[渲染意图联合类型 RFC](../rfc/implemented/architecture/2026-07-02-tool-render-intent-union.md)ACPAgent Client Protocol桥接层将 `diff` 卡片映射为 `{ type: 'diff' }` 内容块,将 `terminal` 卡片映射为 `_meta` 终端约定,并将文件卡片的标题相对于会话 cwd 做相对化处理。
`ToolCallKind``'read' | 'edit' | 'delete' | 'move' | 'search' | 'execute' | 'fetch' | 'other'`)为 generic 卡片选择图标。`FileLocation``{ path, line? }`)和 `FileDiff``{ path, oldText, newText }`)是共享的文件卡片词汇。该设计固定[渲染意图联合类型 RFC](../rfc/implemented/architecture/2026-07-02-tool-render-intent-union.md)ACP 桥接层将 `diff` 卡片映射为 `{ type: 'diff' }` 内容块,将 `terminal` 卡片映射为 `_meta` 终端约定,并将文件卡片的标题相对于会话 cwd 做相对化处理。
完整的展示字段文档见 [`packages/core/tools/src/presentation.ts`](../../packages/core/tools/src/presentation.ts)。bash 工具自身的 schema`bash`/`bash_output`/`bash_kill`)及其驱动的执行器见 [bash.md](bash.md)。