docs: translate remaining non-README documentation

This commit is contained in:
Tianyi Cui
2026-07-26 02:33:29 +08:00
parent 5f04c92f15
commit 30db52fa4b
102 changed files with 3859 additions and 82 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
commands.md: 056c775f4c2e1586447db11821e5c7d56be01881
commands.zh.md: 1a51305df356d8becf8c5517704dc375cdb8b585

View File

@@ -1,5 +1,7 @@
# Human Commands
English | [中文](commands.zh.md)
The human-command seam of [`dsh-commands`](../../packages/ui/commands). Interactive adapters use it to discover and directly execute plugin-owned commands for an exact agent without creating a model message. The [command Agent Note](../../.agents/notes/implemented/feature/2026-07-19-plugin-command-registration.md) owns dispatch and lifecycle rationale; the [package README](../../packages/ui/commands/README.md) owns composition and limitations.
Source: [`packages/ui/commands/src/index.ts`](../../packages/ui/commands/src/index.ts)

View File

@@ -0,0 +1,86 @@
# 用户命令
[English](commands.md) | 中文
[`dsh-commands`](../../packages/ui/commands) 的用户命令 seam。交互式适配器用它发现插件拥有的命令并针对确切的 agent智能体直接执行这些命令而不创建模型消息。[命令 Agent Noteagent 决策记录)](../../.agents/notes/implemented/feature/2026-07-19-plugin-command-registration.md) 负责分发与生命周期的决策依据;[packageREADME](../../packages/ui/commands/README.md) 负责组合方式与限制。
来源:[`packages/ui/commands/src/index.ts`](../../packages/ui/commands/src/index.ts)
## 输入元数据
该 seam 公开一个可选的非结构化输入提示。命令的可用性由插件组合决定:每个消费注册表的适配器都会看到全部生效定义。
```ts type-equiv
/** Immutable metadata for a command's optional unstructured input. */
interface CommandInputDescriptor {
/** Placeholder shown before the user supplies free-form input. */
readonly hint: string
}
```
## 定义
`CommandDefinition` 是由插件编写的注册定义。注册表会验证并冻结一份与原始注册对象脱离的生效定义。
```ts type-equiv
/** Plugin-owned command registration. */
interface CommandDefinition {
/** Lowercase command name without the leading slash. */
readonly name: string
/** Human-readable summary used in discovery UI. */
readonly description: string
/** Optional free-form input hint advertised to capable clients. */
readonly input?: CommandInputDescriptor
/** Execute against the receiving agent without sending the command to the model. */
readonly handler: (invocation: CommandInvocation) => CommandResult | Promise<CommandResult>
}
```
## 调用与结果
适配器拥有取消操作,并传入确切的目标 agent。`rawInput` 紧接在解析后的名称之后,并保留适配器传入的分隔符与后缀。结果会直接呈现给 UI而不是工具结果或会话事件。
```ts type-equiv
/** Invocation passed to one registered command handler. */
interface CommandInvocation {
/** Exact agent whose human-facing surface received the command. */
readonly agent: Agent
/** Exact text following the registered command name, including separator whitespace. */
readonly rawInput: string
/** Cancellation signal owned by the dispatching UI request. */
readonly signal: AbortSignal
}
```
```ts type-equiv
/** Expected command outcome rendered directly by the dispatching UI. */
type CommandResult =
| { readonly kind: 'success'; readonly text?: string }
| { readonly kind: 'error'; readonly text: string }
```
## 发现与解析视图
作用域解析后,适配器会获得不含处理器的不可变描述符。`parseCommand()` 在注册表解析前返回 `ParsedCommand`;语法有效的输入仍可能指向不可用的命令。
```ts type-equiv
/** Handler-free immutable command view returned to UI adapters. */
interface CommandDescriptor {
/** Lowercase command name without the leading slash. */
readonly name: string
/** Human-readable summary used in discovery UI. */
readonly description: string
/** Optional free-form input hint advertised to capable clients. */
readonly input?: CommandInputDescriptor
}
```
```ts type-equiv
/** Syntactically valid slash command before registry resolution. */
interface ParsedCommand {
/** Lowercase command name without the leading slash. */
readonly name: string
/** Exact text following the command name. */
readonly rawInput: string
}
```

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
goal.md: 2e8d296eeda6e5f69c0f92829e347b7f55f41fa9
goal.zh.md: a9c946e7cd37cf948c7ac0f3e4d0ea35ac80d614

View File

@@ -1,5 +1,7 @@
# Same-session goals
English | [中文](goal.zh.md)
Types shared by the event-sourced goal domain and its policy consumers. The [goal-domain Agent Note](../../.agents/notes/implemented/feature/2026-07-19-persisted-same-session-goal-domain.md) owns the persistence and activation decisions; this page records the literal shapes from [`packages/goal/goal/src/types.ts`](../../packages/goal/goal/src/types.ts).
## Identity and lifecycle

View File

@@ -0,0 +1,145 @@
# 同会话目标
[English](goal.md) | 中文
事件溯源目标领域及其策略消费方共享的类型。[目标领域 Agent Noteagent 决策记录)](../../.agents/notes/implemented/feature/2026-07-19-persisted-same-session-goal-domain.md)负责记录持久化与激活决策;本页记录 [`packages/goal/goal/src/types.ts`](../../packages/goal/goal/src/types.ts) 中的字面形态。
## 标识与生命周期
`GoalId` 是[品牌化 id](core.md#branded-ids)。调用方通过 `GoalRef` 修改一个确切修订版本;每次获准的持久变更都会递增修订号。
```ts type-equiv
/** Compare-and-set identity for one exact goal revision. */
interface GoalRef {
/** Stable goal identity. */
readonly id: GoalId
/** Positive revision; every durable mutation increments it. */
readonly revision: number
}
```
持久阶段回答目标发生了什么。进程本地激活状态则另行回答续跑消费方能否开始另一个 Round。
```ts type-equiv
/** Durable continuation phase. Activation is process-local and separate. */
type GoalPhase =
| 'active'
| 'paused'
| 'blocked'
| 'complete'
```
阻塞是唯一表示「因问题而停止」的持久状态。由策略负责的阻塞原因会携带一个用于路由、稳定且采用 lower-kebab-case 的代码,以及一段供人和模型阅读的自由文本说明。
```ts type-equiv
/** Machine-routable and human-readable explanation for a blocked goal. */
interface GoalBlockReason {
/** Stable lower-kebab-case classification chosen by the blocking policy. */
readonly code: string
/** Non-empty explanation shown to humans and models. */
readonly message: string
}
```
```ts type-equiv
/** Full durable state written by every non-clear goal mutation. */
interface GoalSnapshot extends GoalRef {
/** Human-requested completion objective. */
readonly objective: string
/** Durable lifecycle phase. */
readonly phase: GoalPhase
/** Present exactly while `phase` is `blocked`. */
readonly blockedReason?: GoalBlockReason
/** Total admitted goal-round cap. */
readonly maxGoalRounds: number
}
```
```ts type-equiv
/** Current goal projection, including values derived from the session log. */
interface GoalView extends GoalSnapshot {
/** Highest admitted round number for this goal. */
readonly roundsStarted: number
/** Epoch milliseconds of the create mutation. */
readonly createdAt: number
/** Epoch milliseconds of the latest mutation. */
readonly updatedAt: number
/** Process-local continuation eligibility; never persisted. */
readonly activation: GoalActivation
}
```
## 持久变更
每次变更都是 Round 编号为 0、来源为目标的 `user/message`,其元数据要么是完整快照,要么是清除墓碑。版本、元数据、目标来源和逐字渲染内容共同构成一项回放不变量。
```ts type-equiv
/** Full-snapshot goal mutation retained in a model-visible context event. */
interface GoalSnapshotChangeMeta {
readonly kind: 'goal/change'
readonly version: 1
readonly operation: Exclude<GoalOperation, 'clear'>
readonly goal: GoalSnapshot
readonly roundsStarted: number
readonly createdAt: number
readonly updatedAt: number
}
```
```ts type-equiv
/** Tombstone retained when the current goal is cleared. */
interface GoalClearChangeMeta {
readonly kind: 'goal/change'
readonly version: 1
readonly operation: 'clear'
readonly cleared: GoalRef
readonly clearedAt: number
}
```
目标状态变更使用 Round `0`。续跑消费方会为每个获准的用户消息轮次标注正数且连续的 Round 编号和当前修订号;回放会拒绝编号缺口、陈旧修订号、已停止阶段和超出上限。
```ts type-equiv
/** Message attribution for durable goal state and continuation rounds. */
interface GoalMessageSource {
readonly kind: 'goal'
readonly goalId: GoalId
readonly revision: number
/** Zero for state changes; positive for admitted continuation rounds. */
readonly round: number
}
```
## 请求与通知
创建操作会区分调用方省略的值与部署选择,`create()` 会在内部解析后者。编辑是局部替换,其运行时校验器要求至少提供一个字段。每条变更通知都会携带获准的操作和确切修订号;清除操作不带 `goal`。
```ts type-equiv
/** Input whose omitted round cap is resolved by the service configuration. */
interface CreateGoalRequest {
readonly objective: string
readonly maxGoalRounds?: number
}
```
```ts type-equiv
/** Fields changed by an edit; at least one must be present. */
interface EditGoalRequest {
readonly objective?: string
readonly maxGoalRounds?: number
}
```
```ts type-equiv
/** Live notification after one goal mutation has been accepted for logging. */
interface GoalChanged {
readonly operation: GoalOperation
readonly ref: GoalRef
/** Absent for a clear tombstone. */
readonly goal?: GoalView
}
```
## 服务行为
[`GoalService`](../../packages/goal/goal/src/index.ts) 解析创建默认值、执行严格回放折叠、校验确切的活跃 agent 身份、以比较并设置方式执行变更、叠加延迟注入,并发出 `goal/changed` 通知;监听器故障会被隔离。包 [README](../../packages/goal/goal/README.md) 负责记录可调用契约和面向模型的契约。

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
lsp.md: 62b133cbfdf521e067c56355664d7514a613397f
lsp.zh.md: d7000970ec9114bcdad40a39d2712d48b9865529

View File

@@ -1,5 +1,7 @@
# LSP navigation
English | [中文](lsp.zh.md)
The LSP seam — a [capability seam](../../.agents/notes/implemented/architecture/2026-07-15-lsp-capability-seam.md) exposing semantic code navigation on one `ctx.lsp` service, split across packages: interface ([dsh-lsp](../../packages/lsp/lsp), `ctx.lsp` + the provider registry), a generic implementation ([dsh-lsp-local](../../packages/lsp/lsp-local), a configured stdio language-server host), and consumer ([dsh-tool-lsp](../../packages/lsp/tool-lsp), the `lsp` tool schema). LSP is **one optional capability**, not part of the agent-loop spine — so its vocabulary lives here, not in [core.md](core.md). A provider swap does not change how the model asks for navigation.
Source: [`packages/lsp/lsp/src/types.ts`](../../packages/lsp/lsp/src/types.ts)

View File

@@ -0,0 +1,165 @@
# LSP 导航
[English](lsp.md) | 中文
LSP seam 是一个[能力 seam](../../.agents/notes/implemented/architecture/2026-07-15-lsp-capability-seam.md):它在单一 `ctx.lsp` 服务上公开语义代码导航并拆分到多个包package接口[dsh-lsp](../../packages/lsp/lsp)`ctx.lsp` + 提供方注册表)、通用实现([dsh-lsp-local](../../packages/lsp/lsp-local),经过配置的 stdio 语言服务器宿主)和消费方([dsh-tool-lsp](../../packages/lsp/tool-lsp),即 `lsp` 工具 schema。LSP 是**一项可选能力**,不属于 agent loop智能体循环主干因此其词汇定义在此而非 [core.md](core.md) 中。更换提供方不会改变模型请求导航的方式。
源文件:[`packages/lsp/lsp/src/types.ts`](../../packages/lsp/lsp/src/types.ts)
## 操作与坐标
seam 与模型恰好公开 4 项语义查询;该联合是闭合的,因此新增一项查询会通过编译强制要求同步修改 seam、提供方和工具。位置与范围采用从零开始的 UTF-16 坐标,与协议一致;面向模型的工具采用从 1 开始的光标约定,并在输入和输出时进行转换。
```ts type-equiv
/**
* The four semantic queries the seam and model expose. A closed union: adding an operation is a
* compile-enforced change across the seam, providers, and the tool. Symbols and call hierarchy are
* deliberately deferred (they need different schemas).
*/
type LspOperation = 'goToDefinition' | 'findReferences' | 'goToImplementation' | 'hover'
```
```ts type-equiv
/** A zero-based UTF-16 cursor coordinate, matching the LSP wire convention. */
interface LspPosition {
/** Zero-based line. */
readonly line: number
/** Zero-based UTF-16 code-unit offset within the line. */
readonly character: number
}
```
```ts type-equiv
/** A zero-based UTF-16 half-open range `[start, end)`. */
interface LspRange {
readonly start: LspPosition
readonly end: LspPosition
}
```
## 请求
每个字段都是必填项:`workspaceRoot` 由调用方提供,`languageId` 来自提供方注册而非请求,超时与结果上限由消费方决定。因此没有字段需要由实现提供默认值,也不存在 `resolve()` 步骤。提供方收到调用方请求和派生的 `languageId`;后者只用于同步瞬态文档,从不参与选择。
```ts type-equiv
/**
* A caller's normalized query. Every field is required: `workspaceRoot` is caller-supplied,
* `languageId` comes from the provider registration (not here), and consumers own timeouts and
* result limits — so no field needs implementation defaulting and there is no `resolve()` step.
*/
interface LspQueryRequest {
/** Which semantic query to run. */
readonly operation: LspOperation
/** The source file to query (relative to `workspaceRoot` or absolute; the provider canonicalizes). */
readonly filePath: string
/** The zero-based UTF-16 cursor position to query at. */
readonly position: LspPosition
/** The workspace root the provider resolves against and indexes; required, never defaulted. */
readonly workspaceRoot: string
}
```
```ts type-equiv
/**
* A request as a provider receives it: the caller's {@link LspQueryRequest} plus the `languageId`
* the seam derived from the provider's extension mapping. The language id only synchronizes the
* transient document; it does not participate in selection.
*/
interface LspProviderQuery extends LspQueryRequest {
/** The LSP language id for `filePath`, from this provider's extension mapping. */
readonly languageId: string
}
```
## 结果
这是一个闭合的可辨识联合:导航操作规范化为 `locations``hover` 规范化为内容或 `null`。消费方使用 `switch` 对 `kind` 做穷尽处理,因此新增分支会使编译失败,直到完成处理。`findReferences` 始终包含声明;提供方在内部强制保证这一点,因此调用方没有对应 flag。`locations` 变体携带 `resolvedWorkspaceRoot`,即提供方对请求中 `workspaceRoot` 的规范形式,也是其 `file:` URI 所相对的根目录;调用方在相对化显示路径时应使用它,而不是可能经过符号链接的请求根目录。
```ts type-equiv
/** One resolved location: a document URI and the range within it. */
interface LspLocation {
/** The target document URI (`file:` or otherwise), verbatim from the server. */
readonly uri: string
/** The range within the target document. */
readonly range: LspRange
}
```
```ts type-equiv
/** Normalized hover content, or `null` for no hover at the position. */
interface LspHover {
/** The normalized hover text (markdown or plaintext, provider-joined). */
readonly contents: string
/** The range the hover applies to, when the server supplied one. */
readonly range?: LspRange
}
```
```ts type-equiv
/**
* The closed result union. Navigation operations (`goToDefinition`, `findReferences`,
* `goToImplementation`) normalize to `locations`; `hover` normalizes to content or `null`.
* Consumers `switch` on `kind` to exhaustiveness so a new arm breaks compilation until handled.
*
* The `locations` variant carries `resolvedWorkspaceRoot`: the provider's canonical form of the
* request's `workspaceRoot`, and the root its `file:` location URIs are relative to. A caller that
* relativizes display paths MUST use this, not the request's (possibly symlinked) `workspaceRoot`;
* otherwise a symlinked workspace misclassifies in-workspace results as external.
*/
type LspQueryResult =
| { readonly kind: 'locations'; readonly locations: readonly LspLocation[]; readonly resolvedWorkspaceRoot: string }
| { readonly kind: 'hover'; readonly hover: LspHover | null }
```
## 提供方与服务
每个提供方拥有一个稳定的品牌化 `id`,以及一份互斥的、小写且以点开头的扩展名映射。`registerProvider` 会原子保留 id 和每个扩展名:注册无效或冲突时不发布任何内容;其 disposer 会释放所有保留项。每次查询独立选择提供方,且选择与顺序无关;没有匹配项时抛出 `LspError` `LSP_UNAVAILABLE`。该 seam 不公开协议类型、进程或文档控制,也不提供通用 JSON-RPC 逃生口。
```ts type-equiv
/**
* A language-server backend registered on `ctx.lsp`. Each provider owns a stable {@link
* LspProviderId} and an extension-to-language-id map (lowercase, leading-dot keys).
* `findReferences` always includes declarations — the provider enforces this internally; callers
* get no flag.
*/
interface LspProvider {
/** Stable provider identity, reserved atomically with the extension mappings. */
readonly id: LspProviderId
/** Lowercase leading-dot extension → LSP language id (e.g. `{ '.ts': 'typescript' }`). */
readonly extensionToLanguage: Readonly<Record<string, string>>
/**
* Run one query. The seam has already selected this provider and derived `languageId`.
* @param request - the resolved provider query (caller request + derived language id).
* @param signal - optional cancellation; the provider stops its own work when it aborts.
* @returns the normalized, closed-union result.
*/
query(request: LspProviderQuery, signal?: AbortSignal): Promise<LspQueryResult>
}
```
```ts type-equiv
/**
* The LSP capability seam (`ctx.lsp`). Owns provider registration/selection and normalized query
* execution; exposes exactly the four operations and no protocol escape hatch.
*/
interface LspService {
/**
* Register a provider, atomically reserving its id and every normalized extension. Any conflict
* or invalid input publishes nothing and throws `LspError`; the returned disposer releases all
* reservations. Disposed with the calling fiber.
* @param provider - the backend to register.
* @returns a synchronous disposer releasing the id and all extension reservations.
*/
registerProvider(provider: LspProvider): () => void
/**
* Select a provider by the file's extension and run one query. Selection is per-query and
* order-independent; no match throws `LspError` `LSP_UNAVAILABLE`.
* @param request - the normalized query.
* @param signal - optional cancellation forwarded to the selected provider.
* @returns the normalized, closed-union result.
*/
query(request: LspQueryRequest, signal?: AbortSignal): Promise<LspQueryResult>
}
```
`LspProviderId` 是该 seam 的品牌化 id来自 [dsh-brand](../../packages/util/brand) 的 `Branded<'LspProviderId'>``LspError` 扩展 `HarnessError`,提供 `LSP_INVALID_PROVIDER`、`LSP_CONFLICT`、`LSP_UNAVAILABLE`、`LSP_DISPOSED`、`LSP_UNSUPPORTED_OPERATION` 和 `LSP_MALFORMED_RESPONSE` 等稳定错误码,调用方应按错误码路由,而不是解析 `message`。

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
pty.md: 97e1e662d1128ab0555e34f8284cf69d7d9d0d1a
pty.zh.md: b17bc0d2c7bdb2a980df36824bd360ea975967f5

View File

@@ -1,5 +1,7 @@
# Persistent PTY Sessions
English | [中文](pty.zh.md)
Types shared by PTY backends, `ctx.pty`, and the model-facing consumer. The [persistent PTY Agent Note](../../.agents/notes/implemented/feature/2026-07-16-persistent-pty-sessions.md) owns the rationale; this page records the cross-package vocabulary from [`packages/pty/pty/src/types.ts`](../../packages/pty/pty/src/types.ts).
## Identity and readiness

View File

@@ -0,0 +1,91 @@
# 持久 PTY 会话
[English](pty.md) | 中文
PTY 后端、`ctx.pty` 与面向模型的消费方共享的类型。[持久 PTY Agent Noteagent 决策记录)](../../.agents/notes/implemented/feature/2026-07-16-persistent-pty-sessions.md) 负责记录决策依据;本页记录来自 [`packages/pty/pty/src/types.ts`](../../packages/pty/pty/src/types.ts) 的跨包package词汇。
## 标识与就绪
`PtySessionId` 是由服务铸造的品牌化 id。可选名称是拥有者本地的显示元数据授权比较的是确切的所属 `Agent`,而不是名称或猜测的 id。
`PtyWaitReason` 说明一次发送为何返回。它与 `PtySessionStatus` 无关:一次发送可能因静默或超时而返回,但顶层 shell 仍然存活;`session_exit` 表示该 shell 已退出,而不是某个任意的前台子进程已退出。
```ts type-equiv
/** Why one interactive send returned control to its caller. */
type PtyWaitReason = 'stdin_read' | 'inferred_idle' | 'timeout' | 'session_exit'
```
```ts type-equiv
/** Top-level PTY process status, independent of a send's wait reason. */
type PtySessionStatus =
| { kind: 'running' }
| { kind: 'exited'; exitCode: number | null; signal: NodeJS.Signals | null }
```
## 后端与活跃会话
后端负责某个已注册类型的启动方式和就绪检测。`PtyService` 只在初始化成功后才发布返回的会话,随后负责 id 授权与清理。无法清理部分启动资源的后端会以 `PtyBackendCleanupError` 拒绝,从而让资源释放流程保留该清理失败,同时不替换调用方的取消原因。后端会话拥有终端状态,并负责使已捕获资源完全停稳。
```ts type-equiv
/** Replaceable provider for one PTY session type. */
interface PtyBackend {
/** Stable type selected by {@link PtySpawnRequest.type}. */
readonly type: string
/** Create an unpublished session or reject after cleaning partial resources; cleanup failure uses {@link PtyBackendCleanupError}. */
spawn(spec: PtyBackendSpawnSpec): Promise<PtyBackendSession>
}
```
```ts type-equiv
/** Backend-owned live session retained by {@link PtyService}. */
interface PtyBackendSession {
/** Initial bounded terminal output returned from `terminal_open`. */
readonly motd: string
/** Top-level process id when one exists. */
readonly pid?: number
/** Start one exclusive send operation. */
startSend(request: PtySendRequest): PtySendOperation
/** Read one bounded page from retained scrollback. */
read(request: PtyReadRequest): PtyReadResult
/** Signal the verified foreground process group. */
signal(signal: PtySignal): Promise<PtySignalResult>
/** Observe top-level process status. */
status(): PtySessionStatus
/** Idempotently close the captured owned process tree and await quiescence. */
close(reason: string): Promise<void>
}
```
## 发送与保留输出
一个活跃会话同时只接受一个活动发送。该操作向通用后台任务公开一个消费式输出游标,并向前台调用方公开一个最终结果。`PtyReadResult` 则为有界的会话 scrollback 单独分页。
```ts type-equiv
/** Live backend-owned send; exactly one may be active per PTY session. */
interface PtySendOperation {
/** Resolves after readiness, timeout, cancellation, or top-level process exit. */
done: Promise<PtySendResult>
/** Consume output produced since the prior call. */
readOutput(): PtySendRead
/** Request `SIGINT`; returns false after the operation settled. */
cancel(): boolean
}
```
```ts type-equiv
/** Settled result for one foreground or background send. */
interface PtySendResult {
/** Bounded rendered terminal delta remaining at settlement. */
viewport: string
/** Why the wait returned; this does not imply arbitrary child-process exit. */
waitReason: PtyWaitReason
/** Top-level session status observed at settlement. */
sessionStatus: PtySessionStatus
/** Whether output was dropped from the operation or retained scrollback. */
truncated: boolean
}
```
## 归属与持久性
`PtyService` 会将一项等待完成的清理附加到确切的拥有者作用域拒绝其他拥有者的操作并让会话在后端或工具插件重载期间保持存活。PTY 状态与原始字节仍局限在进程内。模型输入与有界的返回输出通过现有 `tool/call`、`tool/result` 和任务结果路径持久保存,而不是重复记录 PTY 会话事件。

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
session-reference.md: 4898cdd641427a023dde63bfc9759300964c7fac
session-reference.zh.md: 8e36d70241f2565a587bd3c1ee270d99dba47d71

View File

@@ -1,5 +1,7 @@
# Session References
English | [中文](session-reference.zh.md)
Structured cross-session reference requests and prepared message contexts. The [package contract](../../packages/context/session-reference) owns canonical URIs, current-surface projection, tag-safe JSON and byte retention, stable errors, and the untrusted model prompt. Host adapters use these types instead of passing their UI mention syntax into the agent core.
Source: [`packages/context/session-reference/src/types.ts`](../../packages/context/session-reference/src/types.ts)

View File

@@ -0,0 +1,67 @@
# 会话引用
[English](session-reference.md) | 中文
结构化的跨会话引用请求与预备消息上下文。[package契约](../../packages/context/session-reference) 负责规范 URI、当前表层投影、标签安全的 JSON 与字节保留、稳定错误和不可信的模型提示词。宿主适配器使用这些类型,而不会把各自 UI 的提及语法传入 agent智能体核心。
来源:[`packages/context/session-reference/src/types.ts`](../../packages/context/session-reference/src/types.ts)
## 输入与候选项
`SessionReferenceInput` 是与宿主无关的选择。id 具有权威性label 是随快照携带的显示元数据。
```ts type-equiv
/** One source session selected by a host. */
interface SessionReferenceInput {
/** Opaque source session identity. */
sessionId: SessionId
/** Optional user-facing mention label. */
label?: string
}
```
`SessionReferenceCandidate` 是面向宿主的发现输出。存在最新会话标题时,它的 label 使用该标题;筛选仍只搜索 session id 和 cwd绝不搜索 transcript文本记录
```ts type-equiv
/** One host-facing candidate from exact session metadata. */
interface SessionReferenceCandidate {
/** Opaque source session identity. */
sessionId: SessionId
/** Latest log-backed title, falling back to the opaque session id. */
label: string
/** Source session working directory, when recorded. */
cwd?: string
/** Source session creation time in Unix epoch milliseconds. */
createdAt: number
}
```
## 预备消息
预备过程保留可读的当前消息内容,并最多返回一个聚合上下文。宿主会把 `contexts` 绑定到该次确切的 `followup()` 或 `steer()` 调用。
```ts type-equiv
/** Message payload and the zero-or-one durable snapshot contexts bound to it. */
interface PreparedReferencedMessage {
/** Readable message content after host mention tokens are removed. */
content: ContentBlock[]
/** Empty without references; otherwise one aggregated untrusted context. */
contexts: HookContext[]
}
```
## 错误
`SessionReferenceError.code` 区分无效配置或输入、自引用、数量限制、源读取失败、预算失败和取消。宿主协议会把这些 code 映射到各自的错误信封,无需检查提示词字节。
```ts type-equiv
/** Stable failure codes exposed to host adapters. */
type SessionReferenceErrorCode =
| 'SESSION_REFERENCE_INVALID_CONFIG'
| 'SESSION_REFERENCE_INVALID_REFERENCE'
| 'SESSION_REFERENCE_SELF_REFERENCE'
| 'SESSION_REFERENCE_TOO_MANY'
| 'SESSION_REFERENCE_READ_FAILED'
| 'SESSION_REFERENCE_BUDGET_EXCEEDED'
| 'SESSION_REFERENCE_CANCELLED'
```

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
session-title.md: 6575bda5fdecf2be15ed7c3288efb0efa759ac8a
session-title.zh.md: 66ec567ac6cef32acef9c50ae3e67155097a76b6

View File

@@ -1,5 +1,7 @@
# Session Titles
English | [中文](session-title.zh.md)
Durable latest-wins title state and the optional asynchronous provider vocabulary owned by [`@deepseek-ai/dsh-session-title`](../../packages/session-title/session-title). The shared LLM helper owns the exact auxiliary request record. Package READMEs own timing, fallback, failure, and fork behavior; the generated [persistence catalog](../persistence-catalog.md) owns the complete event declarations.
Sources: [`packages/session-title/session-title/src/index.ts`](../../packages/session-title/session-title/src/index.ts), [`packages/session-title/session-title-llm/src/index.ts`](../../packages/session-title/session-title-llm/src/index.ts)

View File

@@ -0,0 +1,142 @@
# 会话标题
[English](session-title.md) | 中文
[`@deepseek-ai/dsh-session-title`](../../packages/session-title/session-title) 所拥有的持久化后写覆盖标题状态与可选异步提供方词汇。共享 LLM大语言模型辅助组件负责精确的辅助请求记录。各包packageREADME 负责时序、回退、失败与 fork 行为;生成的[持久化日志事件目录](../persistence-catalog.md)负责完整的事件声明。
源码:[`packages/session-title/session-title/src/index.ts`](../../packages/session-title/session-title/src/index.ts)、[`packages/session-title/session-title-llm/src/index.ts`](../../packages/session-title/session-title-llm/src/index.ts)
## 持久标题状态
提供方生成修订时会记录 `SessionTitleProviderId``SessionTitleEventData` 携带精确的人类消息来源信息,`SessionTitleSnapshot` 则加入 `foldSessionTitle()` 选出的持久事件信封事实。
```ts type-equiv
/** Identifies one session-title provider registration. */
type SessionTitleProviderId = Branded<'SessionTitleProviderId'>
```
```ts type-equiv
/** Exact auxiliary model route that produced a title. */
interface SessionTitleModelProvenance {
/** Registered LLM provider route. */
readonly provider: string
/** Provider model id. */
readonly model: string
}
```
```ts type-equiv
/** Durable ownership record for an accepted session title. */
type SessionTitleSource =
| { readonly kind: 'fallback' }
| {
readonly kind: 'provider'
readonly provider: SessionTitleProviderId
readonly model?: SessionTitleModelProvenance
}
```
```ts type-equiv
/** Payload of the log-only `session/title` event. */
interface SessionTitleEventData {
/** Normalized non-empty title text. */
readonly title: string
/** Exact human `user/message` seqs used to derive this title. */
readonly messageSeqs: number[]
/** Built-in fallback or registered-provider provenance. */
readonly source: SessionTitleSource
}
```
```ts type-equiv
/** Latest folded title plus the title event's durable envelope facts. */
interface SessionTitleSnapshot extends SessionTitleEventData {
/** Seq of the latest `session/title` event. */
readonly eventSeq: number
/** Timestamp of the latest `session/title` event. */
readonly updatedAt: number
}
```
## 辅助请求记录
共享 LLM 辅助组件会在调用模型前,记录每一项已经过验证且可分发的标题请求。即使后续生成失败,载荷仍会复现模型可见的系统输入与消息输入、路由、输出上限、提供方归属和源消息归因。
```ts type-equiv
/** Exact model-visible request recorded before one auxiliary title dispatch. */
interface SessionTitleLlmRequestEventData {
/** Registered title-provider identity responsible for the request. */
readonly titleProvider: SessionTitleProviderId
/** Exact human `user/message` seqs represented in `messages`. */
readonly messageSeqs: number[]
/** Exact auxiliary LLM route. */
readonly route: SessionTitleModelProvenance
/** Exact auxiliary system prompt. */
readonly system: string
/** Exact auxiliary message list. */
readonly messages: Message[]
/** Exact auxiliary output-token cap. */
readonly maxTokens: number
}
```
## 提供方输入与输出
服务会对截至某一修订的合格消息创建快照。提供方返回的 seq 仅可来自该请求;由服务负责的接受过程会验证顺序、规范化标题、强制执行字节上限并追加来源信息。
```ts type-equiv
/** One eligible human text message exposed to title providers. */
interface SessionTitleUserMessage {
/** Source `user/message` event seq. */
readonly seq: number
/** Exact concatenated text-block content. */
readonly text: string
}
```
```ts type-equiv
/** Automatic generation cadence owned by a registered provider. */
type SessionTitleAutomaticMode = 'first-message' | 'all-user-messages'
```
```ts type-equiv
/** Immutable input supplied to one title-provider call. */
interface SessionTitleProviderRequest {
/** Live session being titled. */
readonly session: Session
/** All eligible human messages through this generation revision. */
readonly messages: readonly SessionTitleUserMessage[]
/** Exact current logged main-request route, when one has been recorded. */
readonly route?: SessionTitleModelProvenance
/** Cancellation for supersession, disposal, timeout composition, or the explicit caller. */
readonly signal: AbortSignal
}
```
```ts type-equiv
/** Provider output before service-owned normalization and durable acceptance. */
interface SessionTitleProviderResult {
/** Proposed title text. */
readonly title: string
/** Exact seqs from `request.messages` used by this result. */
readonly messageSeqs: readonly number[]
/** Auxiliary LLM route, when generation used a model. */
readonly model?: SessionTitleModelProvenance
}
```
```ts type-equiv
/** One optional asynchronous title implementation registered with the service. */
interface SessionTitleProvider {
/** Stable provider identity recorded in title provenance. */
readonly id: SessionTitleProviderId
/** When new human prompts start automatic generation. */
readonly automatic: SessionTitleAutomaticMode
/**
* Produce one title revision.
* @param request - message snapshot, current route, session, and cancellation.
* @returns proposed title plus exact input seqs and optional model provenance.
*/
generate(request: SessionTitleProviderRequest): Promise<SessionTitleProviderResult>
}
```

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
spill.md: a798d8143b2849dc0cf49d04e7019ce796cdee45
spill.zh.md: 1af6939d1d8fd37958cae4f9cf2cbf706b17acd0

View File

@@ -1,5 +1,7 @@
# Spill Storage
English | [中文](spill.zh.md)
The spill storage seam — a [capability seam](../../.agents/notes/implemented/architecture/2026-07-08-tool-output-spill-files.md) that persists a tool's oversized text and returns a model-facing locator plus retrieval guidance, split across packages: interface ([dsh-spill](../../packages/spill/spill), `ctx.spillStore`), implementation ([dsh-spill-local](../../packages/spill/spill-local), private session-scoped files on the host filesystem), and consumer ([dsh-spill-policy](../../packages/spill/spill-policy), the `tools/post-execute` policy). Spill is **one optional capability**, not part of the agent-loop spine — so its vocabulary lives here, not in [core.md](core.md). Preview mechanics stay in [dsh-retention](../../packages/util/retention); this seam only saves the final text the policy hands it.
Source: [`packages/spill/spill/src/types.ts`](../../packages/spill/spill/src/types.ts)

View File

@@ -0,0 +1,85 @@
# 落盘存储
[English](spill.md) | 中文
落盘存储 seam 是一项[能力 seam](../../.agents/notes/implemented/architecture/2026-07-08-tool-output-spill-files.md)它持久保存工具的超大文本并返回面向模型的定位符与检索指引该能力拆分到三个包package接口[dsh-spill](../../packages/spill/spill)`ctx.spillStore`)、实现([dsh-spill-local](../../packages/spill/spill-local),宿主文件系统中会话作用域的私有文件)和消费方([dsh-spill-policy](../../packages/spill/spill-policy)`tools/post-execute` 策略)。落盘是**一项可选能力**,不属于 agent loop智能体循环主干因此其词汇记录在此处而不在 [core.md](core.md) 中。预览机制仍归 [dsh-retention](../../packages/util/retention) 所有;该 seam 只保存策略交给它的最终文本。
源码:[`packages/spill/spill/src/types.ts`](../../packages/spill/spill/src/types.ts)
## 保存请求
`saveText` 是整个 seam原样持久保存 `content`,并返回不透明的定位符、后端提供的检索提示和准确字节数。请求携带保存时的存储命名空间(`owner`)、内容来源(`source`,用于命名和检查的描述性来源信息,而非访问控制)以及后端可用作命名提示的 `suggestedName`(它不是路径)。
```ts type-equiv
/** One request to persist text to a spill artifact. */
interface SaveTextSpill {
owner: SpillOwner
source: SpillSource
/**
* A caller-suggested base name (e.g. `web_fetch.txt`). The backend sanitizes
* it to a single safe path segment before use — it is a hint, never a path.
*/
suggestedName: string
/** The full text to persist (UTF-8). */
content: string
}
```
```ts type-equiv
/**
* Save-time storage namespace for a spilled artifact. The session id lets a
* backend group storage under the producing session, but the returned
* {@link SpillLocator} is the model-facing handle. Forked sessions inherit
* locators already present in the seeded log; those artifacts are not copied or
* re-owned, and spills produced after the fork use the child session id.
*/
interface SpillOwner {
sessionId: SessionId
}
```
`SpillOwner.sessionId` 是保存时的存储命名空间。fork 后的会话会从种子日志继承已有的落盘定位符这些产物不会被复制或重新取得所有权fork 后产生的落盘则使用子会话 id。保留期清理可以连同其他旧会话产物一起使旧定位符失效落盘 seam 不定义逐会话的清理策略。
```ts type-equiv
/**
* Provenance of one spilled artifact — recorded by the backend for a readable
* filename and inspection. Not interpreted for access control; purely
* descriptive.
*/
interface SpillSource {
/** The tool whose result was spilled (e.g. `web_fetch`). */
toolName: string
/** The model-issued call id the result belongs to. */
callId: CallId
/** A short human label for the artifact (e.g. `result`). */
label: string
}
```
## 结果
```ts type-equiv
/** A saved spill artifact: its locator, byte length, and backend-specific retrieval guidance. */
interface SpillRef {
locator: SpillLocator
bytes: number
retrievalHint: string
}
```
`SpillLocator` 是后端返回的[品牌化](core.md#branded-ids)面向模型句柄。本地后端将它渲染为文件系统路径;远程或数据库后端可以渲染 URI、键或命令 token。消费方将它视为不透明值并使用 `retrievalHint` 渲染,而不是假定 `read` 始终是正确的检索机制。
```ts type-equiv
/**
* Opaque model-facing handle for one spilled artifact. A local backend may use a
* filesystem path; a remote or database backend may use a URI or key. Consumers
* render it with {@link SpillRef.retrievalHint}, but do not parse it.
*/
type SpillLocator = Branded<'SpillLocator'>
```
## 服务
`SpillStore``ctx.spillStore`,定义于 [`packages/spill/spill/src/index.ts`](../../packages/spill/spill/src/index.ts))是只有一个方法的抽象服务:`saveText(input) → Promise<SpillRef>`。它持久保存完整的 `content`并在实际存储失败权限、ENOSPC、后端不可用时拒绝。该 seam 只负责存储:不负责保留策略、工具结果替换或检索/搜索 API。
本地后端([dsh-spill-local](../../packages/spill/spill-local))写入 `<root>/session-<hash>/<random>-<safeName>`根目录是已配置或延迟创建的私有0700目录会话子目录采用 `sha256(sessionId)`,并通过排他的仅所有者可访问写入(`open(path, 'wx', 0o600)`)防止预先植入的符号链接重定向写入。其 `locator` 是本地路径,`retrievalHint` 则告知模型在该路径上使用 `read` 或 `grep`。策略消费方([dsh-spill-policy](../../packages/spill/spill-policy))会把超过 `maxInlineBytes` 的纯文本最终结果替换为保留库生成的首尾预览和落盘引用;该过程尽力而为:保存失败时保留原始内联结果,而不会把成功的调用变成 `isError`。

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
tasks.md: d1f5a6d7b369e6113132f60e493cf87757e20599
tasks.zh.md: 1562d9401f0f55ac6d6260902b8b1c71d9664d48

View File

@@ -1,5 +1,7 @@
# Background Task Runtime
English | [中文](tasks.zh.md)
Types shared by long-running producers, `ctx.tasks`, and task control surfaces. The [runtime Agent Note](../../.agents/notes/implemented/architecture/2026-06-20-generic-long-running-tool-runtime.md) owns the design; this page records the literal shapes from [`packages/tasks/tasks/src/types.ts`](../../packages/tasks/tasks/src/types.ts).
## Ids and status

View File

@@ -0,0 +1,154 @@
# 后台任务运行时
[English](tasks.md) | 中文
长时间运行的生产方、`ctx.tasks` 与任务控制接口共用的类型。[运行时 Agent Noteagent 决策记录)](../../.agents/notes/implemented/architecture/2026-06-20-generic-long-running-tool-runtime.md)负责设计;本页记录 [`packages/tasks/tasks/src/types.ts`](../../packages/tasks/tasks/src/types.ts) 中的字面形状。
## ID 与状态
`TaskId` 是按 `<kind>-N` 生成的[品牌化 id](core.md#branded-ids)。访问控制依赖拥有者授权,而非 id 的保密性。`TaskKind` 派生自可合并扩展的 map注册表将各个 kind 视为不透明的 id 命名空间。
```ts type-equiv
/**
* Producer-defined task kinds. Plugins extend this map by declaration merging;
* the registry treats every value as an opaque id namespace.
*/
interface TaskKindMap {
bash: 'bash'
subagent: 'subagent'
}
```
`TaskStatus` 为 `'running' | 'stopping' | 'completed' | 'killed' | 'failed'`;生产方特有的事实归入 `TaskSnapshot.detail`。
## 生产方契约
`TaskStart` 声明身份和启动器。运行时会在调用 `run()` 前完成预检,随后提交注册,不再执行可能失败的步骤。生产方拥有执行资源;运行时拥有身份、访问权限和生命周期状态。
```ts type-equiv
/**
* Producer declaration passed to {@link TaskService.start}. The runtime
* preflights access and cleanup before invoking {@link run}; the producer owns
* execution resources while the runtime owns identity and lifecycle state.
*/
interface TaskStart {
/** Producer kind — also the id prefix (`bash`, `subagent`, …). */
kind: TaskKind
/** One-line model-facing label (the command; the delegation description). */
label: string
/**
* Optional UTF-8 byte cap for each complete model-facing completion notice or
* output read, including control-surface status metadata.
*/
outputLimitBytes?: number
/**
* Owning live agent. Access is fenced by its session id, and agent disposal
* cancels and awaits the task. The instance must be the one currently
* registered under its agent id. Omitting the owner creates an unowned task,
* open to any caller until service disposal.
*/
owner?: Agent
/**
* Start the work after preflight and synchronously return its hooks. Called
* once; a throw leaves nothing registered, and the producer must clean up any
* partially started resources.
*/
run(): TaskHooks
}
```
`TaskHooks.done` 是完全停稳边界。可选的 `readOutput` 用来区分会消费输出的流式任务和仅有最终输出的任务。
```ts type-equiv
/** Hooks through which the runtime controls and observes producer work. */
interface TaskHooks {
/**
* Request termination. Must be synchronous, idempotent, and eventually settle
* {@link done}; throws propagate. The optional reason is forwarded verbatim.
*/
cancel(reason?: string): void
/**
* Resolves after the producer releases its resources, not merely when work
* finishes. Must not reject; the runtime converts a rejection to `failed`.
* If teardown cancellation throws, the runtime may force-fail only the
* registry record without claiming that the work stopped.
*/
done: Promise<TaskOutcome>
/**
* Consume output produced since the previous call. The producer formats
* truncation and spill notices. Absence marks a final-output-only task; each
* task has one consuming cursor.
*/
readOutput?(): string
}
```
```ts type-equiv
/** Terminal result supplied by a producer through {@link TaskHooks.done}. */
interface TaskOutcome {
/** How the task ended: finished (`completed`), cancelled (`killed`), or broke (`failed`). */
status: 'completed' | 'killed' | 'failed'
/** Kind-specific detail rendered into status lines ('exit code: 3', 'max-tokens'). */
detail?: string
/** Final output for tasks without `readOutput`; stream tasks leave it unset. */
output?: string
}
```
## 消费方视图
快照是每次新建的只读投影。`ownerSession` 携带用于授权的共享 `SessionId`;完成监听器则会另行收到用于生命周期清理的确切拥有者对象。另一个接口已经交付终止状态或承诺交付时,`reported` 会抑制完成通知。
```ts type-equiv
/**
* A read-only projection of one task, safe to hand to listeners and tools —
* a fresh object per call, never live registry state.
*/
interface TaskSnapshot {
/** The registry-issued id (`<kind>-N`). */
id: TaskId
/** The producer kind the task was registered with. */
kind: TaskKind
/** The producer-supplied one-line label. */
label: string
/** Producer-owned cap for complete model-facing notices and output reads. */
outputLimitBytes?: number
/**
* Owner session id used for authorization and correlation; absent for
* unowned tasks. Completion listeners receive the exact {@link Agent}
* separately through {@link TaskDoneListener}.
*/
ownerSession?: SessionId
/** Current lifecycle state. */
status: TaskStatus
/** Kind-specific status detail, present once the producer supplied one (usually terminal). */
detail?: string
/** Epoch ms when the task was registered. */
startedAt: number
/** Epoch ms when the task settled; absent while `running`/`stopping`. */
finishedAt?: number
/**
* True when a kill, read, or wait has reported or committed to report the
* terminal state. Completion surfaces suppress redundant notices when set.
*/
reported: boolean
}
```
```ts type-equiv
/** Output and post-read state returned by {@link TaskService.read}. */
interface TaskRead {
/**
* Stream kinds: the consuming delta since the previous read. Final-output
* kinds: empty while live, the terminal {@link TaskOutcome.output} (or
* empty) once settled — idempotent, never consumed.
*/
text: string
/** The task's state at read time. */
snapshot: TaskSnapshot
}
```
## 服务行为
[`TaskService`](../../packages/tasks/tasks/src/index.ts) 提供原子 `start`、限定调用方作用域的 `get` 和 `list`、`read`、`kill`、有界 `wait`、故障隔离的 `onTaskDone` 监听器,以及 `attachSurface` 可用性防线。授权会比较拥有者会话;拥有者清理会选择确切的已注册 `Agent` 实例。包package契约见 [`dsh-tasks`](../../packages/tasks/tasks/README.md),面向模型的接口见 [`dsh-tool-tasks`](../../packages/tasks/tool-tasks/README.md)。

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
token-meter.md: 05784e294485a11acf0e4c8972e4083b1786c943
token-meter.zh.md: c0dc55274acf21186f7baa00c377f9135792f888

View File

@@ -1,5 +1,7 @@
# Token Meter
English | [中文](token-meter.zh.md)
`@deepseek-ai/dsh-token-meter` exposes one detached replay snapshot for request pressure and positional surface pricing. `logRevision` is the number of durable events consumed for every field in the measurement.
Source: [`packages/llm/token-meter/src/types.ts`](../../packages/llm/token-meter/src/types.ts)

View File

@@ -0,0 +1,43 @@
# Token 计量
[English](token-meter.md) | 中文
`@deepseek-ai/dsh-token-meter` 公开一个独立的回放快照,用于表示请求压力与按位置计算的 surface 定价。`logRevision` 表示生成该计量中每个字段时所消费的持久事件数量。
来源:[`packages/llm/token-meter/src/types.ts`](../../packages/llm/token-meter/src/types.ts)
## `TokenMeasurement`
```ts type-equiv
/** Detached immutable request-pressure and surface snapshot at one consumed log revision. */
interface TokenMeasurement {
/** Number of durable events consumed; equal to the next unread event seq. */
readonly logRevision: number
/** Provider or heuristic anchor used for this measurement. */
readonly baseline: TokenMeasurementBaseline
/** Signed repricing of current surface content relative to the baseline anchor. */
readonly surfaceDeltaTokens: number
/** Non-negative current request-and-response pressure. */
readonly totalTokens: number
/** Total heuristic tokens across the current surface. */
readonly surfaceTokens: number
/** Current surface nodes in positional head-to-tail order. */
readonly nodes: readonly TokenSurfaceNode[]
}
```
`baseline.kind === 'usage'` 表示最近一次成功的提供方调用具有相同的规范请求信封,且当前总量不低于该调用的完整启发式锚点。`estimated` 表示不存在可复用的保守 usage 锚点,因此服务使用固定启发式规则对完整信封和 surface 定价。后续成功请求会替换早先的锚点;有符号的 `surfaceDeltaTokens` 会保留相对于匹配锚点的增长与缩减。`totalTokens` 仍表示请求与响应压力,`surfaceTokens` 则是仅针对 surface 的启发式总量,等于所有节点价格之和。
## `TokenSurfaceNode`
```ts type-equiv
/** One token-priced node in the current ordered session surface. */
interface TokenSurfaceNode {
/** Durable sequence number of the surface event. */
readonly seq: number
/** Heuristic tokens for the exact message projected by this node. */
readonly tokens: number
}
```
surface 顺序具有权威性;替换节点的持久 seq 可能高于位置排在其后的节点。该快照不可变,不会随底层回放折叠推进而增长。