fix(rebase): restore consolidated documentation state

This commit is contained in:
Turtle
2026-07-29 21:16:31 +08:00
parent 9970f60969
commit d2c7aaddc7
18 changed files with 40 additions and 350 deletions

View File

@@ -2,10 +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/examples/README.md
<<<<<<< HEAD
README.md: c229cef22087ac290bf862d6b3e31fdb533858c4
README.zh.md: 208b9a138506785ea1dd2d83ddfbba29e4b7968e
=======
README.md: d3ad432e71036db0d21f059e52f5d32e58010c42
README.zh.md: 0218e60df2511974b8eb222e23331c5a70c9df60
>>>>>>> a1c6a2c3f (refactor(cli)!: one shared base config with per-surface overlays)

View File

@@ -2,25 +2,16 @@
[English](README.md) | 中文
预先组合的插件 bundle组合包供轻量叶节点 `cordis.yml` 加载,无需手工组装主干和前端入口。这些是 **演示/参考**packagenpm 名称的 `-demo` 后缀把每个包标为非产品表层,直接查看包名即可辨认。仓库根目录 [`examples/`](../../examples/AGENTS.md) 下的可运行叶节点与 [Python SDK 运行时](../../python/sdk-runtime/README.md) 是消费方;每个消费方都只包含可替换后端和一个组合包入口。
预先组合的插件 bundle组合包供轻量叶节点 `cordis.yml` 加载,无需手工组装主干和前端入口。这些是 **演示/参考**npm 名称的 `-demo` 后缀把每个包标为非产品表层,直接查看包名即可辨认。仓库根目录 [`examples/`](../../examples/AGENTS.md) 下的可运行叶节点与 [Python SDK runtime](../../python/sdk-runtime/README.md) 是消费方;每个叶节点都只包含可替换后端和一个组合包入口。
| 包 | npm 名称 | 角色 |
|---|---|---|
<<<<<<< HEAD
| `agent-spine-demo/` | `@deepseek-ai/dsh-agent-spine-demo` | 不含执行器和 UI 的 agent智能体主干打包为一个组合包插件带后备会话标题和可选择启用的持久化目标栈 |
| `tui-demo/` | `@deepseek-ai/dsh-tui-demo` | 全屏终端应用组合包:主干 + 持久化目标 + `/goal` 命令 + JSONL 持久化 + `dsh-tui` + 预创建的 `main` agent没有 bin由 [`dsh`](../../apps/cli/README.md) CLI命令行界面启动 |
=======
| `agent-spine-demo/` | `@deepseek-ai/dsh-agent-spine-demo` | 不含执行器和 UI 的 agent 主干,打包为一个组合包插件,带后备会话标题和选用的持久目标栈 |
>>>>>>> a1c6a2c3f (refactor(cli)!: one shared base config with per-surface overlays)
| `cli-demo/` | `@deepseek-ai/dsh-cli-demo` | 无头单次应用:主干 + JSONL 持久化 + 预创建的 `main` agent提供文本和 DSH 原生 JSON 输出 |
| `acp-demo/` | `@deepseek-ai/dsh-acp-demo` | ACPAgent Client Protocol自动化服务器应用:主干 + 持久目标 + JSONL 持久化 + [`acp`](../acp/acp/README.md) 桥接层(无 stdout logger带启动 `bin` |
| `jsonrpc-demo/` | `@deepseek-ai/dsh-jsonrpc-demo` | 只有 bin 的运行时,用于启动外部 `cordis.yml`,供 stdio JSON-RPC SDK 客户端使用 |
| `acp-demo/` | `@deepseek-ai/dsh-acp-demo` | ACP 自动化服务器应用:主干 + 持久目标 + JSONL 持久化 + [`acp`](../acp/acp/README.md) 桥接层(无 stdout logger带启动 `bin` |
| `jsonrpc-demo/` | `@deepseek-ai/dsh-jsonrpc-demo` | 只有 bin 的 runtime,用于启动外部 `cordis.yml`,供 stdio JSON-RPC SDK 客户端使用 |
<<<<<<< HEAD
`agent-spine-demo` 是共享组合包;`tui-demo``cli-demo``acp-demo` 分别将它与全屏终端、无头单次和 ACP 自动化前端入口组合。`cli-demo``acp-demo` 拥有各自的启动 bin`tui-demo` 只交付组合包插件,产品 [`dsh`](../../apps/cli/README.md) CLI 是它的终端前端入口。`jsonrpc-demo` 自身不挂载任何组合,而是启动部署的 `cordis.yml` 所指名的任意插件树Python SDK 运行时会启动它。
=======
`agent-spine-demo` 是共享组合包;`cli-demo``acp-demo` 分别将它与无头单次和 ACP 自动化前端入口组合,并拥有各自的启动 bin。产品 [`dsh`](../../apps/cli/README.md) CLI 不使用组合包:其 TUI 与 web surface 都是一份共享的 `base.cordis.yml` 加各自一份 overlay。`jsonrpc-demo` 自身不挂载任何组合,而是启动部署的 `cordis.yml` 所指名的任意插件树Python SDK runtime 会启动它。
>>>>>>> a1c6a2c3f (refactor(cli)!: one shared base config with per-surface overlays)
这些 **不是** 产品 API。它们打包的主干组件位于 [`core/`](../core/README.md)人类SDK 通道和启动粘合代码位于 [`ui/`](../ui/README.md),自动化传输位于 [`acp/`](../acp/README.md),可替换后端位于各自能力组;演示组合包只选定其中一种具体组合。可以自由替换或 fork。
@@ -28,4 +19,4 @@
## jsonrpc binexe 名称是历史遗留
`jsonrpc-demo` 已像同级包一样重命名,但其 bin 仍为 `dsh-jsonrpc-agent`,单文件可执行程序仍为 `dsh-jsonrpc-agent-pkg`(在 [Python 分发](../../python/sdk-runtime/README.md)各处被引用)。这些名称属于 SDK 的运行时启动表层;只有 SDK 统一该启动流程时才会协调它们,而不会在此次移动中处理。
`jsonrpc-demo` 已像同级包一样重命名,但其 bin 仍为 `dsh-jsonrpc-agent`,单文件可执行程序仍为 `dsh-jsonrpc-agent-pkg`(在 [Python 分发](../../python/sdk-runtime/README.md)各处被引用)。这些名称属于 SDK 的 runtime 启动表层;只有 SDK 统一该启动流程时才会协调它们,而不会在此次移动中处理。

View File

@@ -2,10 +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/examples/agent-spine-demo/README.md
<<<<<<< HEAD
README.md: 359e7153be2f480ba3fea4b06782acdc9f89ebb9
README.zh.md: acd8c06940b03e90e368314cd725846a2b92b656
=======
README.md: 6fde5c64052e369541787f90c12c33a7b0b8f9eb
README.zh.md: d5b0e2b50707750132bdeae9d7e56d513b0f40a7
>>>>>>> a1c6a2c3f (refactor(cli)!: one shared base config with per-surface overlays)

View File

@@ -2,7 +2,7 @@
[English](README.md) | 中文
**默认的不含执行器、不含 UI 的 agent(智能体)主干** 作为一个 Cordis 组合包插件。它加载每个 harness agent 所需的固定服务集合,包括本地 skill(技能)提供方,并将循环的 `agents` 列表作为自身配置转发。因此,应用包package只需添加前端入口和可替换后端,就能组合出可工作的 agent。
**默认的不含执行器、不含 UI 的 agent 主干** 作为一个 Cordis 组合包插件。它加载每个 harness agent 所需的固定服务集合,包括本地 skill 提供方,并将循环的 `agents` 列表作为自身配置转发。因此,应用包只需添加前端入口和可替换后端,就能组合出可工作的 agent。
阅读此包可了解完整插件树及其组合顺序。
@@ -43,15 +43,11 @@
主干包含每个前端入口都共有的全部组件。可替换组件和与前端入口耦合的组件留在外部,由加载组合包的一方选择:
- **LLM(大语言模型)适配器**:组合包交付抽象 `llm` 服务;叶节点在 `ctx.llm` 上注册具体适配器(`llm-deepseek``llm-pi-ai``llm-replay`)。
- **基于模型的会话标题提供方**组合包挂载带可覆盖示例限制的后备服务5 个词、40 个后备字节、80 个可接受标题字节);叶节点可以恰好选用一个首消息或全消息 LLM 提供方。
- **LLM 适配器**:组合包交付抽象 `llm` 服务;叶节点在 `ctx.llm` 上注册具体适配器(`llm-deepseek``llm-pi-ai``llm-replay`)。
- **模型支持的会话标题提供方**组合包挂载带可覆盖示例限制的后备服务5 个词、40 个后备字节、80 个可接受标题字节);叶节点可以恰好选用一个首消息或全消息 LLM 提供方。
- **bash 执行器**:组合包交付 `tool-bash`(消费方 schema叶节点提供 `ctx.bash``bash-local` 或沙箱化实现)。
- **非本地 skill 提供方**:组合包交付 skill 注册表、本地文件系统提供方和 `skill` 工具;部署可以把嵌入式目录或远程目录等其他提供方作为同级插件添加。
<<<<<<< HEAD
- **前端入口与各应用基础设施**:终端 TUI 或 ACPAgent Client Protocol自动化传输以及 `hmr`。应用包([`dsh-tui-demo`](../tui-demo/README.md)、[`dsh-acp-demo`](../acp-demo/README.md))拥有这些选择。`timer` 位于主干中,因为它是共有组件且不写 stdout前端入口拥有 stdout因此留在组合包外。
=======
- **前端入口与各应用基础设施**:终端 TUI 或 ACP 自动化传输,以及 `hmr`。应用包([`dsh-cli-demo`](../cli-demo/README.md)、[`dsh-acp-demo`](../acp-demo/README.md))拥有这些选择。`timer` 位于主干中,因为它是共有组件且不写 stdout前端入口拥有 stdout因此留在组合包外。
>>>>>>> a1c6a2c3f (refactor(cli)!: one shared base config with per-surface overlays)
这把[接口/实现/消费方 seam](../../../.agents/notes/implemented/architecture/2026-06-13-capability-seams.md) 提升到组合层:组合包拥有共享主干,叶节点拥有后端,应用包拥有前端入口。
@@ -63,25 +59,25 @@ import type { Config } from '@deepseek-ai/dsh-agent-spine-demo'
// workspaceContext requires { maxBytes } or false; the other owner schemas supply defaults.
```
组合包将每个字段转发给拥有它的子节点:`agents``maxParallelToolCalls` 交给 `agent-loop``agents` 默认为 `[]`,上限在该处默认),因此每个应用提供自己的预创建 agentTUI 和无头应用预创建 `main`ACP 应用则在 `session/new` 按需创建 agent`persona``toolOrder` 交给 `dsh-system-prompt``tools` 交给工具注册表以配置呈现模式`sessionTitle` 交给后备标题服务;`skills.registry``skills.local``skills.tool` 分别交给 skill 注册表、本地提供方和面向模型的消费方;必填的 `workspaceContext` 选择交给 `dsh-workspace-context``{ maxBytes }` 启用加载,`false` 禁用);`invariants` 交给不变式服务;`toolBash`/`toolTasks` 交给组合包拥有的两个面向模型工具插件。组合包始终挂载 `dsh-llm-retry`,而每个叶节点适配器拥有自己的嵌套 `retryPolicy`。省略 `sessionTitle` 时采用显式示例策略5 个词、40 个后备字节、80 个可接受标题字节。`goals` 对象会选用持久领域、模型工具和同会话 Goal Round 驱动器,并将 `goals.domain``goals.tool` 转发给各自拥有者;省略或设为 `false` 会让整个栈缺席,使无头调用方继续以单轮次结算。设置 `skills.enabled: false` 会同时省略本地提供方和面向模型的 skill 工具;设置 `toolTasks: false` 会保留供前台生产方使用的任务服务,但不公开 `task_output`/`task_list`/`task_kill`。它对 `dshHome` 只解析一次,解析通过 [`@deepseek-ai/dsh-paths`](../../util/paths/README.md) 完成,并将所得绝对值转发给 tool-bash 的托管环境和已启用的本地 skill 发现。顶层 `dshHome` 缺席时采用 `skills.local.dshHome`;两者同时提供但解析后的路径不同会明确失败。`toolBash.enableRunInBackground` 只控制 bash 生产方;独立加载的生产方保留各自配置。工作区指令先于 skill 目录注册,因此其会话前缀消息先渲染。应用包使用 `pickSpineConfig()`,只复制这些由组合包拥有的字段。
组合包将每个字段转发给拥有它的子节点:`agents``maxParallelToolCalls` 交给 `agent-loop``agents` 默认为 `[]`,上限在该处默认),因此每个应用提供自己的预创建 agentTUI 和无头应用预创建 `main`ACP 应用则在 `session/new` 按需创建 agent`persona``toolOrder` 交给 `dsh-system-prompt``tools` 交给工具注册表以配置呈现 mode`sessionTitle` 交给后备标题服务;`skills.registry``skills.local``skills.tool` 分别交给 skill 注册表、本地提供方和面向模型的消费方;必填的 `workspaceContext` 选择交给 `dsh-workspace-context``{ maxBytes }` 启用加载,`false` 禁用);`invariants` 交给不变式服务;`toolBash`/`toolTasks` 交给组合包拥有的两个面向模型工具插件。组合包始终挂载 `dsh-llm-retry`,而每个叶节点适配器拥有自己的嵌套 `retryPolicy`。省略 `sessionTitle` 时采用显式示例策略5 个词、40 个后备字节、80 个可接受标题字节。`goals` 对象会选用持久领域、模型工具和同会话驱动器,并将 `goals.domain``goals.tool` 转发给各自拥有者;省略或设为 `false` 会让整个栈缺席,使无头调用方继续以一轮结算。设置 `skills.enabled: false` 会同时省略本地提供方和面向模型的 skill 工具;设置 `toolTasks: false` 会保留供前台生产方使用的任务服务,但不公开 `task_output`/`task_list`/`task_kill`。它对 `dshHome` 只解析一次,解析通过 [`@deepseek-ai/dsh-paths`](../../util/paths/README.md) 完成,并将所得绝对值转发给 tool-bash 的托管环境和已启用的本地 skill 发现。顶层 `dshHome` 缺席时采用 `skills.local.dshHome`;两者同时提供但解析后的路径不同会明确失败。`toolBash.enableRunInBackground` 只控制 bash 生产方;独立加载的生产方保留各自配置。Workspace 指令先于 skill 目录注册,因此其会话前缀消息先渲染。应用包使用 `pickSpineConfig()`,只复制这些由组合包拥有的字段。
例如,`{ invariants: { enabled: true, package_allowlist: ['^@deepseek-ai/dsh-'], package_blocklist: ['agent-loop$'] } }` 会让包拥有的配套插件保持挂载但抑制被阻止的拥有者。Blocklist 匹配优先于 allowlist 匹配;正则表达式与生命周期规则见 [`dsh-invariants`](../../support/invariants/README.md)。
## 为何使用代码组合包,而非共享 YAML include
YAML include 可以去重配置,却无法拥有 bin 或提供前端入口默认值。ACP 应用包默认接出协议纯净的 stdout但叶节点仍可添加不安全的 logger。组合包子节点把服务注册到根 isolate-keyed store因此叶节点同级插件无需依赖加载顺序即可通过注入看到它们。
YAML include 可以去重配置,却无法拥有 bin 或提供前端入口默认值。ACP 应用包默认接出协议纯净的 stdout但叶节点仍可添加不安全的 logger。组合包子节点把服务注册到根 isolate-keyed store因此注入这些服务的叶节点同级插件无需依赖加载顺序即可看到它们。
重试策略可能在新的编号步骤中重复失败的请求。重试状态、提供方错误和失败的部分分片不进入模型历史每次提供方尝试仍可能产生计费always 模式没有尝试次数上限;前端入口从所有已记录步骤推导用量;重建的请求保留先前前缀,以便复用提供方缓存
重试策略可能在新的编号步骤中重复失败的请求。重试状态、提供方错误和失败的部分 chunk 不进入模型历史每次提供方尝试仍可能产生计费always mode 没有尝试次数上限;前端入口从所有已记录步骤推导用量;重建的请求保留先前前缀,以便复用提供方 cache
## 模型体验
模型通过 `dsh-system-prompt``dsh-tool-skill``dsh-tool-bash``dsh-tools``dsh-llm-retry` 间接获得体验;还会通过 `dsh-tool-goal` Goal Round 提示词获得体验,前提是启用 `goals`。组合包自身不添加面向模型的包装内容。
模型通过 `dsh-system-prompt``dsh-tool-skill``dsh-tool-bash``dsh-tools``dsh-llm-retry` 间接获得体验;还会通过 `dsh-tool-goal`目标轮次提示词获得体验,前提是启用 `goals`。组合包自身不添加面向模型的包装内容。
#### KV Cache 影响
不会直接失效;上述消费方负责请求前缀的任何变更。
不会直接失效;具名消费方拥有请求前缀的任何变更。
## 已知限制与暂缓事项
## 已知限制与延后工作
- **大部分主干集合固定在代码中**`apply()` 始终挂载核心服务与 `tool-bash`配置可以省略组合包内的目标、skill 与任务控制工具,但要替换循环或删除其他主干成员,就必须组合另一个组合包
- **大部分主干集合固定在代码中**`apply()` 始终挂载核心服务与 `tool-bash`配置可以省略组合包内的目标、skill 与任务控制工具,但要替换循环或删除其他主干成员,就必须组合另一个 bundle
- **不变式 seam 与配套插件仍是固定成员**`invariants.enabled: false` 或包筛选器会抑制检查但不会移除服务或配套插件注册Session 始终启用的校验与冻结是另一套机制。

View File

@@ -1,6 +0,0 @@
# 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 packages/examples/tui-demo/README.md
README.md: 058ebe87af5f041bd19fbfb205a97753ccacf6b9
README.zh.md: 43681e9c77cbd77459ec0539b69e0ab73274d2c1

View File

@@ -1,112 +0,0 @@
# @deepseek-ai/dsh-tui-demo
[English](README.md) | 中文
全屏终端应用组合包:一个 Cordis 插件,组合 [`@deepseek-ai/dsh-agent-spine-demo`](../agent-spine-demo/README.md)、持久化的同会话目标、人类命令注册表与 `/goal` 生产方、JSONL 持久化、键盘支持的用户交互、预创建的 `main` agent智能体以及 [`@deepseek-ai/dsh-tui`](../../ui/tui/README.md)。一份 `cordis.yml` 将它作为一个 Cordis 配置项挂载;[`dsh`](../../../apps/cli/README.md) CLI命令行界面是启动此类配置的入口。
管道、脚本和其他非交互式运行应使用 [`@deepseek-ai/dsh-cli-demo`](../cli-demo/README.md)。此组合包需要一对 TTY不提供面向行的回退。
## 内置组件
| 插件 | 设置在此处的原因 |
|---|---|
| `@deepseek-ai/dsh-agent-spine-demo` | 共享服务、面向模型的工具,以及一个已配置的 `main` agent |
| `@deepseek-ai/dsh-commands` | 供 TUI 和命令插件消费、仅面向人类的命令发现与分发 |
| `@deepseek-ai/dsh-command-goal` | 直接在主干的持久化目标栈上提供 `/goal` 状态与变更 |
| `@deepseek-ai/dsh-session-persistence-jsonl` | 位于 `persistenceRoot` 下的持久会话日志 |
| `@deepseek-ai/dsh-session-checkpoint-policy` | 模型请求和顶层工具 effect 前的语义持久性屏障,以及已完成步骤的检查点 |
| `@deepseek-ai/dsh-session-query-sqlite` + `@deepseek-ai/dsh-session-reference` | TUI 消费的组合式精确FTS 会话查询与有界 `@session` 快照;面向模型的查询工具仍由叶节点选用 |
| `@deepseek-ai/dsh-user-interaction` | 与提供方无关的人类问题服务 |
| `@deepseek-ai/dsh-tui` | 全屏 transcript文本记录、编辑器、工具卡片、计划与问题 overlay |
| `@deepseek-ai/dsh-tool-ask-user` | 面向模型的 `ask_user_question` 工具 |
可替换的 LLM大语言模型、bash、文件系统和其他能力提供方仍留在叶节点配置中。`@cordisjs/plugin-hmr` 也仍是仅叶节点使用的开发条目,因为它需要 Loader 内部实现。
## 配置
| 键 | 默认值 | 路由目标 |
|---|---|---|
| `provider` | 必填 | 已配置 `main` agent 的提供方 |
| `model` | 必填 | 已配置 `main` agent 的模型 |
| `maxParallelToolCalls` | agent-loop 默认值 | 组合包内循环的并发上限 |
| `persona` | 无 | 系统提示词 persona 模板 |
| `toolOrder` | 字典序 | 显式的面向模型工具顺序 |
| `tools` | 拥有者默认值 | 工具呈现模式 |
| `dshHome` | 拥有者默认值 | bash 与 skill技能使用的 harness 主目录 |
| `sessionTitle` | 主干示例限制 | 后备标题词数/字节限制 |
| `skills` | 拥有者默认值 | skill 注册表、本地提供方和工具配置 |
| `toolBash` | 拥有者默认值 | 面向模型的 bash 工具配置 |
| `toolTasks` | 拥有者默认值 | 后台任务控制工具配置,或 `false` |
| `goals` | 拥有者默认值 | 持久目标领域与模型工具配置;`false` 会移除目标栈与 `/goal` 生产方 |
| `workspaceContext` | 必填 | Workspace 指令配置,或 `false` |
| `persistenceRoot` | `./.sessions` | JSONL 持久化根目录,以及派生 `session-query.db` 索引的父目录 |
| `persistenceCompression` | `'zstd'` | JSONL 产物编码(`'zstd'` 或原始 `'none'` |
| `sessionReferences` | 服务默认值 | 路由到 `dsh-session-reference` 的跨会话候选项与快照限制 |
| `welcome` | `ready.` | TUI 副标题 |
| `resumeCommand` | 无 | 退出和无宿主回退的命令模板;选择器本身使用会话查询与宿主移交 |
| `ui` | 拥有者默认值 | 推理reasoning、颜色、卡片高度等 TUI 呈现设置 |
| `resumeSessionId` | 无 | 要恢复的确切持久化会话 |
新运行会创建 `main-session-<uuid>` 会话 id并将它同时传给 TUI 与已配置的 agent。恢复运行会将两个组件都绑定到 `resumeSessionId`。TUI 先于主干挂载,因此它可以渲染匹配的配置启动失败,而不会留下空白终端。应用为 `/resume` 组合持久化和会话查询;嵌入宿主还可以提供 `tuiResumeHost`,用于原地移交进程。
## 入口
此包package不交付 bin。[`dsh`](../../../apps/cli/README.md) CLI 是终端入口:裸 `dsh` 启动已交付的 `examples/tui-agent/cordis.yml`(它挂载此组合包),而 `dsh --config <path-to-cordis.yml>` 启动另一个挂载此组合包的叶节点配置。它加载 cwd 下可选的 `.env`,驱动 Cordis Loader并等待完整插件树。仓库安装了 Loader 的可选原生辅助程序,因此裸包说明符可以在纯 Node 下解析。
## 叶节点示例
```yaml
- id: llm-deepseek
name: '@deepseek-ai/dsh-llm-deepseek'
config:
apiKey: !!js process.env.DEEPSEEK_API_KEY
- id: bash
name: '@deepseek-ai/dsh-bash-local'
- id: tui-agent
name: '@deepseek-ai/dsh-tui-demo'
config:
provider: deepseek
model: deepseek-v4-flash
workspaceContext:
maxBytes: 65536
welcome: 'Coding agent ready.'
ui:
showReasoning: true
```
## 模型体验
### 交互式终端轮次
#### 模型看到的内容
每次非空、非命令的编辑器提交都会成为用户消息;运行中轮次内的提交成为 steering中途引导。斜杠命令输入和输出仍只面向人类而已接受的 `/goal` 变更会追加领域拥有的模型可见状态。共享主干提供已配置的 persona、workspace 指令、skill 目录、目标控制和可见工具 schema。TUI 渲染本身对模型不可见。
#### Token 影响
用户、assistant 与工具历史按常规会话和压缩compaction规则增长。Header、卡片、计划、Markdown 样式和快捷键不增加 token。
#### KV Cache 影响
只要组合后的提示词、schema、路由和保留历史前缀保持稳定就保持仅追加。组合方式变更与 compaction 可能从第一个变化的 token 起使复用失效。
### 人类问题答案
#### 模型看到的内容
`ask_user_question` 会保留工具调用,以及 `dsh-tool-ask-user` 定义的精简答案或稳定中断错误。问题 overlay 只在终端显示。
#### Token 影响
只有已完成或失败的工具结果会增加保留 token。
#### KV Cache 影响
仅追加;答案跟在可复用请求前缀之后。
## 已知限制与暂缓事项
- **只支持 TTY**stdin 与 stdout 都必须是终端;自动化使用 `dsh-cli-demo`
- **一个已配置的终端会话**transcript 与编辑器绑定到一个确切会话 id。
- **应用集群固定不变**JSONL 持久化与 ask-user 工具内置;不同策略需要另一种组合。
- **批准机制独立存在**:此应用回答 `ctx.userInteraction`,而不是 `ctx.approval`;权限提示需要批准服务和回答方。