Merge remote-tracking branch 'origin/master' into fix/intent-draft-sync-echo
This commit is contained in:
6
packages/README.i18n.yaml
Normal file
6
packages/README.i18n.yaml
Normal 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: d7427c3f9892f56185cc1175245f14a6ccea0d25
|
||||
README.zh.md: 6894aa7333f6ba4bc5723871fb77c18b5fb518a1
|
||||
@@ -1,5 +1,7 @@
|
||||
# Packages
|
||||
|
||||
English | [中文](README.zh.md)
|
||||
|
||||
Packages use the `@deepseek-ai/dsh-*` scope. Each is a Cordis `Service` subclass or function plugin; contributions use `ctx.effect()`, `ctx.on()`, or `ctx.waterfall()`. Authoring rules: [package](AGENTS.md) and [root](../AGENTS.md#conventions).
|
||||
|
||||
## Hierarchy
|
||||
|
||||
56
packages/README.zh.md
Normal file
56
packages/README.zh.md
Normal file
@@ -0,0 +1,56 @@
|
||||
# 包
|
||||
|
||||
[English](README.md) | 中文
|
||||
|
||||
所有包都使用 `@deepseek-ai/dsh-*` scope。每个包都是 Cordis `Service` 子类或函数插件;所有贡献通过 `ctx.effect()`、`ctx.on()` 或 `ctx.waterfall()` 注册。编写规则见[包](AGENTS.md)与[根规则](../AGENTS.md#conventions)。
|
||||
|
||||
## 层级结构
|
||||
|
||||
包位于 `packages/<group>/<pkg>/`;组是容器,包名仍为 `@deepseek-ai/dsh-<pkg>`。**每个组 README 是规范的包/ctx 键映射。**
|
||||
|
||||
| 组 | 职责 | 发布预期 |
|
||||
|---|---|---|
|
||||
| [`core/`](core/README.md) | 产品 API 主干:会话、提示词、工具、agent(智能体)服务与具体循环 | 产品:稳定表面 |
|
||||
| [`goal/`](goal/README.md) | 持久化的同会话 goal 状态与生命周期 | 产品:稳定表面 |
|
||||
| [`llm/`](llm/README.md) | LLM(大语言模型)能力系列:抽象服务 + 提供方适配器 | 产品:稳定表面 |
|
||||
| [`bash/`](bash/README.md) | Bash 能力系列:执行器 seam、本地实现、面向模型的工具 | 产品:稳定表面 |
|
||||
| [`pty/`](pty/README.md) | 持久 PTY 能力系列:按所有者隔离的会话、本地实现和面向模型的工具 | 产品:稳定表面 |
|
||||
| [`code-runtime/`](code-runtime/README.md) | 代码执行能力系列:面向模型所写程序的运行时 seam + worker 线程后端 | 产品:稳定表面 |
|
||||
| [`sandbox/`](sandbox/README.md) | 进程限制 seam;bwrap/Landlock/Seatbelt 后端 | 产品:稳定表面 |
|
||||
| [`fs/`](fs/README.md) | 文件系统能力系列:seam、本地实现、面向模型的文件工具、bash 后端发现工具 | 产品:稳定表面 |
|
||||
| [`lsp/`](lsp/README.md) | LSP 能力系列:seam、通用 stdio 提供方和 `lsp` 工具 | 产品:稳定表面 |
|
||||
| [`skill/`](skill/README.md) | Skill(技能)能力系列:提供方注册表、本地提供方和面向模型的目录/加载器 | 产品:稳定表面 |
|
||||
| [`compact/`](compact/README.md) | 压缩(compaction)能力系列:抽象 seam + 基础后端(工具延后) | 产品:稳定表面 |
|
||||
| [`context/`](context/README.md) | 模型可见请求上下文,包括 workspace 指令和时间上下文 | 产品:稳定表面 |
|
||||
| [`subagent/`](subagent/README.md) | Subagent 能力系列:提供方注册表 seam 和面向模型的委托工具 | 产品:稳定表面 |
|
||||
| [`tasks/`](tasks/README.md) | 通用后台任务运行时和面向模型的 `task_*` 控制工具 | 产品:稳定表面 |
|
||||
| [`workflow/`](workflow/README.md) | 工作流能力系列:脚本引擎 seam、worker 线程引擎、面向模型的 `workflow` 与新 agent `ralph` 工具 | 产品:稳定表面 |
|
||||
| [`web/`](web/README.md) | Web 能力系列:seam、搜索/获取提供方实现和面向模型的 Web 工具 | 产品:稳定表面 |
|
||||
| [`spill/`](spill/README.md) | 溢出能力系列:存储 seam、本地实现、工具结果溢出策略 | 产品:稳定表面 |
|
||||
| [`todo/`](todo/README.md) | Todo/规划系列:面向模型的 `todo_write` 工具 | 产品:稳定表面 |
|
||||
| [`plan/`](plan/README.md) | Plan 协作状态,提供直接进入命令与经评审的退出 | 产品:稳定表面 |
|
||||
| [`timeout/`](timeout/README.md) | 工具调用超时策略:`tools/execute` 截止时间强制执行器 | 产品:稳定表面 |
|
||||
| [`guard/`](guard/README.md) | 循环卫生守卫:建议性重复调用提醒 | 产品:稳定表面 |
|
||||
| [`cordis/`](cordis/README.md) | 自指运行时工具集:检查实时运行时的插件与服务,挂载/卸载模型所写插件([设计](../.agents/notes/implemented/feature/2026-07-08-self-referential-cordis-toolset.md)) | 产品:稳定表面 |
|
||||
| [`hooks/`](hooks/README.md) | 钩子桥接 + 共享 Claude Code/Codex 协议格式库 | 产品:稳定表面 |
|
||||
| [`session-persistence/`](session-persistence/README.md) | 持久化能力系列:seam + JSONL/SQLite 后端 | 产品:稳定表面 |
|
||||
| [`session-query/`](session-query/README.md) | 会话检索系列:逻辑语料库、有界读取、血缘、事件关系、语义过滤和 SQLite 全文搜索 | 产品:稳定表面 |
|
||||
| [`session-title/`](session-title/README.md) | 日志支撑的会话标题:回退服务、共享 LLM 策略和选用提供方 | 产品:稳定表面 |
|
||||
| [`storage/`](storage/README.md) | 非会话存储中枢 + 后端 + 领域形式 | 产品:稳定表面 |
|
||||
| [`workspace/`](workspace/README.md) | Workspace 实体 | 产品:稳定表面 |
|
||||
| [`sdk/`](sdk/README.md) | 项目 SDK 工具 | 产品:稳定表面 |
|
||||
| [`acp/`](acp/README.md) | 仅面向自动化的 Agent Client Protocol 服务器 | 产品:稳定表面 |
|
||||
| [`ui/`](ui/README.md) | 人类/客户端集成:TUI 与 JSON-RPC、批准/交互 seam、用户问答工具 | 产品:稳定表面 |
|
||||
| [`examples/`](examples/README.md) | 演示组合包(agent-spine + TUI/CLI/ACP/JSON-RPC bin),由叶节点加载 | 支持:示例基础设施 |
|
||||
| [`support/`](support/README.md) | 支持基础设施(testkit、不变式、回放、Loader 冒烟测试) | 支持:兼容性预期较低 |
|
||||
| [`util/`](util/README.md) | 组间共享的低层零依赖工具(`Branded<B>`、Harness home/路径辅助函数、超时、保留策略) | 支持:小型、稳定、无 harness 依赖 |
|
||||
|
||||
组用于区分产品 API 与支持基础设施。新包加入现有组;新组则更新其 README 和此表。
|
||||
|
||||
## 依赖
|
||||
|
||||
依赖图由工具生成:[docs/module-graph.md](../docs/module-graph.md)(`pnpm run gen-module-graph`,CI 中有新鲜度门禁)。
|
||||
|
||||
**扩展插件依赖接口,绝不依赖具体循环。** `dsh-agent-loop` 可替换;UI、钩子和工具插件使用 `dsh-agent`。包括 `dsh-agent-spine-demo` 在内的组合包可以依赖主干插件。能力拆分为接口/实现/消费方包;详见[能力 seam](../.agents/notes/implemented/architecture/2026-06-13-capability-seams.md)。
|
||||
|
||||
包 README 覆盖用途、API、扩展点和[模型体验](../docs/cookbook/adding-a-package.md#4-write-the-package-readme);列入模型无关[省略允许清单](../scripts/verify-package-readme-model-experience.ts)的包除外。它们还要包含 `## Known Limitations and Deferred Work`,或使用其[允许清单](../scripts/verify-package-readme-limitations.ts)。
|
||||
6
packages/acp/README.i18n.yaml
Normal file
6
packages/acp/README.i18n.yaml
Normal 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: 326615210e5cfc39004fc5ab7462623089ac4126
|
||||
README.zh.md: 9999ecdd019501c3f501a6c69fab5e0ccfaf555c
|
||||
@@ -1,5 +1,7 @@
|
||||
# acp/ — Agent Client Protocol automation
|
||||
|
||||
English | [中文](README.zh.md)
|
||||
|
||||
The ACP group exposes harness agents to programmatic clients. It is an interoperability transport, not a presentation or human-interaction layer.
|
||||
|
||||
| Package | Role |
|
||||
|
||||
11
packages/acp/README.zh.md
Normal file
11
packages/acp/README.zh.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# acp/:Agent Client Protocol 自动化
|
||||
|
||||
[English](README.md) | 中文
|
||||
|
||||
ACP(Agent Client Protocol)组将 harness 中的 agent(智能体)公开给程序化客户端。它是互操作传输层,而非展示层或人机交互层。
|
||||
|
||||
| 包 | 职责 |
|
||||
|---|---|
|
||||
| [`acp/`](acp/README.md) | 仅面向自动化的 ACP 服务器:新文本会话、已提交的 assistant 输出、机器权限策略、取消和由连接拥有的清理。 |
|
||||
|
||||
与之匹配的进程外 subagent 客户端仍位于 [`subagent/subagent-acp`](../subagent/subagent-acp/README.md),因为它实现 subagent 提供方接口;任意 ACP 客户端都可以驱动同一服务器契约。
|
||||
6
packages/acp/acp/README.i18n.yaml
Normal file
6
packages/acp/acp/README.i18n.yaml
Normal 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: 1b188b994d17ce56e8d5df019ddef755338fcc88
|
||||
README.zh.md: f8abe9e45a5efffa436513f7d4a931c69c624b84
|
||||
@@ -1,5 +1,7 @@
|
||||
# @deepseek-ai/dsh-acp
|
||||
|
||||
English | [中文](README.zh.md)
|
||||
|
||||
Automation-only [Agent Client Protocol](https://agentclientprotocol.com) server over JSON-RPC stdio. Programmatic clients create fresh harness agents, send text prompts, collect committed assistant text, resolve one-shot permission requests by policy, and cancel work. The primary in-repository client is [`dsh-subagent-acp`](../../subagent/subagent-acp/README.md).
|
||||
|
||||
This package is a transport adapter, not a UI integration or a capability seam. It does not expose editor navigation, transcript replay, commands, modes, configuration pickers, elicitation, reasoning, plans, titles, or tool presentation. Interactive rendering and human questions belong to the web and TUI modules.
|
||||
|
||||
79
packages/acp/acp/README.zh.md
Normal file
79
packages/acp/acp/README.zh.md
Normal file
@@ -0,0 +1,79 @@
|
||||
# @deepseek-ai/dsh-acp
|
||||
|
||||
[English](README.md) | 中文
|
||||
|
||||
通过 JSON-RPC stdio 提供的仅面向自动化的 [Agent Client Protocol](https://agentclientprotocol.com) 服务器。程序化客户端可以创建新 harness agent(智能体)、发送文本提示词、收集已提交的 assistant 文本、通过策略解决一次性权限请求并取消工作。仓库中的主要客户端是 [`dsh-subagent-acp`](../../subagent/subagent-acp/README.md)。
|
||||
|
||||
此包(package)是传输适配器,而非 UI 集成或能力 seam。它不公开编辑器导航、transcript(文本记录)回放、命令、mode、配置选择器、信息征集、推理、计划、标题或工具展示。交互渲染与人类问题属于 Web 和 TUI 模块。
|
||||
|
||||
## 插件
|
||||
|
||||
`apply(ctx, config)` 在 stdin/stdout 上打开 `AgentSideConnection` 并驱动 `ctx.agents`。Stdout 专用于协议帧。
|
||||
|
||||
| 配置 | 默认值 | 含义 |
|
||||
|---|---|---|
|
||||
| `provider` | 无 | 每个已创建 agent 的初始提供方路由。 |
|
||||
| `model` | 无 | 每个已创建 agent 的初始模型。 |
|
||||
|
||||
两个字段都是可选的,以便由另一个 agent/request 监听器提供目标。可运行 ACP 组合同时要求两者。
|
||||
|
||||
## 协议契约
|
||||
|
||||
| 方法 | 行为 |
|
||||
|---|---|
|
||||
| `initialize` | 协商受支持的版本,并仅公布基线提示词(无图像、音频或嵌入上下文能力)。不公布会话、编辑器、终端、文件系统或 MCP 能力。 |
|
||||
| `authenticate` | 空操作,因为服务器不公布身份验证方法。 |
|
||||
| `session/new` | 使用绝对主 `cwd` 创建新 agent;接受空的 `additionalDirectories` 和 `mcpServers`,拒绝非空值。 |
|
||||
| `session/prompt` | 连接文本块,将基线资源链接渲染为带方括号的文本引用,拒绝空输入或超出基线的输入,每个会话只允许一个正在处理的请求,并从该请求拥有的持久 `turn/end` 结算。 |
|
||||
| `session/cancel` | 仅取消被定址的 agent,并将其待处理提示词结算为 `cancelled`;未知 id 为空操作。 |
|
||||
| `session/update` | 为每个非空文本块发出一个 `agent_message_chunk`;这些文本块来自已提交的 `assistant/message`。省略原始增量和非消息事件。 |
|
||||
| `session/request_permission` | 为携带工具调用 id 的桥接层所有批准请求提供一次性允许/拒绝选项。客户端可以自动回答。 |
|
||||
|
||||
一个连接可以拥有多个会话。桥接层使用带品牌的 session id 为记录建键,并在路由事件或权限请求前检查精确的 agent 标识。每个会话都有独立的提示词槽位、workspace、取消路径和 disposer。
|
||||
|
||||
已提交消息输出有意以逐 token 延迟换取干净的自动化结果。未提交的提供方分片和重试尝试无法泄漏部分文本;推理与工具活动仍保留在会话日志中,以便其他界面观测。
|
||||
|
||||
## 生命周期
|
||||
|
||||
客户端断开与 Cordis 释放共用同一个记忆化清理流程。桥接层先拒绝新会话和提示词,结算待处理提示词,然后并行释放所有已拥有的 agent handle,并等待它们的循环/会话清理完成。因此,仅 ACP 的插件重载不会遗留 agent。
|
||||
|
||||
## 运行
|
||||
|
||||
`pnpm --dir /path/to/deepseek-harness run demo:acp` 启动仓库的自动化服务器组合。父 harness 可以通过 [`@deepseek-ai/dsh-subagent-acp`](../../subagent/subagent-acp/README.md) spawn 它;其他 ACP 客户端只需上述核心方法。
|
||||
|
||||
## 模型体验
|
||||
|
||||
### 提示词文本
|
||||
|
||||
#### 模型所见内容
|
||||
|
||||
`session/prompt` 文本块会原样连接为一条用户消息;基线资源链接会在该消息中表示为带方括号的 `[resource_link name=… uri=…]` 引用,模型可以使用自身工具打开它。协议元数据、客户端能力、权限选择和 session id 绝不进入模型请求。
|
||||
|
||||
#### Token 影响
|
||||
|
||||
提示词 token 取决于数据,并保留在该会话的历史中直到压缩。并发 ACP 会话保留独立上下文。
|
||||
|
||||
#### KV Cache 影响
|
||||
|
||||
仅追加;新用户消息位于可复用请求前缀之后,不会使先前缓存条目失效。
|
||||
|
||||
### 权限决策
|
||||
|
||||
#### 模型所见内容
|
||||
|
||||
没有直接内容。拥有该决策的工具通过常规工具结果路径记录允许、拒绝、取消或不可用结果。
|
||||
|
||||
#### Token 影响
|
||||
|
||||
只有拥有该决策的工具结果会贡献 token。
|
||||
|
||||
#### KV Cache 影响
|
||||
|
||||
通过所属工具结果仅追加。
|
||||
|
||||
## 已知限制与延后工作
|
||||
|
||||
- **仅新会话**:不支持加载、列出、恢复、删除和 fork。
|
||||
- **仅基线提示词和一个 workspace**:图像、音频、嵌入资源、非空附加目录和 MCP 服务器都会被拒绝;资源链接会被展平为文本引用,而不是已获取内容。
|
||||
- **仅已提交答案**:实时进度、推理、工具活动、计划、标题和用量不上线。
|
||||
- **连接拥有的生命期**:一个连接会释放其所有会话;尚未实现每会话关闭。
|
||||
6
packages/bash/README.i18n.yaml
Normal file
6
packages/bash/README.i18n.yaml
Normal 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: 08b36270800cdd79c82d6781bbfb2e12e2dc2060
|
||||
README.zh.md: a98506a6cdf41e5b298b40e1b8e1faf0c4c917d2
|
||||
@@ -1,5 +1,7 @@
|
||||
# bash/ — bash capability family
|
||||
|
||||
English | [中文](README.zh.md)
|
||||
|
||||
The canonical three-package capability seam (see [capability seams](../../.agents/notes/implemented/architecture/2026-06-13-capability-seams.md)): an abstract executor interface, concrete implementations, and the model-facing tool that consumes it. All **product** packages.
|
||||
|
||||
| Package | Role | ctx key |
|
||||
|
||||
14
packages/bash/README.zh.md
Normal file
14
packages/bash/README.zh.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# bash/:bash 能力家族
|
||||
|
||||
[English](README.md) | 中文
|
||||
|
||||
规范的三包能力 seam(见[能力 seam](../../.agents/notes/implemented/architecture/2026-06-13-capability-seams.md)):抽象执行器接口、具体实现,以及消费该接口的面向模型工具。这些全是**产品** 包。
|
||||
|
||||
| 包 | 职责 | ctx key |
|
||||
|---|---|---|
|
||||
| `bash/` | 抽象 bash 执行器 seam(接口 + 词汇;沙箱结果事实携带 [`sandbox/`](../sandbox/README.md) seam 的模式/强制执行词汇) | `ctx.bash` |
|
||||
| `bash-local/` | 本地子进程 `BashExecutor` 实现 | (注册 `ctx.bash`) |
|
||||
| `bash-sandbox/` | 消费沙箱的 `BashExecutor`(通过 `ctx.sandbox` 包装每个命令 argv,标记拒绝/强制执行事实;扩展 `bash-local` 的机制) | (注册 `ctx.bash`) |
|
||||
| `tool-bash/` | 面向模型的 `bash` schema;后台进程注册到通用 [`tasks/`](../tasks/README.md) 运行时 | (注册到 `ctx.tools`) |
|
||||
|
||||
接口位于 `bash/bash/`。以 `bash-sandbox` 替换 `bash-local`,同时不改动接口或工具,正是这种拆分存在的意义:叶级 `cordis.yml` 选择一个执行器配置项;受限实现还需选择一个 `ctx.sandbox` 提供方配置项(见 [acp-agent 示例的默认组合](../../examples/acp-agent/))。
|
||||
6
packages/bash/bash-local/README.i18n.yaml
Normal file
6
packages/bash/bash-local/README.i18n.yaml
Normal 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: 1668f33e8acf6d749d4d3753478c12d48a19ac3c
|
||||
README.zh.md: 0e0a4ad41b532e39f6f2470aa981a08b6d6230c1
|
||||
@@ -1,5 +1,7 @@
|
||||
# @deepseek-ai/dsh-bash-local
|
||||
|
||||
English | [中文](README.zh.md)
|
||||
|
||||
Local-subprocess implementation of the `@deepseek-ai/dsh-bash` executor seam: `LocalBashExecutor` spawns `bash -c <command>` per call in its own process group, collects bounded output with size-limited full-stream spill files, and escalates kills SIGTERM→SIGKILL across the whole group.
|
||||
|
||||
The package root exports the default and named `LocalBashExecutor` plugin plus its `Config`; subprocess plumbing stays internal to the implementation package.
|
||||
|
||||
49
packages/bash/bash-local/README.zh.md
Normal file
49
packages/bash/bash-local/README.zh.md
Normal file
@@ -0,0 +1,49 @@
|
||||
# @deepseek-ai/dsh-bash-local
|
||||
|
||||
[English](README.md) | 中文
|
||||
|
||||
`@deepseek-ai/dsh-bash` 执行器 seam 的本地子进程实现:`LocalBashExecutor` 每次调用都会在独立进程组中 spawn `bash -c <command>`,收集有界输出,并用限制大小的完整流 spill 文件保留超量内容,随后针对整个进程组从 SIGTERM 逐步升级为 SIGKILL。
|
||||
|
||||
包根目录导出默认与具名的 `LocalBashExecutor` 插件及其 `Config`;子进程管道细节保留在该实现包内部。
|
||||
|
||||
## 配置
|
||||
|
||||
```yaml
|
||||
- id: bash
|
||||
name: '@deepseek-ai/dsh-bash-local'
|
||||
config:
|
||||
cwd: /path/to/workspace # default: process.cwd()
|
||||
timeoutMs: 120000 # default foreground timeout
|
||||
maxTimeoutMs: 600000 # cap for per-call overrides
|
||||
maxOutputBytes: 64000 # per-stream in-memory cap; overflow spills to disk
|
||||
maxSpillBytes: 67108864 # per-stream full-output spill cap
|
||||
graceMs: 3000 # kill escalation and post-exit pipe-drain grace
|
||||
```
|
||||
|
||||
## 行为(以及设计来源)
|
||||
|
||||
设计时调研了 Claude Code、OpenCode、Codex 和 pi 的 bash 工具,主要取舍如下:
|
||||
|
||||
- **每次调用都 spawn,不保留 shell 状态**:每次调用都启动新的非登录 `bash -c`(行为确定,不读取 rc 文件)。调研的四种工具均会每次调用单独 spawn。`XXX(stateful-shell)` 位于 `src/run.ts`,记录了两种已验证的有状态设计(Claude Code 仅持久化 cwd;Codex 使用 PTY exec 会话),供真实工作流程需要时采用。
|
||||
- **使用逐步升级终止整个进程组**:子进程使用 `detached` spawn(拥有独立进程组);终止时先向该组发送 SIGTERM,经过 `graceMs` 宽限期后再发送 SIGKILL(默认 3 秒,沿用 OpenCode 的升级策略;管道与子 shell 会随父进程一起结束)。主 shell 退出后,继承的 stdout/stderr 管道也只获得同样有界的排空宽限期,因此存活的后代进程无法无限期地阻止命令结束。系统会容忍 ESRCH;脱离该组重新挂载的 daemon 仍可能存活,这与调研工具的局限相同。
|
||||
- **保留尾部的截断 + 有界 spill 文件**:输出超过 `maxOutputBytes` 后,内存中保留尾部(错误/结果通常聚集在末尾,沿用 pi/OpenCode 的理由),同时将完整流追加到临时文件,并在可用时报告该路径。前台 `BashExecRequest.stdoutMaxBytes` 可为某个受信任调用方提高单次 stdout 捕获预算;stderr 和后台任务仍使用 `maxOutputBytes`。某个流大于 `maxSpillBytes` 时,会丢弃已不完整的 spill,仅返回带截断标记的尾部。如果最终关闭 spill 时报告延迟写回失败,执行器同样不会公布路径,以免声称存在不完整的文件。
|
||||
- **适合模型的环境变量 + 凭证清理**:以 `process.env` 为基础,移除形似凭证的变量(`*KEY*`/`*SECRET*`/`*TOKEN*`)和所有环境中的 `DSH_*` 名称,再设置 `NO_COLOR=1 TERM=dumb PAGER=cat GIT_PAGER=cat`(Codex 硬编码的集合),防止分页器与 ANSI 颜色破坏结果。spec 的普通 `env` 在清理后合并,但会拒绝 `DSH_*`;受管 `dshEnv` 会拒绝普通名称并最后合并,防止遗留嵌套 harness 身份。提供的 stdin 会被写入后关闭;否则 fd 0 指向 `/dev/null`。详见 [stdin/env Agent Note](../../../.agents/notes/implemented/architecture/2026-06-30-bash-stdin-env-trusted-plugin-surface.md) 与 [受管环境 Agent Note](../../../.agents/notes/implemented/feature/2026-07-10-agent-session-identity-and-log-location.md)。
|
||||
- **后台进程**:`start()` 会立即返回实时 `BashProcess` 句柄,不应用超时(Claude Code 在转为后台时会解除超时);句柄的 `readOutput()` 使用全流字节偏移量进行增量读取;dispose 会终止每个运行中的进程并等待其退出。所有具有任务形态的事项(id、所有权、轮询、通知)都属于通用 [`ctx.tasks` 运行时](../../tasks/tasks/README.md),工具层会在其中注册该句柄;本执行器不会接触会话或注册表。
|
||||
|
||||
## 模型体验
|
||||
|
||||
通过 `dsh-tool-bash` 间接影响;该工具会渲染此执行器有界的 stdout/stderr 尾部、后台进程增量、spill 文件路径与基础设施失败。
|
||||
|
||||
#### KV Cache 影响
|
||||
|
||||
不会直接失效;请求前缀变更由具名消费方负责。
|
||||
|
||||
## 已知限制与暂缓事项
|
||||
|
||||
- **自身不受约束**:此执行器始终以 harness 进程的权限运行命令;需要限制的部署可以组合 [`dsh-bash-sandbox`](../bash-sandbox/README.md),每次调用的 allow/deny/ask 策略则属于 `tools/pre-execute`。
|
||||
- **没有持久 shell 或 PTY**:每次调用都启动新的非登录 `bash -c`;仅持久化 cwd 与交互式终端会话均继续暂缓,直到真实工作流程需要它们。
|
||||
- **仅支持 POSIX**:`bash` 二进制、独立进程组、进程组终止以及 SIGTERM→SIGKILL 升级都已硬编码;不支持 Windows。
|
||||
- **凭证清理依赖名称启发式规则**:只匹配 `*KEY*`/`*SECRET*`/`*TOKEN*`;名称不同的 secret(例如 `*PASSWORD*`)会继续传递,对误删变量引入白名单属于已记录的后续工作。
|
||||
- **不会删除已完成的 spill 文件**:有界的完整输出恢复文件(以及每个进程的私有 spill 目录)会在 OS tmpdir 下累积,直到外部机制进行清理;超大的不完整 spill 会被丢弃并立即尝试删除,但清理失败可能留下一个有界文件。
|
||||
|
||||
原始进程处理位于 `src/run.ts`;`src/index.ts` 负责服务接线。
|
||||
6
packages/bash/bash-sandbox/README.i18n.yaml
Normal file
6
packages/bash/bash-sandbox/README.i18n.yaml
Normal 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: ca77a9c626784b29145712535d69de4afbd3a697
|
||||
README.zh.md: c1a65ead539ef3930d70d27f2b176a5346daded3
|
||||
@@ -1,5 +1,7 @@
|
||||
# @deepseek-ai/dsh-bash-sandbox
|
||||
|
||||
English | [中文](README.zh.md)
|
||||
|
||||
Sandbox-consuming implementation of the [`@deepseek-ai/dsh-bash`](../bash/) executor seam. Load it **instead of** `@deepseek-ai/dsh-bash-local`, together with a [`ctx.sandbox`](../../sandbox/sandbox/) provider (e.g. [`@deepseek-ai/dsh-sandbox-local`](../../sandbox/sandbox-local/)) and a [`ctx.sandboxPolicy`](../../sandbox/sandbox-policy/) (which owns the default mode + workspace root, shared with the sandboxed filesystem) — no alternate tool plugin is needed; `dsh-tool-bash` detects the executor's `sandboxMode` capability and adds the escalation fields.
|
||||
|
||||
The package root exports the default and named `SandboxBashExecutor` plugin plus its `Config`; quoting and result-classification helpers stay internal.
|
||||
|
||||
90
packages/bash/bash-sandbox/README.zh.md
Normal file
90
packages/bash/bash-sandbox/README.zh.md
Normal file
@@ -0,0 +1,90 @@
|
||||
# @deepseek-ai/dsh-bash-sandbox
|
||||
|
||||
[English](README.md) | 中文
|
||||
|
||||
消费 [`@deepseek-ai/dsh-bash`](../bash/) 执行器 seam 的沙箱实现。加载它时,应**用它替代** `@deepseek-ai/dsh-bash-local`,并同时加载 [`ctx.sandbox`](../../sandbox/sandbox/) 提供方(例如 [`@deepseek-ai/dsh-sandbox-local`](../../sandbox/sandbox-local/))及 [`ctx.sandboxPolicy`](../../sandbox/sandbox-policy/);后者拥有默认模式 + 工作区根目录,并与受沙箱约束的文件系统共享这些设置。无需使用替代工具插件;`dsh-tool-bash` 会检测执行器的 `sandboxMode` 能力并添加升权字段。
|
||||
|
||||
包根目录导出默认与具名的 `SandboxBashExecutor` 插件及其 `Config`;引号处理与结果分类 helper 保留在内部。
|
||||
|
||||
每条命令的限制方式都是:把本执行器即将 spawn 的精确 `['bash', '-c', command]` argv 交给提供方,再 spawn 其返回的(已包装)argv。由哪种平台 runner 执行限制,以及是否有 runner 可用(必须快速失败并返回结构化 `SANDBOX_UNAVAILABLE` 错误,绝不能静默无约束运行),属于提供方职责;本包只拥有 bash 侧。
|
||||
|
||||
| 模式 | 文件影响 |
|
||||
|---|---|
|
||||
| `read-only`(默认) | 任何位置都不可写(在 `/dev` 中只有 `/dev/null` 节点可写,因此 `>/dev/null` 仍可正常工作) |
|
||||
| `workspace-write` | 只能写入 `workspaceRoot` + `/tmp`(在 bwrap 下为临时目录,在 Landlock 下为宿主 `/tmp`,在 Seatbelt 下为 `/private/tmp` 加每用户临时目录) |
|
||||
| `danger-full-access` | 不作限制;绝不咨询提供方。前台结果携带 `sandbox: { mode, denied: false }`;后台进程句柄不携带沙箱事实。 |
|
||||
|
||||
语义:
|
||||
|
||||
- **拒绝是结果事实。** 如果一次失败运行的 stderr 包含所选后端自身的拒绝方言,即提供方在每次包装时加上的特征(bwrap 下的 EROFS 文本、Landlock 下的 EACCES、Seatbelt 下的 EPERM),则结果报告 `BashRunResult.sandbox.denied: true`(从已收集的 stderr 尾部进行保守分类)。每次受限制运行还会携带执行时模式(`result.sandbox.mode`)与提供方强制执行完整性(`result.sandbox.enforcement`:`full`,或在较旧 Landlock ABI 上为 `partial`)。
|
||||
- **Runner 失败是沙箱失败,绝不是命令失败。** 前台执行会抛出 `SANDBOX_UNAVAILABLE`;已结算的后台进程会标记 `process.sandbox.runnerFailed`,bash 产生方通过通用 `task_output` 渲染它。spawn 失败也会经过结算,因此受限制的后台句柄会保留自身的模式/强制执行事实,并释放每进程计数。
|
||||
- **部署回退,每次调用策略。** [`ctx.sandboxPolicy`](../../sandbox/sandbox-policy/) 为每次工具调用解析完整的 `SandboxExecutionPolicy`:调用会话提供自身的模式覆盖与不可变 cwd 根目录,部署配置则为无 agent 调用提供回退。已批准的升权只更改该策略的模式,会话根目录仍然附着其上。`resolve()` 把策略带入 spec,因此来自不同项目的重叠命令会在各自的根目录与模式下运行、分类和报告。能力事实 `ctx.bash.sandboxMode` 报告已配置的默认值,因此工具层只在装载该执行器时才公布升权。模型只能通过结果事实了解沙箱:静态 bash 工具描述会解释拒绝标记,系统提示词中不会声明当前模式。
|
||||
- **只限制文件影响。** 设计上不限制网络与进程可见性:模式词汇不会声称覆盖后端未强制执行的范围。
|
||||
- 进程机制(spawn、进程组终止、输出收集/spill、后台句柄、凭证清理)继承自 [`dsh-bash-local`](../bash-local/);runner 选择位于 [`dsh-sandbox-local`](../../sandbox/sandbox-local/)。
|
||||
|
||||
seam 上仅拒绝:拒绝是一项已报告事实,本执行器绝不自行协商权限。批准问题位于工具层(`dsh-tool-bash`),由它驱动本包遵守的覆盖。
|
||||
|
||||
```yaml
|
||||
- id: sandbox
|
||||
name: '@deepseek-ai/dsh-sandbox-local'
|
||||
- id: sandbox-policy
|
||||
name: '@deepseek-ai/dsh-sandbox-policy'
|
||||
config:
|
||||
mode: read-only
|
||||
workspaceRoot: !!js process.cwd() # fallback for calls without a session cwd
|
||||
- id: bash
|
||||
name: '@deepseek-ai/dsh-bash-sandbox'
|
||||
```
|
||||
|
||||
无密钥消费方集成证明是 `tests/bwrap.e2e.ts`、`tests/landlock.e2e.ts` 和 `tests/seatbelt.e2e.ts`(通过 `ctx.bash` 驱动真实提供方 + 真实 runner,在真实世界验证,并在相应 runner 缺失时各自自行跳过)。agent-spine e2e 还会在一个 Cordis 上下文中驱动两个并发会话,并证明每个真实 bash 工具调用只能写入自身项目。可运行 demo 见 [acp-agent 示例的默认组合](../../../examples/acp-agent/)。
|
||||
|
||||
## 模型体验
|
||||
|
||||
### 间接的 Bash 工具 schema
|
||||
|
||||
#### 模型看到的内容
|
||||
|
||||
基线是生成的 [`dsh-tool-bash` schema](../../../docs/tool-catalog.md#deepseek-aidsh-tool-bash)。通过公布一个执行限制的 `sandboxMode`,此后端会为 `bash` 增加 `sandbox_permissions`,其 enum 为 `workspace-write` | `danger-full-access`,并增加 `justification`。后端不添加提示词文本,会话的有效模式仍不会声明。
|
||||
|
||||
#### Token 影响
|
||||
|
||||
在 `bash` 可见的请求上增加少量固定 schema;模式切换不增加上下文 token。
|
||||
|
||||
#### KV Cache 影响
|
||||
|
||||
执行器持续公布相同沙箱能力时,前缀保持稳定。更改这些能力会改变 `bash` schema,可能使从该定义起的复用失效;每会话模式切换不会导致失效。
|
||||
|
||||
### 间接的 Bash 工具结果
|
||||
|
||||
#### 模型看到的内容
|
||||
|
||||
在普通有界输出之后,被拒绝的调用会精确追加 `[sandbox: file access denied under <mode> mode]`。当升权可用时,接下来精确追加 `[sandbox: escalation available — retry this exact command once with sandbox_permissions (the narrowest wider mode that suffices) + justification; the approval prompt asks the user]`。已结算的后台 runner 失败则追加 `[sandbox: the sandbox runner itself failed under <mode> mode — the command did not run; this is a sandbox problem, not a command failure]`。
|
||||
|
||||
#### Token 影响
|
||||
|
||||
除普通输出外,正常允许的运行不会增加 token。拒绝或失败会增加上述有条件标记,并保留到压缩。
|
||||
|
||||
#### KV Cache 影响
|
||||
|
||||
仅追加;新可见内容位于可复用请求前缀之后,不会使现有 KV-cache 配置项失效。
|
||||
|
||||
### 间接的 Bash 工具错误
|
||||
|
||||
#### 模型看到的内容
|
||||
|
||||
如果没有 runner 能强制执行受限模式,前台调用会传播 [`SANDBOX_UNAVAILABLE` 错误;它由 `dsh-sandbox` 持有](../../sandbox/sandbox/README.md#confinement-error-indirectly)。如果 runner 在执行时失败,此后端会提供第一行 stderr 作为详细信息。
|
||||
|
||||
#### Token 影响
|
||||
|
||||
该次调用可见的是有条件错误文本,并保留在历史记录中直到压缩。
|
||||
|
||||
#### KV Cache 影响
|
||||
|
||||
仅追加;新可见内容位于可复用请求前缀之后,不会使现有 KV-cache 配置项失效。
|
||||
|
||||
## 已知限制与暂缓事项
|
||||
|
||||
- **限制只覆盖文件影响**:网络访问与进程可见性不变,因此这些模式不是通用安全沙箱。
|
||||
- **拒绝从失败命令的 stderr 推断**:后端特征使该推断可跨平台使用,但匹配的应用错误可能被分类为拒绝,也可能遗漏未出现在保留尾部中的拒绝。
|
||||
- **后台 runner 失败没有即时错误通道**:它记录在已结算进程上,并在调用方使用 `task_output` 读取通用任务时呈现。
|
||||
- **`danger-full-access` 有意绕过 `ctx.sandbox`**:它是显式无约束模式,不是更宽的沙箱 profile。
|
||||
6
packages/bash/bash/README.i18n.yaml
Normal file
6
packages/bash/bash/README.i18n.yaml
Normal 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: b4ee66a1fa2696254a1f2f411b7db5d3190f8370
|
||||
README.zh.md: 151d4bd7ab257234584b9008c96e6356d7e39351
|
||||
@@ -1,5 +1,7 @@
|
||||
# @deepseek-ai/dsh-bash
|
||||
|
||||
English | [中文](README.zh.md)
|
||||
|
||||
The **bash executor seam**: an abstract `BashExecutor` service (`ctx.bash`) defining WHAT a bash backend does — run foreground commands and start background processes — without saying HOW. Task ids, ownership, collection, cancellation, and notices belong to the generic `ctx.tasks` runtime.
|
||||
|
||||
This package is the interface quarter of the bash capability, split so each concern can evolve (and be swapped) independently:
|
||||
|
||||
49
packages/bash/bash/README.zh.md
Normal file
49
packages/bash/bash/README.zh.md
Normal file
@@ -0,0 +1,49 @@
|
||||
# @deepseek-ai/dsh-bash
|
||||
|
||||
[English](README.md) | 中文
|
||||
|
||||
**bash 执行器 seam**:抽象 `BashExecutor` 服务(`ctx.bash`)定义 bash 后端做什么,即运行前台命令与启动后台进程,但不规定如何实现。task id、所有权、收集、取消与通知属于通用 `ctx.tasks` 运行时。
|
||||
|
||||
本包是 bash 能力中负责接口的四分之一,各项职责因此可以独立演进(和替换):
|
||||
|
||||
| 包 | 职责 |
|
||||
|---|---|
|
||||
| `@deepseek-ai/dsh-bash`(本包) | 接口:抽象服务 + 词汇类型 |
|
||||
| `@deepseek-ai/dsh-bash-local` | 实现:本地子进程 |
|
||||
| `@deepseek-ai/dsh-bash-sandbox` | 实现:沿用 `dsh-bash-local` 的机制,但通过 [`ctx.sandbox`](../../sandbox/sandbox/) 限制每次 spawn,并将拒绝报告为结果事实 |
|
||||
| `@deepseek-ai/dsh-tool-bash` | 基于 `ctx.bash`、面向模型的工具 schema |
|
||||
|
||||
该拆分与 LLM seam(`LlmService`/`LlmAdapter`)及 agent 工具调研结果一致:pi 将执行隐藏在 `BashOperations` 接口之后(本地 shell/SSH/VM 后端),Codex 则隐藏在 exec-server 协议之后。`dsh-bash-sandbox` 正是这种替换的实际应用:沙箱执行器位于同一接口之后;消费方检测其 `sandboxMode` 能力并添加升权字段,无需导入实现。容器化或远程执行器也可以同样接入。
|
||||
|
||||
## 服务 API(`ctx.bash`)
|
||||
|
||||
| 成员 | 语义 |
|
||||
|---|---|
|
||||
| `run(spec)` | 前台执行。命令完成时 resolve。**只会因基础设施失败而 reject**(工作目录不可用、shell 缺失、信号已在调用前中止);非零退出、超时终止和中止终止都会 resolve 为描述性 `BashRunResult`。 |
|
||||
| `start(spec)` | 后台执行。立即返回不含任务语义的 `BashProcess` 句柄;**不应用超时**。调用方可以将其适配到 `ctx.tasks`。 |
|
||||
| `sandboxMode` | 工具层的能力事实:沙箱执行器用于限制执行的默认模式(基类中为 `undefined`,即「此执行器不使用沙箱」)。`dsh-tool-bash` 会在注册时读取它,仅当组合确实支持升权字段时才公布这些字段。 |
|
||||
| `BashProcess.readOutput()` | **增量** 读取输出:连续读取绝不会重复交付。因缓冲区边界丢失数据的读取会标记 `lossy`,并指向完整流 spill 文件。 |
|
||||
| `BashProcess.kill()` | 终止进程组。如果进程已结束,返回 `false`。 |
|
||||
|
||||
实现会继承 `BashExecutor` 并实现抽象方法。dispose 必须终止每个运行中的进程并等待其退出,详见 HMR 安全测试。
|
||||
|
||||
## 词汇
|
||||
|
||||
`BashExecRequest`(command、workdir?、timeoutMs?、stdoutMaxBytes?、signal?、stdin?、env?、dshEnv?、sandboxPolicy?)在执行前解析为 `BashExecSpec`(command、workdir、timeoutMs、stdoutMaxBytes、signal?、stdin?、env?、dshEnv?、sandboxPolicy)。`stdoutMaxBytes` 是受信任前台运行的捕获预算,用于必须解析完整有界 stdout 的消费方;面向模型的 bash 工具不公开该字段。`sandboxPolicy` 在请求上可选,在已解析 spec 上必填但可为 null:它携带完整的每次调用模式与工作区根目录。沙箱工具路径通过 `ctx.sandboxPolicy` 从调用会话解析它;沙箱执行器的直接调用方回退到部署策略,非沙箱执行器则携带该字段但不作限制。
|
||||
|
||||
每会话沙箱模式覆盖词汇(`'sandbox/mode'` 事件、`effectiveSandboxMode(events)` fold 以及 `setSandboxMode(session, mode)` 写入路径)不位于此处。它是所有强制执行家族共享的策略状态,属于 [`@deepseek-ai/dsh-sandbox-policy`](../../sandbox/sandbox-policy/)。`run()` 返回 `BashRunResult`;`start()` 返回 `BashProcess`,其增量读取与终止方法由 `dsh-tool-bash` 适配为通用任务注册。沙箱执行器会在前台结果与已结算进程句柄上标记 `BashSandboxInfo`。详见 `src/types.ts` 与 [core-data-structures/bash.md](../../../docs/core-data-structures/bash.md)。
|
||||
|
||||
`stdin` 与普通 `env` 由同进程插件(hooks 桥接、原生插件)设置,用于向 hook 命令提供其 JSON payload 和 `CLAUDE_PROJECT_DIR`/`CLAUDE_PLUGIN_ROOT` 值。`dshEnv` 是受类型限制、仅允许受管 key 的独立受信任 overlay;导出的 `DSH_ENV_PREFIX` 是该 namespace、其 `DshEnvironmentKey` 模板类型、执行器清理、注册表验证、派生内置名称与模型指引的单一真源。模型 bash 使用 `ctx.bashEnv` 收集的当前快照。实现会移除继承的受管 key,拒绝普通 `env` 中的这些名称,再合并 `dshEnv`,因此省略的当前事实不会回退到陈旧环境状态。面向模型的工具不公开任何一个字段。这三者在已解析 spec 上仍然可选;缺失表示没有输入/overlay。详见 [bash-stdin-env Agent Note](../../../.agents/notes/implemented/architecture/2026-06-30-bash-stdin-env-trusted-plugin-surface.md) 与 [会话环境 Agent Note](../../../.agents/notes/implemented/feature/2026-07-10-agent-session-identity-and-log-location.md)。
|
||||
|
||||
## 模型体验
|
||||
|
||||
通过 `dsh-tool-bash` 间接影响;该工具会将执行器输出与沙箱事实转为指引和保留的工具结果 token。
|
||||
|
||||
#### KV Cache 影响
|
||||
|
||||
不会直接失效;请求前缀变更由具名消费方负责。
|
||||
|
||||
## 已知限制与暂缓事项
|
||||
|
||||
- **没有交互式输入词汇**:`stdin` 只会在 spawn 时写入一次并关闭;seam 不提供向运行中任务继续输入的通道,也没有 PTY 会话概念。
|
||||
- **前台超时始终由执行器拥有**:seam 上的调用方拥有 deadline 模式已由 [工具调用超时策略 Agent Note](../../../.agents/notes/implemented/architecture/2026-07-07-tool-call-timeout-policy.md) 明确暂缓。
|
||||
6
packages/bash/tool-bash/README.i18n.yaml
Normal file
6
packages/bash/tool-bash/README.i18n.yaml
Normal 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: 965ae25a5e29a4f767adfcb73e4a77f1060e4b46
|
||||
README.zh.md: 60be5c5ca5624719f5ca651a78b6ba56f3f3df06
|
||||
@@ -1,5 +1,7 @@
|
||||
# @deepseek-ai/dsh-tool-bash
|
||||
|
||||
English | [中文](README.zh.md)
|
||||
|
||||
The model-facing `bash` tool registered over the `ctx.bash` executor seam. Foreground execution stays behind that seam; a background process handle is registered with the generic `ctx.tasks` runtime and controlled through `task_output`, `task_list`, and `task_kill` from `@deepseek-ai/dsh-tool-tasks`.
|
||||
|
||||
Requires a loaded executor implementation (e.g. `@deepseek-ai/dsh-bash-local`); the plugin stays pending until `ctx.bash` exists (`inject: ['tools', 'bash', 'systemPrompt']`).
|
||||
|
||||
158
packages/bash/tool-bash/README.zh.md
Normal file
158
packages/bash/tool-bash/README.zh.md
Normal file
@@ -0,0 +1,158 @@
|
||||
# @deepseek-ai/dsh-tool-bash
|
||||
|
||||
[English](README.md) | 中文
|
||||
|
||||
模型侧 `bash` 工具,注册在 `ctx.bash` 执行器 seam 上。前台执行始终位于该 seam 之后;后台进程句柄会注册到通用 `ctx.tasks` 运行时,并通过 `task_output`、`task_list` 和 `task_kill` 控制;这些工具由 `@deepseek-ai/dsh-tool-tasks` 提供。
|
||||
|
||||
需要加载执行器实现(例如 `@deepseek-ai/dsh-bash-local`);在 `ctx.bash` 可用之前,插件会保持等待状态(`inject: ['tools', 'bash', 'systemPrompt']`)。
|
||||
|
||||
包(package)根只公开 Cordis 插件契约(`name`、`inject`、`Config`、`apply`);结果渲染和后台进程适配仍是实现细节,由同包测试覆盖。
|
||||
|
||||
插件还会提供 `tool:bash` 提示词段落(顺序 105):检查每个结果中的 `[exit code: N]` 标记,发现失败时先调查原因再继续。
|
||||
|
||||
## 工具
|
||||
|
||||
### `bash`
|
||||
|
||||
| 参数 | 类型 | 说明 |
|
||||
|---|---|---|
|
||||
| `command` | string(必填) | 通过 `bash -c` 运行。调用之间不保留状态;请使用 `workdir`,不要使用 `cd`。 |
|
||||
| `description` | string(必填) | 用一行主动语态概述命令(5~10 个词),仅用于 UI/日志显示,不影响执行。 |
|
||||
| `timeoutMs` | number | 以毫秒为单位覆盖超时时间。执行器会应用其配置的默认值和上限。 |
|
||||
| `workdir` | string | 本次调用的工作目录。默认为调用方 agent(智能体)会话 cwd 的文件系统标识(`session.header.cwd`),使每个会话都在自己的工作区中运行;相对 `workdir` 也以同一标识为基准解析。 |
|
||||
| `run_in_background` | boolean | 立即返回 task id;不应用超时。 |
|
||||
| `sandbox_permissions` | string enum | 仅当已挂载的执行器启用沙箱时才会公开(`ctx.bash.sandboxMode` 报告一个具有限制作用的默认值):被拒命令所需的更宽模式,取自封闭的目标词汇 `workspace-write`/`danger-full-access`(绝不能缩减为执行器默认值;有效模式按会话确定,执行时会基于它检查是否严格拓宽,未拓宽的请求直接失败,不会向任何人发起提示)。 |
|
||||
| `justification` | string | 必须与 `sandbox_permissions` 一同提供(缺少任一项都会产生验证错误):用一句话向用户解释此命令为何需要这项更宽权限。 |
|
||||
|
||||
执行前,`command`、`workdir` 和 `timeoutMs` 会通过 `ctx.bash.resolve()` 依据执行器配置默认值完成解析,因此执行器 seam(`BashExecSpec`)收到显式的 `workdir`/`timeoutMs` 值。工具层会根据调用方 agent 的 `session.header.cwd` 应用工作目录默认值,然后才调用 `resolve()`:由于 N 个会话共享一个执行器,逐会话 cwd 必须来自 `exec.agent`;只有无法取得会话 cwd 时,执行器才回退到自身配置/`process.cwd()`。存在沙箱策略时,工具会复用已经规范化的 `workspaceRoot` 作为工作目录基准,防止限制逻辑与进程启动过程对同一个会话路径拼写产生不同解析结果。
|
||||
|
||||
### 托管 shell 环境
|
||||
|
||||
每次模型发起的前台或后台 bash 调用都会收到新收集的一组可信 `DSH_*` 环境变量。`DSH_HOME` 是由 [`@deepseek-ai/dsh-paths`](../../util/paths/README.md) 解析出的 Harness home 绝对路径(依次采用 `dshHome` 配置、环境中的 `$DSH_HOME`、`~/.dsh`),`DSH_SHELL=1` 则标识受托管的子进程。Agent 调用还会收到 `DSH_SESSION_ID=agent.session.header.id`;当活跃的持久化 seam 找到 JSONL 产物时,也会收到 `DSH_SESSION_JSONL=<absolute target path>`。JSONL 路径只是位置提示:首次 flush 前它可能尚不存在,也可能不包含当前缓冲的轮次,并且它不是授权凭据。
|
||||
|
||||
`ctx.bashEnv` 持有收集过程。其他插件可以注册具有 effect 作用域的贡献方,提供稳定名称、已声明的键/说明以及 `resolve(execution: ToolExecution)`;重复持有或运行时返回未声明的键会快速失败,而 `list()` 无需执行提供方即可列举声明。Harness 内置项保留 `DSH_HOME`、`DSH_SHELL` 和 `DSH_SESSION_ID`;tool-bash 的持久化转换器持有 `DSH_SESSION_JSONL`,其值来自后端无关的 `sessionPersistence.locate()` seam。
|
||||
|
||||
```ts
|
||||
import type { Context } from 'cordis'
|
||||
import type {} from '@deepseek-ai/dsh-tool-bash'
|
||||
|
||||
export const inject = ['bashEnv']
|
||||
|
||||
export function apply(ctx: Context): void {
|
||||
ctx.bashEnv.register({
|
||||
name: 'deployment-region',
|
||||
variables: { DSH_DEPLOYMENT_REGION: { description: 'Current deployment region.' } },
|
||||
resolve: execution => execution.agent === undefined ? {} : { DSH_DEPLOYMENT_REGION: 'cn-north' },
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
overlay 根据当前 `ToolExecution` 计算,并通过专用的 `BashExecRequest.dshEnv` 通道传递。本地执行器会先删除继承的所有 `DSH_*`,再合并该快照,因此嵌套 harness 和并发的父/子 agent 不会泄漏陈旧身份。它绝不会修改 `process.env`。工具说明只教授通用 `$DSH_*` 约定,不会点名持久化专用变量,也不会添加永久的系统提示词段落。
|
||||
|
||||
结果文本依次包含 stdout、可选的 `[stderr]` 段落和适用的沙箱拒绝、超时、信号、退出代码及截断标记。超时与最终退出状态分别报告;非零退出仍是由模型解释的结果,不会成为 `isError`。截断结果会链接安全的完整 spill 文件,或报告文件不可用。只有 spawn 错误和中止等基础设施故障才会产生 `isError`。
|
||||
|
||||
已完成前台进程的规范成功值为 `{ kind: 'foreground', ...BashRunResult }`,已发布任务则为 `{ kind: 'background', taskId }`。Native renderer 保留上述文本,包括精确的 `started background task <id>`;程序化消费方使用带类型字段,无需解析这些字符串。执行器的流上限仍是 `BashRunResult` 的采集限制,并携带其 spill 路径。
|
||||
|
||||
当 `run_in_background` 为 true 时,此插件会在 spawn 前预检 `ctx.tasks.start()`,把调用方 agent 注册为持有者,并将返回的 `BashProcess` 句柄适配为通用的取消/完成/增量输出钩子。任务运行时持有 id、跨会话隔离、完成通知、等待和 dispose(资源释放)清理;此插件只把 bash 退出/沙箱事实映射为任务输出和结果详情。`enableRunInBackground: false` 会移除该参数,并在执行时拒绝强制后台调用。
|
||||
|
||||
## UI 展示
|
||||
|
||||
工具持有自己的 `presentCall`/`presentResult` 渲染意图。前台调用是终端卡片,包含命令、说明、cwd、原始输出和解析后的退出状态。后台启动只返回 task id,因此使用通用执行卡片;通用 `task_*` 工具持有各自的卡片。这些 presenter 是纯函数,可安全回放。
|
||||
|
||||
## 工具仅使用具名参数构建请求
|
||||
|
||||
`BashExecRequest` seam 携带可选的 `stdoutMaxBytes`、`stdin`、普通 `env` 和托管 `dshEnv`,供可信进程内插件及此工具的环境注册表使用。模型侧工具不公开 `stdoutMaxBytes`、`stdin` 或 `env`:它使用具名的命令/工作目录/超时/信号/沙箱字段,加上从注册表收集的 `dshEnv` 来构建请求。额外模型键会被忽略,无法替换托管值。Shell 语法可以提供等价的命令级行为,而本地执行器会清除环境中的凭据和陈旧 `DSH_*` 值。参见 [stdin/env Agent Note(agent 决策记录)](../../../.agents/notes/implemented/architecture/2026-06-30-bash-stdin-env-trusted-plugin-surface.md)。
|
||||
|
||||
## 权限与升权
|
||||
|
||||
除非启用沙箱的执行器([`dsh-bash-sandbox`](../bash-sandbox/))限制命令,否则命令以执行器的完整权限运行。仅拒绝型沙箱会把拒绝作为结果事实报告,并在此渲染为拒绝标记;逐调用的允许/拒绝/询问策略由 `tools/pre-execute` waterfall(瀑布式事件)负责(参见 docs/architecture.md)。
|
||||
|
||||
需要升权的 bash 调用会在执行前解析 `ctx.approval`。`allowed-once` 只对该次调用应用请求模式;审批被拒、取消、不可用或缺少审批上下文时,命令完全不会执行,并返回不同的错误。发生真实拒绝后,模型可以在同一轮次中使用满足需要的最窄模式和理由重试同一命令一次;审批提示本身就是征求同意的步骤。升权绝不能预先推测,禁用或拒绝审批即为最终结果。其理由由 [沙箱 Agent Note](../../../.agents/notes/implemented/feature/2026-07-06-sandbox.md) 持有。
|
||||
|
||||
## 逐会话模式切换
|
||||
|
||||
对于启用沙箱的执行器,每次调用依次按单次升权、会话覆盖、执行器默认值解析模式。未启用沙箱以及没有 agent 的调用不携带会话覆盖。提示词和切换通知均不公布当前常驻模式;拒绝结果会在边界相关时报告有效模式。参见 [`dsh-bash` 整合](../bash/README.md)和[沙箱切换契约](../../../.agents/notes/implemented/feature/2026-07-06-sandbox.md)。
|
||||
|
||||
## 模型体验
|
||||
|
||||
### 系统提示词
|
||||
|
||||
#### 模型看到的内容
|
||||
|
||||
此插件注册作用域内的每个请求都包含下方 bash 指引。启用沙箱的执行器不会添加模式声明或切换通知。作用域工具限制可以隐藏 schema,但不会移除这个独立注册的段落。
|
||||
|
||||
##### Bash 指引
|
||||
|
||||
```markdown
|
||||
Check the [exit code: N] marker on every bash result; investigate failures before moving on.
|
||||
```
|
||||
|
||||
#### Token 影响
|
||||
|
||||
插件活跃期间,每个请求都会产生少量固定输入开销,不受沙箱模式或模式切换影响。
|
||||
|
||||
#### KV Cache 影响
|
||||
|
||||
只要注册作用域和提示词文本不变,前缀即可稳定复用。插件激活或 dispose 可能从此提示词段落开始使复用失效;沙箱模式切换不会。
|
||||
|
||||
### 工具 schema
|
||||
|
||||
#### 模型看到的内容
|
||||
|
||||
模型会看到生成的 [`bash` schema](../../../docs/tool-catalog.md#deepseek-aidsh-tool-bash)。仅当此生产方启用 `run_in_background` 时,该字段才会出现;仅当已挂载执行器声明支持沙箱时,`sandbox_permissions` 和 `justification` 才会出现。Agent 作用域的工具限制可以移除该 agent 的定义。
|
||||
|
||||
#### Token 影响
|
||||
|
||||
工具可见的每个请求都会产生固定 schema 开销;沙箱支持会增加升权字段及其条件说明段落。
|
||||
|
||||
#### KV Cache 影响
|
||||
|
||||
只要可见性、后台支持和执行器沙箱功能保持不变,前缀即可稳定复用。限制、配置或执行器发生变化时,可能从首个变化的工具定义开始使复用失效。
|
||||
|
||||
### 前台结果
|
||||
|
||||
#### 模型看到的内容
|
||||
|
||||
renderer 先输出依数据而定的 stdout 尾部,再输出可选的 `[stderr]` 和 stderr 尾部。没有输出时,它会精确输出 `(no output)`。条件行精确为 `[output truncated; full output: <path-or-(unavailable)>]`、`[sandbox: file access denied under <mode> mode]`、`[timed out after <timeoutMs>ms]`、`[killed by signal: <signal>]` 和 `[exit code: <exitCode>]`;沙箱升权与 runner 故障行原文列于 [`dsh-bash-sandbox`](../bash-sandbox/README.md)。
|
||||
|
||||
#### Token 影响
|
||||
|
||||
调用前结果 token 为零。每条流的输出有界,每个已输出行则会保留在历史中,直至压缩(compaction)。
|
||||
|
||||
#### KV Cache 影响
|
||||
|
||||
仅追加;新可见内容位于可复用请求前缀之后,不会使现有 KV-cache 条目失效。
|
||||
|
||||
### 后台任务上下文与结果
|
||||
|
||||
#### 模型看到的内容
|
||||
|
||||
启动会精确返回 `started background task <taskId>`。此生产方会向通用任务运行时提供增量进程输出、可选的 `[some output was dropped from memory; full output: <paths-or-(unavailable)>]`、沙箱事实,以及 `exit code: <exitCode>` 或 `signal: <signal>` 等终止详情。[`dsh-tool-tasks`](../../tasks/tool-tasks/README.md) 持有模型可见的状态行、完成通知、列表和取消响应。
|
||||
|
||||
#### Token 影响
|
||||
|
||||
启动确认很短并会保留;收集到的输出依数据而定,并受执行器流缓冲区限制。消费式读取不会重复先前输出。
|
||||
|
||||
#### KV Cache 影响
|
||||
|
||||
仅追加;新可见内容位于可复用请求前缀之后,不会使现有 KV-cache 条目失效。
|
||||
|
||||
### 工具错误
|
||||
|
||||
#### 模型看到的内容
|
||||
|
||||
验证和策略失败统一为 `Error: <message>`。此包的稳定消息包括 `invalid command: expected a non-empty string`、`invalid description: expected a non-empty string`、`invalid timeoutMs: expected a positive number, got <value>`、`invalid escalation: sandbox_permissions requires a justification`、`invalid escalation: justification is only valid together with sandbox_permissions`、`invalid justification: expected a non-empty sentence`、`background execution is disabled for this bash tool`、`background tasks unavailable: load @deepseek-ai/dsh-tasks and @deepseek-ai/dsh-tool-tasks`、`sandbox_permissions is not available in this composition (no sandboxing executor to escalate)`、`sandbox escalation to "<mode>" is not strictly wider than this call's current "<mode>" mode`、审批不可用/拒绝/取消变体,以及 `command aborted`。
|
||||
|
||||
#### Token 影响
|
||||
|
||||
只有失败调用会增加这些保留 token;升权被拒时命令不会运行,因此不会添加命令输出。
|
||||
|
||||
#### KV Cache 影响
|
||||
|
||||
仅追加;新可见内容位于可复用请求前缀之后,不会使现有 KV-cache 条目失效。
|
||||
|
||||
## 已知限制与延期工作
|
||||
|
||||
- **回放退出状态 pill 从结果文本解析**:如果输出最后一行恰好精确为 `[exit code: N]` / `[killed by signal: …]`,会话回放将显示错误的 pill;这是仅影响展示的已知残留问题。
|
||||
- **`bash` 工具不采用 `timeout-policy` 预算**:根据[工具调用 timeout-policy Agent Note](../../../.agents/notes/implemented/architecture/2026-07-07-tool-call-timeout-policy.md),它保留由执行器持有的 `BASH_TIMEOUT` 路径。
|
||||
- **后台进程没有执行器超时**:工作不再需要时,调用方必须使用 `task_kill`,或依赖持有者/服务的 dispose。
|
||||
6
packages/client/connection/README.i18n.yaml
Normal file
6
packages/client/connection/README.i18n.yaml
Normal 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: 80228a180faba0c556ff720e999b29b5bb1635b6
|
||||
README.zh.md: f4b857886bfafa891ceb1bd6b79b27e1fb725819
|
||||
@@ -1,5 +1,7 @@
|
||||
# @deepseek-ai/dsh-client-connection
|
||||
|
||||
English | [中文](README.zh.md)
|
||||
|
||||
Wire consumer layer: the client plugin's apply mounts `ctx.connection` (shared api client + single-consumer stream-loop starter); the export face carries the wire contract types, the `AbstractApiClient` seam, and the loop's sink/config types. The platform subclasses (WebApiClient/FixtureApiClient), the ConnectionController loop, and the fixture data source are package-internal — apply selects and drives them; tests reach them via src. Contract: api-contracts v3 §3.
|
||||
|
||||
## Keyless fixture
|
||||
|
||||
22
packages/client/connection/README.zh.md
Normal file
22
packages/client/connection/README.zh.md
Normal file
@@ -0,0 +1,22 @@
|
||||
# @deepseek-ai/dsh-client-connection
|
||||
|
||||
[English](README.md) | 中文
|
||||
|
||||
协议消费层:客户端插件的 apply 会挂载 `ctx.connection`(共享 API 客户端 + 单消费方流循环启动器);导出表层携带协议契约类型、`AbstractApiClient` seam,以及循环的 sink/配置类型。平台子类(WebApiClient/FixtureApiClient)、ConnectionController 循环和 fixture 数据源都属于包内部:apply 负责选择并驱动它们,测试则通过 src 访问。契约:api-contracts v3 §3。
|
||||
|
||||
## 无密钥 fixture
|
||||
|
||||
任何 `fixture` 查询参数都会选择内存载体。`fixture=empty` 启动时不含 Workspace 或 Session;`fixturePrompt=reject` 在接受前拒绝提示词;`fixtureAttach=fail` 发布 Session 但拒绝将其附加到 Workspace;`fixtureSessionCreate=drop-response` 在丢弃创建响应前发布 Session 并为其发出帧;`fixtureFrames=workspace-first` 则反转默认的 Session 优先创建帧顺序。按名称/路径创建 Workspace 以及由调用方预先分配 SessionId,均具有足够的确定性,组装后的 Web 测试可以据此协调列表与帧的到达。
|
||||
|
||||
## 模型体验
|
||||
|
||||
无。协议消费层只在浏览器与主机之间搬运已经组合好的消息;这里没有任何内容进入模型请求。
|
||||
|
||||
#### KV Cache 影响
|
||||
|
||||
无;该包既不组装也不发送提供方请求。
|
||||
|
||||
## 已知限制与暂缓事项
|
||||
|
||||
- **history 的隐式恢复存在争议**:在未附加的会话上打开 history,会在主机侧拉起 agent;纯持久化读取的替代方案记录在 rt-core 协调账本中,P-I 不作改变。该包的消费方会在首次打开时感受到这段延迟。
|
||||
- **计划移除 `ToolEventView`/`ToolCallView`/`ToolResultView` 的重新导出**:当 toolview 迁移删除主机 `viewFor` 行时,它们会一并移除(呈现属于客户端);在此之前,fixture 保留一份局部 `viewFor` 镜像。
|
||||
6
packages/client/hmr/README.i18n.yaml
Normal file
6
packages/client/hmr/README.i18n.yaml
Normal 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: 2b2f63c25cbf3a46babef78a4dfb52f859156887
|
||||
README.zh.md: 6d94ca4a5e91f390e58575aa4ddf64fc18a509de
|
||||
@@ -1,5 +1,7 @@
|
||||
# @deepseek-ai/dsh-client-hmr
|
||||
|
||||
English | [中文](README.zh.md)
|
||||
|
||||
Hot reload for fetch-arrival client plugins. A static-arrival entry composed only into `--dev` graphs (`dsh web --dev`); production graphs omit the row, so the shell-bundled code stays inert.
|
||||
|
||||
The browser half subscribes to the system SSE channel (`GET /plugins/events`) and reloads one plugin per `rebuilt` frame, serialized through a queue (the bundle handoff slot is single). The sequence per frame — `prefetch` (fetch the new bundle before touching anything), `invalidate`, `registry.delete` (before the fiber: a bare fiber dispose trips the vendored Loader's self-dispose branch, which would mark the entry disabled), drain the old fiber, delete `entry.fiber`, remove owned `<style data-plugin>` tags, `entry.refresh()` re-imports and remounts, `fiber.await()` rethrows startup failures loud. Dependents reload through cordis itself: a fiber's activation epoch strings its service providers' uids, so replacing a provider's fiber cascades every dependent with zero client-side graph analysis. The node half detects rebuilds with one interval that stat-polls each graph bundle from a synchronous baseline, immediately re-hashes after adding a row, retains missing rows as dirty, and broadcasts only real rev changes; any tsdown watch process producing the bundle therefore triggers HMR with no builder→host channel.
|
||||
|
||||
21
packages/client/hmr/README.zh.md
Normal file
21
packages/client/hmr/README.zh.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# @deepseek-ai/dsh-client-hmr
|
||||
|
||||
[English](README.md) | 中文
|
||||
|
||||
为通过 fetch 到达的客户端插件提供热重载。该静态到达配置项只组合进 `--dev` 图(`dsh web --dev`);生产图省略此行,因此外壳打包的代码保持不活动。
|
||||
|
||||
浏览器侧订阅系统 SSE 通道(`GET /plugins/events`),每个 `rebuilt` 帧重载一个插件,并通过队列串行执行(组合包交接 slot 只能容纳一个)。每帧的顺序是:`prefetch`(在触碰任何内容前抓取新组合包)、`invalidate`、`registry.delete`(在 fiber 之前执行:只释放 fiber 会触发 vendored Loader 的 self-dispose 分支,把配置项标为禁用)、排空旧 fiber、删除 `entry.fiber`、移除自身拥有的 `<style data-plugin>` 标签、通过 `entry.refresh()` 重新导入并挂载、以 `fiber.await()` 将启动失败高声重新抛出。依赖方由 cordis 自身重载:fiber 的激活 epoch 会串联其服务提供方的 uid,因此替换提供方 fiber 会级联所有依赖方,无需客户端图分析。node 侧使用一个 interval 检测重建:从同步基线开始 stat-poll 每个图组合包;新增一行后立即重新计算 hash;缺失行保持 dirty;只广播真实 rev 变更。因此,任何生成组合包的 tsdown watch 进程都能触发 HMR,无需 builder→host 通道。
|
||||
|
||||
## 模型体验
|
||||
|
||||
无。重载驱动器属于浏览器侧机制;这里没有任何内容进入模型请求。
|
||||
|
||||
#### KV Cache 影响
|
||||
|
||||
无;该包既不组装也不发送提供方请求。
|
||||
|
||||
## 已知限制与暂缓事项
|
||||
|
||||
- **重载有意保持粗粒度**:会创建全新的 fiber 和组件;重载插件中的 React 状态会丢失,数据层(connection/runtime fiber、Session 对象)不受影响。react-refresh 级状态保留与「重新执行组合包会重新运行 factory」冲突,因此有意排除。
|
||||
- **失败时不回滚**:失败的重载会使配置项处于 FAILED 状态,并在 loader 状态投影中高声报告;自动恢复先前组合包会等到实际需要出现后再实现。
|
||||
- **重建帧不会刷新图 rev**:陈旧 rev 无害(组合包端点以 no-cache 提供内容);rev 刷新会随重新连接握手机制落地。
|
||||
6
packages/client/locale/README.i18n.yaml
Normal file
6
packages/client/locale/README.i18n.yaml
Normal 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: 9015af2b44a33771b06863ace139fe97695df616
|
||||
README.zh.md: 6b129bcabbef5b5a00c5073ebc9142a0e406ddba
|
||||
@@ -1,5 +1,7 @@
|
||||
# @deepseek-ai/dsh-client-locale
|
||||
|
||||
English | [中文](README.zh.md)
|
||||
|
||||
Locale plugin: LocaleService — the browser locale preference (`zh`/`en`, persisted under `dsh.locale`, getter/setter with `locale/change` snapshots) plus the ns×locale dictionary registry (`bind(ns)`→t with a stable function identity; lookup chain active → zh → key).
|
||||
|
||||
## Model Experience
|
||||
|
||||
18
packages/client/locale/README.zh.md
Normal file
18
packages/client/locale/README.zh.md
Normal file
@@ -0,0 +1,18 @@
|
||||
# @deepseek-ai/dsh-client-locale
|
||||
|
||||
[English](README.md) | 中文
|
||||
|
||||
locale 插件:LocaleService 包含浏览器 locale 偏好(`zh`/`en`,以 `dsh.locale` 为键持久化;提供 getter/setter,并生成 `locale/change` 快照),以及 ns×locale 字典注册表(`bind(ns)`→t 的函数标识稳定;查找链为 active → zh → key)。
|
||||
|
||||
## 模型体验
|
||||
|
||||
无。locale 注册表为浏览器 UI 文案提供服务;这里没有任何内容进入模型请求。
|
||||
|
||||
#### KV Cache 影响
|
||||
|
||||
无;该包既不组装也不发送提供方请求。
|
||||
|
||||
## 已知限制与暂缓事项
|
||||
|
||||
- **只有设置界面完成翻译**:其他页面仍保留内联文案;将全仓文案提取到字典的工作暂缓。
|
||||
- **切换 locale 只重新渲染已订阅的消费方**:未接入 `locale/change` 的分区会保留已渲染文本,直到重新挂载。
|
||||
6
packages/client/modules/README.i18n.yaml
Normal file
6
packages/client/modules/README.i18n.yaml
Normal 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: efba9e2eb0b148677fc7ac18bfad6333fb6f80da
|
||||
README.zh.md: 7d1aa8af08256c47c1ae65343e46c30e910128d0
|
||||
@@ -1,5 +1,7 @@
|
||||
# @deepseek-ai/dsh-client-modules
|
||||
|
||||
English | [中文](README.zh.md)
|
||||
|
||||
Client module system: the browser peer of Node's internal ESM loader, built as a lazy CJS table. The web shell mounts the vendored cordis Loader for entry governance (fiber lifecycle, inject waiting, update/refresh) and injects this package's `ClientModuleLoader` as its `internal` seam — the vendored side's only consumption point is `EntryTree.import`, so replacing `internal` replaces exactly "how plugin code arrives" and nothing else.
|
||||
|
||||
Lazy CJS model (web2): executing a plugin bundle only REGISTERS its factory (`window.__ModuleLoader__.load({id, factory})`); every module body side effect — CSS injection included — lives in the factory closure and runs at materialization (`factory(require)` → export surface, memoized in `loadCache`), not at script execution. A factory that requires another registered-but-unmaterialized module materializes it recursively, so load order needs no external sequencing; require cycles throw (factory-form CJS cannot deliver partial exports). `<id>/client` and the bare id name the same surface (a plugin bundle IS its package's client half).
|
||||
|
||||
22
packages/client/modules/README.zh.md
Normal file
22
packages/client/modules/README.zh.md
Normal file
@@ -0,0 +1,22 @@
|
||||
# @deepseek-ai/dsh-client-modules
|
||||
|
||||
[English](README.md) | 中文
|
||||
|
||||
客户端模块系统:Node 内部 ESM loader 的浏览器端对等实现,以惰性 CJS 表构建。web 外壳挂载 vendored cordis Loader 来治理配置项(fiber 生命周期、inject 等待、update/refresh),并把该包的 `ClientModuleLoader` 作为其 `internal` seam 注入;vendored 一侧唯一的消费点是 `EntryTree.import`,因此替换 `internal` 恰好只会替换「插件代码如何到达」,不会改变其他内容。
|
||||
|
||||
惰性 CJS 模型(web2):执行插件组合包只会注册其 factory(`window.__ModuleLoader__.load({id, factory})`);每个模块主体的副作用(包括 CSS 注入)都位于 factory 闭包中,在物化时运行(`factory(require)` → 导出表层,并在 `loadCache` 中记忆化),不会在脚本执行时运行。如果 factory 请求另一个已注册但尚未物化的模块,系统会递归物化它,因此加载顺序无需外部编排;require 循环会抛出异常(factory 形式的 CJS 无法交付部分导出)。`<id>/client` 与裸 id 指向同一表层(一个插件组合包就是其包的客户端侧)。
|
||||
|
||||
解析分支顺序(`import(specifier)`):平台种子词 → 外壳实例;记忆化记录 → 表层;外壳自身的静态注册表(`registerStatic`,app-shell)→ 模块;已注册 factory → 物化;图行(`window.__DSH_BOOT__`)→ 抓取 + 执行 + 物化;其他情况一律抛出异常。这是构建时组合包纯度门禁的运行时镜像。交给 factory 的同步 `require` 采用相同顺序,但不含抓取分支,并把观察到的边记录到模块记录中。`prefetch` 是第一阶段到达 hook(抓取 + 执行,只注册;并发调用共享一个进行中的 task);`invalidate` 会丢弃 factory 与物化记录,使下一次 prefetch/import 重新抓取(HMR hook)。
|
||||
|
||||
## 模型体验
|
||||
|
||||
无。模块 loader 属于浏览器侧内核机制;这里没有任何内容进入模型请求。
|
||||
|
||||
#### KV Cache 影响
|
||||
|
||||
无;该包既不组装也不发送提供方请求。
|
||||
|
||||
## 已知限制与暂缓事项
|
||||
|
||||
- **有意采用扁平模块图**:每个组合包是一个模块节点,其边只指向表叶;接口(loadCache/edges/invalidate)按通用模块图塑形,因此可以改变 externalization 粒度而不更改接口。
|
||||
- **自身不记录卸载账目**:样式移除与 fiber 拆卸顺序属于 HMR 驱动器(`@deepseek-ai/dsh-client-hmr`);loader 只逐记录清点自身拥有的样式标签 id。
|
||||
6
packages/client/runtime/README.i18n.yaml
Normal file
6
packages/client/runtime/README.i18n.yaml
Normal 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: 5d44f666a12e747eb79535c48d87fcaff381d770
|
||||
README.zh.md: 16577c356ba79066c7c56ae07a266f4ec85fa2e9
|
||||
@@ -1,5 +1,7 @@
|
||||
# @deepseek-ai/dsh-client-runtime
|
||||
|
||||
English | [中文](README.zh.md)
|
||||
|
||||
Client cordis boot and React-free object services: SlotsService wraps SlotCore and supplies renderer data sources; SessionsService owns Session objects, list/scope/history state, and page-local Session Intent state; WorkspacesService depends on SessionsService and owns Workspace objects, list/actions, page-local Workspace Intent state, default-target derivation, and the cross-object New Session flow. The runtime fans the shared Host stream into both managers. Contract: api-contracts v3 §4.
|
||||
|
||||
## Workspace and Session lists
|
||||
|
||||
33
packages/client/runtime/README.zh.md
Normal file
33
packages/client/runtime/README.zh.md
Normal file
@@ -0,0 +1,33 @@
|
||||
# @deepseek-ai/dsh-client-runtime
|
||||
|
||||
[English](README.md) | 中文
|
||||
|
||||
客户端 cordis 启动与不依赖 React 的对象服务:SlotsService 包装 SlotCore 并提供 renderer 数据源;SessionsService 拥有 Session 对象、列表/scope/history 状态和页面局部 Session Intent 状态;WorkspacesService 依赖 SessionsService,拥有 Workspace 对象、列表/操作、页面局部 Workspace Intent 状态、默认目标派生,以及跨对象 New Session 流程。运行时把共享 Host 流分发给两个 manager。契约:api-contracts v3 §4。
|
||||
|
||||
## Workspace 与 Session 列表
|
||||
|
||||
Workspace 和 Session 列表各自具有单调的 `pending` → `ready` 基线阶段,也有各自的刷新活动/错误状态。列表请求期间到达的增量帧会在其响应之上回放。第一次成功的基线建立 Host 顺序;后续刷新更新行和成员关系,但不改变已经显示的标识之间的相对顺序。Workspace 新近程度只在两条基线都 ready 后派生,且绝不改变 Workspace 列表顺序。
|
||||
|
||||
SlotsService 分别为 renderer 提供 `useSessions` 与 `useWorkspaces` 的裸 observable;web-react 创建 hook。Workspace 业务状态不会进入 `SessionListState` 或配置项 store。
|
||||
|
||||
## Session 创建失败
|
||||
|
||||
`SessionsService.create` 接受可选的、由调用方预先分配的 SessionId。失败时抛出 `SessionCreateError`:传输状态不确定后仍可取得 `requestedSessionId`;如果 Host 在附加失败前已经发布真实 Session,则会设置 `publishedSessionId`,此时 `workspace-attach-failed` 提供了证明。在 New Session 流程中,前端 Session 对象拥有其保留的提示词,并推动提示词完成附加与发送;部分发布的 Session 会保留同一对象和提示词,同时显示为 Ungrouped。
|
||||
|
||||
## Session 标题投影
|
||||
|
||||
`SessionManager` 独立于列表和 Session 实例到达情况,保留最近一次通过验证的 `session/title` 控制快照。seq 更新的事件会替换旧快照,标题时间戳计入列表新近程度;订阅基线会先丢弃 seq 超过其 `lastSeq` 的任何已保留标题,再接收可选的折叠标题。显式移除 Session 也会清除已保留标题。因此,面向客户端的 `SessionSummary.title` 只包含真实的持久标题;`displayTitle` 始终存在,并依次回退到 cwd basename 和 Session id。冷启动的持久会话会保持该回退值,直到打开或恢复会话,促使主机折叠并投影日志支持的标题。
|
||||
|
||||
## 模型体验
|
||||
|
||||
无。客户端运行时承载浏览器侧服务与 Session 对象层;这里没有任何内容进入模型请求。
|
||||
|
||||
#### KV Cache 影响
|
||||
|
||||
无;该包既不组装也不发送提供方请求。
|
||||
|
||||
## 已知限制与暂缓事项
|
||||
|
||||
- **`loader.unload` 是 stub(抛出 not-implemented)**:完整链路(fiber 释放 → 注册级联 → 样式移除)随 HMR 项目落地。
|
||||
- **scope 拆卸由阶段驱动,目前只能有一个占用者**:已 staged 的 Session 精确跟随 `list.current`(staging 就是打开信号:事件窗口打开 ⟺ Session 位于 stage);在 staged 状态下被移除的 Session,其 scope 会冻结保留,直到 stage 转向其他 Session,而非直到真实观察者数量降为零。解析(`cell()`/`binding()`/`scope()`)只是纯寻址,可安全用于渲染。并发 pane 落地时,staged 状态可以扩展为多 pane 列表。
|
||||
- **插件组合包从该包执行值导入时必须使用 `/client` 子路径**:裸包名不在 loader external 表中,会内联第二个模块实例;其私有 scope-tag Symbol 永远无法匹配(空状态 P0 事故复盘)。
|
||||
6
packages/client/ui-conversation/README.i18n.yaml
Normal file
6
packages/client/ui-conversation/README.i18n.yaml
Normal 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: f5e2603e8ad588740bea3be4f1a195d658721f0c
|
||||
README.zh.md: 900d3d1608da3c86078dc56ec819b1f851e63de7
|
||||
@@ -1,5 +1,7 @@
|
||||
# @deepseek-ai/dsh-client-ui-conversation
|
||||
|
||||
English | [中文](README.zh.md)
|
||||
|
||||
Conversation domain: skeleton (header/tabs/composer/empty state), chat view (grouped step-summary flow, streaming tail isolation, stats line, per-tool row slot with a bash sample registrant), minimal details panel, scope-addressed ConversationService. Contract: api-contracts v3 §7 plus the slot terminal design (store seat / props shares).
|
||||
|
||||
The no-session hero renders the frontend Session Intent from the Session list projection, including its frontend Workspace Intent when no real Workspace exists. It declares `conversation.empty.workspace`, where ui-workspace registers the same picker used by the sidebar. WorkspacesService starts the cross-object flow; each Workspace or Session object owns its own materialization. The Session keeps its identity across publication and retains any prompt that still needs connection or delivery; ConversationRoot reads that `pendingPrompt` from `useSession` and edits or retries it through the scoped ConversationService.
|
||||
|
||||
33
packages/client/ui-conversation/README.zh.md
Normal file
33
packages/client/ui-conversation/README.zh.md
Normal file
@@ -0,0 +1,33 @@
|
||||
# @deepseek-ai/dsh-client-ui-conversation
|
||||
|
||||
[English](README.md) | 中文
|
||||
|
||||
会话领域:骨架(标题栏/标签页/编辑器/空状态)、聊天视图(分组步骤摘要流、流式尾部隔离、统计行、逐工具行 slot 及一个 bash 示例注册方)、最小详情面板、按 scope 寻址的 ConversationService。契约:api-contracts v3 §7 加 slot 终端设计(store seat/props share)。
|
||||
|
||||
无会话主视觉区会渲染来自 Session 列表投影的前端 Session Intent;没有真实 Workspace 时,还会包含其前端 Workspace Intent。它声明 `conversation.empty.workspace`,ui-workspace 会在此注册侧边栏所用的同一选择器。WorkspacesService 启动跨对象流程;每个 Workspace 或 Session 对象拥有自身的物化。Session 在发布期间保持身份,并保留任何仍需连接或交付的提示词;ConversationRoot 读取该 `pendingPrompt`,其来源是 `useSession`,再通过 scope 内的 ConversationService 编辑或重试。
|
||||
|
||||
视图环本身就是 slot:会话注册声明 `'conversation.view'` 列表 slot(Session scope),并将其列在 `children` 表中;ConversationRoot 通过 renderSlot share 渲染活跃配置项(`only: <active id>`);视图标签页从环账本的注册选项(`id`/`order`/`label`)投影而来。聊天视图是该包自身的环配置项;其他插件(ui-trajectory)通过普通的 `ctx.slots.register` 贡献标签页。先前包内的视图注册表(`registerView`/`ViewEntry`/`ConversationViewMap` 及 chrome 附加表)已退役,逐视图 chrome 则被拆入视图组件自身。
|
||||
|
||||
通用工具行把内置的 bash、read、search、write 和 edit 名称归入专用视觉变体。文件系统变体会渲染 edit 图标和 `Write · <path>` 或 `Edit · <path>` 摘要,同时保留共享的行到详情交互。
|
||||
|
||||
工具行同样是 slot:独立工具环(`ToolViewRegistry`/`ctx.toolviews`/outlet)已经退役。聊天配置项声明键控的 `'conversation.chat.toolview'` 空位(Session scope;key 空间在运行时开放);其渲染点逐行通过 `entryKey: toolName` 分发,并以 `GenericToolCard` 作为调用点 `fallback`。owner 载荷是统一的 `ToolRowOwnerProps`(`callId`/`toolName`/`block`/`openDetails`),`ToolRowProps` 则预先将其与 Session 标准工具包组合。注册方只是普通插件:`ctx.slots.register({ name: 'conversation.chat.toolview', key: '<tool>', inject? }, Row)`,以 `inject: ['slots', 'conversation']` 作为加载顺序 seam(apply 在聊天注册后挂载 ConversationService,因此服务存在即可保证 slot 已声明);Session 区分在组件内部完成(`useSessions` 读取 `parentId`,bash 示例是第三方姿态的范例)。Trajectory/waterfall 工具视图 slot 共享此形状,并随各自的渲染点落地(RendersCheck 会拒绝没有任何渲染方的声明)。
|
||||
|
||||
逐 Session UI 状态(选择、普通编辑器草稿、活跃视图)位于已声明的聊天 store(`stores.ts` `createChatStore`)中:apply 构造一个 handle,并将其传给会话、聊天视图和详情注册,因此 Session slot 每个 Session 共享一个实例(选择由聊天视图写入、详情读取),框架拥有实例生命周期与草稿持久化。前端 Session Intent 来自 Session 列表投影;发布后,任何保留的提示词都来自该 Session 的会话快照。组件保持纯粹:框架标准工具包(Session scope 下的 `useSession`/`sessionId`,以及全局 `useSessions`/`useWorkspaces`)和 store 表层(`useStore`/`actions`)会从注册声明自动到达;inject factory 为运行时 Session 操作、发送/停止、标签页、详情和分页贡献普通数据与回调。
|
||||
|
||||
`src/client/` 按未来的包拆分组织:`contract/` 是唯一的跨领域共享表层(`slots.ts` slot 声明 + 组合后的 slot props,包括工具行契约、`views.ts` 共享原语、`tool-call-model.ts`);`skeleton/`、`chat/` 和 `toolviews/`(示例注册方)领域目录只导入 contract 文件,彼此绝不导入;`apply.ts` 是唯一允许导入全部三个领域的组装点。`/client` 导出表层只包含契约:`apply`/`inject`、两个服务类和 `contract/` 类型家族;实现组件(骨架、聊天行)与 store factory 保持内部状态,只能通过 apply 的 slot 注册到达页面(测试通过 `./src/*` 子路径获取它们)。
|
||||
|
||||
## 模型体验
|
||||
|
||||
无。会话 UI 在浏览器中渲染会话历史与流;这里没有任何内容进入模型请求。
|
||||
|
||||
#### KV Cache 影响
|
||||
|
||||
无;该包既不组装也不发送提供方请求。
|
||||
|
||||
## 已知限制与暂缓事项
|
||||
|
||||
- **统计行没有耗时区段**:assistant `usage` 只携带 token 计数;耗时需要主机数据源。
|
||||
- **详情面板是最小形态**:以原始形式显示已选择调用的参数/结果;Input/Output/Metadata 切换、Prev/Next 步进与 See-in-trajectory 深链接暂缓实现。
|
||||
- **assistant footer 扩展(IconActions 行、逐消息分页)是预留 slot**:设计中已有图稿,尚未实现。
|
||||
- **others 工具行的闪光图标是手绘近似版本**:无法在本地导出设计字形的矢量几何;等到存在精确导出后再将其提升到 ui-primitives。
|
||||
- **审批卡片只是只读占位符**:问题请求通过编辑器链回答(ui-question),Web 侧审批回答属于 P-II 审批项目。
|
||||
6
packages/client/ui-layout/README.i18n.yaml
Normal file
6
packages/client/ui-layout/README.i18n.yaml
Normal 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: 6aeda0e04bf690f5cc8a6d52eea95b1b2782a143
|
||||
README.zh.md: 9fbc2ed8392ae3ceba453517d9af5ef41f039d2d
|
||||
@@ -1,5 +1,7 @@
|
||||
# @deepseek-ai/dsh-client-ui-layout
|
||||
|
||||
English | [中文](README.zh.md)
|
||||
|
||||
Shell plugin: three-column AppFrame (drag handles and concession chain) plus the `ctx.layout` panel-geometry service; it registers into the runtime-owned `root` slot and declares `sidebar`, `conversation`, `details`, and `conversation.empty`. The sidebar is fixed-width (only details shrinks, then auto-closes); a closed sidebar retains a 56px control rail while details closes to zero width. The package also seats the theme presenter: it consumes resolved `ctx.theme` snapshots and projects them onto `document.body` (`data-ds-dark-theme` from the active color scheme plus the theme's alias tokens as inline variables).
|
||||
|
||||
AppFrame reads the runtime Session projection: `baselinesReady` selects loading, a page-local `SessionListState.intent` selects the empty composer, and a connected Session renders through `SessionProvider`. The conversation and empty-state owner shares are empty; each registrant obtains business data from standard hooks and actions from its own inject face. The sidebar owner share contains only `collapsed` and `width`; navigation actions belong to sidebar's own injected service face.
|
||||
|
||||
23
packages/client/ui-layout/README.zh.md
Normal file
23
packages/client/ui-layout/README.zh.md
Normal file
@@ -0,0 +1,23 @@
|
||||
# @deepseek-ai/dsh-client-ui-layout
|
||||
|
||||
[English](README.md) | 中文
|
||||
|
||||
外壳插件:三栏 AppFrame(拖动手柄与让步链)加 `ctx.layout` 面板几何服务;它注册到运行时拥有的 `root` slot,并声明 `sidebar`、`conversation`、`details` 和 `conversation.empty`。侧边栏宽度固定(只会收缩详情栏,然后将其自动关闭);关闭的侧边栏仍保留 56px 控制轨道,详情栏则关闭到零宽度。该包还提供主题呈现器:它消费解析后的 `ctx.theme` 快照,并将其投影到 `document.body`(依据当前配色方案设置 `data-ds-dark-theme`,并将主题的别名 token 设为内联变量)。
|
||||
|
||||
AppFrame 读取运行时 Session 投影:`baselinesReady` 选择加载状态,页面局部的 `SessionListState.intent` 选择空白编辑器,已连接 Session 则通过 `SessionProvider` 渲染。会话及空状态的 owner share 为空;每个注册方通过标准 hook 获取业务数据,并从自身的 inject 表层获取操作。侧边栏 owner share 只包含 `collapsed` 和 `width`;导航操作属于侧边栏自身注入的服务表层。
|
||||
|
||||
`/client` 导出表层包含插件主体(`apply`/`inject`)、`LayoutService` 和四个 owner-share 接口。AppFrame、面板 store 与让步求解器仍属于包内部;测试通过 `/src` 导入内部实现。
|
||||
|
||||
## 模型体验
|
||||
|
||||
无。布局外壳管理浏览器查看状态;这里没有任何内容进入模型请求。
|
||||
|
||||
#### KV Cache 影响
|
||||
|
||||
无;该包既不组装也不发送提供方请求。
|
||||
|
||||
## 已知限制与暂缓事项
|
||||
|
||||
- **详情栏打开/宽度状态是全局状态**:它不会随会话变化(P-I 已裁定);为逐会话键控升级预留了 slot。
|
||||
- **让步链自动关闭通过推导零宽度实现,不会改动持久化的打开标志**:窗口变宽时面板会自行恢复;消费方禁止把 `details.open` 当作实际渲染状态。
|
||||
- **挤压重排期间尚未实现滚动锚定**:与虚拟化列表项目一并暂缓。
|
||||
6
packages/client/ui-models/README.i18n.yaml
Normal file
6
packages/client/ui-models/README.i18n.yaml
Normal 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: 13f51d5338affd65d0705cec6a3b4ef78a534f0f
|
||||
README.zh.md: 466505beb27c729246afe04e6378235b91d072cf
|
||||
@@ -1,5 +1,7 @@
|
||||
# @deepseek-ai/dsh-client-ui-models
|
||||
|
||||
English | [中文](README.zh.md)
|
||||
|
||||
Models settings section plugin: registers the `models` nav entry into `settings.section` with an intentionally empty content column — model management lands in a later phase.
|
||||
|
||||
## Model Experience
|
||||
|
||||
17
packages/client/ui-models/README.zh.md
Normal file
17
packages/client/ui-models/README.zh.md
Normal file
@@ -0,0 +1,17 @@
|
||||
# @deepseek-ai/dsh-client-ui-models
|
||||
|
||||
[English](README.md) | 中文
|
||||
|
||||
模型设置分区插件:注册 `models` 导航项,使其进入 `settings.section`;内容栏有意留空,模型管理将在后续阶段实现。
|
||||
|
||||
## 模型体验
|
||||
|
||||
无。该分区渲染空白的浏览器 UI 内容栏;这里没有任何内容进入模型请求。
|
||||
|
||||
#### KV Cache 影响
|
||||
|
||||
无;该包既不组装也不发送提供方请求。
|
||||
|
||||
## 已知限制与暂缓事项
|
||||
|
||||
- **内容栏按设计留空**:提供方列表、编辑表单和激活流程均暂缓,待模型管理服务就绪后实现。
|
||||
6
packages/client/ui-primitives/README.i18n.yaml
Normal file
6
packages/client/ui-primitives/README.i18n.yaml
Normal 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: 4e2a22e77dc1611728477ea0a9d8c50dfc9f7f5d
|
||||
README.zh.md: 36253971281fd346f9b0ec4648c4b8824ed918a7
|
||||
@@ -1,5 +1,7 @@
|
||||
# @deepseek-ai/dsh-client-ui-primitives
|
||||
|
||||
English | [中文](README.zh.md)
|
||||
|
||||
Pure React atoms (zero cordis): StateDot, ic_ds_* icons, Button/Pill/Menu/Modal/Input, markdown family (MessageText/MarkdownText/JsonBlock). Contract: api-contracts v3 §8.
|
||||
|
||||
## Markdown rendering
|
||||
|
||||
23
packages/client/ui-primitives/README.zh.md
Normal file
23
packages/client/ui-primitives/README.zh.md
Normal file
@@ -0,0 +1,23 @@
|
||||
# @deepseek-ai/dsh-client-ui-primitives
|
||||
|
||||
[English](README.md) | 中文
|
||||
|
||||
纯 React 原子组件(零 cordis):StateDot、ic_ds_* 图标、Button/Pill/Menu/Modal/Input,以及 markdown 家族(MessageText/MarkdownText/JsonBlock)。契约:api-contracts v3 §8。
|
||||
|
||||
## Markdown 渲染
|
||||
|
||||
`MarkdownText` 通过 React 元素渲染来自不受信任 assistant 输出的 GFM。它会省略原始 HTML,使相对链接及非 HTTP(S)/mailto 链接失效,以安全的外部链接属性打开 HTTP(S) 链接,并只渲染图片 alt 文本而不加载远程资源;`MessageText` 仍是用户创作内容使用的字面文本原语。
|
||||
|
||||
## 模型体验
|
||||
|
||||
无。该包在浏览器中渲染纯 React 原子组件;这里没有任何内容进入模型请求。
|
||||
|
||||
#### KV Cache 影响
|
||||
|
||||
无;该包既不组装也不发送提供方请求。
|
||||
|
||||
## 已知限制与暂缓事项
|
||||
|
||||
- **字形级图标是重新绘制的近似版本**:鱼形标志(以及 ui-conversation 持有的闪光图标)来自字体字形,而本地设计数据无法导出其矢量几何;在获得精确导出路径前,使用手工重建版本代替。
|
||||
- **Pill 与 Input 没有设计来源**:两个原子组件均自行定义;与其相似的侧边栏搜索字段和视图标签条由消费方组合,不是这些原子组件。
|
||||
- **StateDot 的 `Active` 变体是设计中的隐藏占位符**:尚未实现;已交付的四种状态(done/warning/ongoing/error)构成完整的 P-I 表层。
|
||||
6
packages/client/ui-question/README.i18n.yaml
Normal file
6
packages/client/ui-question/README.i18n.yaml
Normal 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: 28132d1d0643f5e8f658ab77de9017467da2d172
|
||||
README.zh.md: c70e77fc90eb5b226ceabd8a1e7cc7ca6c011c40
|
||||
@@ -1,5 +1,7 @@
|
||||
# @deepseek-ai/dsh-client-ui-question
|
||||
|
||||
English | [中文](README.zh.md)
|
||||
|
||||
Web `ask_user_question` feature plugin. Its host half mounts `dsh-tool-ask-user` only when the Web feature is selected; its browser half registers the `question` entry in the conversation-owned `conversation.composer` keyed slot.
|
||||
|
||||
The component renders one question at a time with progress navigation, single- and multi-select choices, recommendation badges derived from label suffixes, and custom answers. Single-select choices advance immediately, and Enter submits once every question is answered or skipped; Enter during IME composition confirms the input candidate without advancing. It submits one structured answer batch for the whole request: “Skip this question” retains other drafts and emits the existing blank `{ selected: [] }` shape for that item, while close rejects the whole wait as `ASK_CANCELLED`.
|
||||
|
||||
22
packages/client/ui-question/README.zh.md
Normal file
22
packages/client/ui-question/README.zh.md
Normal file
@@ -0,0 +1,22 @@
|
||||
# @deepseek-ai/dsh-client-ui-question
|
||||
|
||||
[English](README.md) | 中文
|
||||
|
||||
Web `ask_user_question` 功能插件。只有选择 Web 功能时,其主机侧才会挂载 `dsh-tool-ask-user`;浏览器侧会把 `question` 配置项注册到会话拥有的 `conversation.composer` 键控 slot 中。
|
||||
|
||||
组件每次渲染一个问题,提供进度导航、单选和多选选项、由标签后缀派生的推荐徽标,以及自定义答案。单选选项会立即前进;所有问题均已回答或跳过后,Enter 会提交;IME 输入法组合期间按 Enter 只会确认输入候选,不会前进。组件为整个请求提交一批结构化答案:「跳过此问题」会保留其他草稿,并为该项发出既有的空 `{ selected: [] }` 形状;关闭则以 `ASK_CANCELLED` 拒绝整个等待。
|
||||
|
||||
选择状态只存在于以请求 rpcId 为 key 的组件本地。使用相同 id 回放时,只要组件仍挂载,就会保留草稿;主机发出的 `question/resolved` 则会移除编辑器。主机仍具有最终决定权:HTTP 交付成功不会在本地移除待处理状态。
|
||||
|
||||
## 模型体验
|
||||
|
||||
通过 `dsh-tool-ask-user` 间接影响;该包拥有模型可见的工具 schema 和结构化结果。
|
||||
|
||||
#### KV Cache 影响
|
||||
|
||||
不会直接失效;模型可见的工具调用与结果由 `dsh-tool-ask-user` 拥有。
|
||||
|
||||
## 已知限制与暂缓事项
|
||||
|
||||
- **未提交的草稿不持久**:重新连接再同步或完整刷新页面时,会恢复主机拥有且 rpcId 相同的待处理请求,但编辑器卸载会重置本地选项和自定义文本草稿。
|
||||
- **每次只有一个请求拥有编辑器**:后续待处理请求仍留在会话快照中,并在较早请求解决后显示。
|
||||
6
packages/client/ui-settings-general/README.i18n.yaml
Normal file
6
packages/client/ui-settings-general/README.i18n.yaml
Normal 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: c392d745021c0fc6a752cf71dd0506a435106c50
|
||||
README.zh.md: 83ab81e01eae435a74b50fa363a4de203c483002
|
||||
@@ -1,5 +1,7 @@
|
||||
# @deepseek-ai/dsh-client-ui-settings-general
|
||||
|
||||
English | [中文](README.zh.md)
|
||||
|
||||
Settings ownerless-copy plugin: registers everything on the Settings surface that belongs to no single feature — the shell's trigger/header/close chrome content, the General section (Permission/Tool Call skeleton rows + the `settings.general.item` slot declaration), and the `settings` dictionaries. Feature-owned rows (Language, Appearance) and sections (Models) stay with their feature packages.
|
||||
|
||||
## Model Experience
|
||||
|
||||
17
packages/client/ui-settings-general/README.zh.md
Normal file
17
packages/client/ui-settings-general/README.zh.md
Normal file
@@ -0,0 +1,17 @@
|
||||
# @deepseek-ai/dsh-client-ui-settings-general
|
||||
|
||||
[English](README.md) | 中文
|
||||
|
||||
设置界面文案插件:在设置界面注册所有不属于单一功能的内容,包括外壳的触发器、标题栏与关闭控件内容,「通用」分区(「权限」/「工具调用」骨架行和 `settings.general.item` slot 声明),以及 `settings` 字典。归具体功能所有的行(「语言」、「外观」)和分区(「模型」)仍由各自的功能包提供。
|
||||
|
||||
## 模型体验
|
||||
|
||||
无。该插件渲染浏览器设置 UI;这里没有任何内容进入模型请求。
|
||||
|
||||
#### KV Cache 影响
|
||||
|
||||
无;该包既不组装也不发送提供方请求。
|
||||
|
||||
## 已知限制与暂缓事项
|
||||
|
||||
- **「权限」与「工具调用」只是展示骨架**:对应的宿主服务和 RPC 方法尚不存在;这些控件已禁用,不会写入任何内容。一旦获得实际支撑,按照自注册原则,每一项都会移至拥有它的功能插件。
|
||||
6
packages/client/ui-settings/README.i18n.yaml
Normal file
6
packages/client/ui-settings/README.i18n.yaml
Normal 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: bb99f9b37927eec57650aa4025deb043b369c78e
|
||||
README.zh.md: fce11e2cf44fe6c1debe850df644b0114dbde5e3
|
||||
@@ -1,5 +1,7 @@
|
||||
# @deepseek-ai/dsh-client-ui-settings
|
||||
|
||||
English | [中文](README.zh.md)
|
||||
|
||||
Settings shell plugin: a pure composition face. It occupies `sidebar.settings` with the trigger chrome and the modal settings panel, and declares the slots registrants fill: `settings.trigger` / `settings.header` / `settings.close` (chrome content) and `settings.section` (one page per feature). The shell ships no copy and reads no locale state — all text arrives from registrants (ui-settings-general owns chrome and General; features own their sections and rows), so the section ledger bump is its only re-render trigger.
|
||||
|
||||
## Model Experience
|
||||
|
||||
17
packages/client/ui-settings/README.zh.md
Normal file
17
packages/client/ui-settings/README.zh.md
Normal file
@@ -0,0 +1,17 @@
|
||||
# @deepseek-ai/dsh-client-ui-settings
|
||||
|
||||
[English](README.md) | 中文
|
||||
|
||||
设置外壳插件:一个纯组合表层。它以触发控件和模态设置面板占用 `sidebar.settings`,并声明由注册方填充的 slot:`settings.trigger`/`settings.header`/`settings.close`(界面框架内容)和 `settings.section`(每项功能一页)。外壳不自带文案,也不读取 locale 状态:所有文本都来自注册方(ui-settings-general 拥有界面框架和「通用」分区;各功能拥有各自的分区和行),因此只有分区账本更新会触发它重新渲染。
|
||||
|
||||
## 模型体验
|
||||
|
||||
无。设置外壳为浏览器 UI 提供组合能力;这里没有任何内容进入模型请求。
|
||||
|
||||
#### KV Cache 影响
|
||||
|
||||
无;该包既不组装也不发送提供方请求。
|
||||
|
||||
## 已知限制与暂缓事项
|
||||
|
||||
- **面板仅涵盖浏览器偏好设置**:宿主侧设置表层(权限模式、工具调用模式)尚无 RPC 支撑;其骨架位于 ui-settings-general。
|
||||
6
packages/client/ui-sidebar/README.i18n.yaml
Normal file
6
packages/client/ui-sidebar/README.i18n.yaml
Normal 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: 93a1f15a5802f94a0ebe930dda1dbd4fbc7343c9
|
||||
README.zh.md: 1ef636dbd00c894c8312ab1fbfa9a96af45956f0
|
||||
@@ -1,5 +1,7 @@
|
||||
# @deepseek-ai/dsh-client-ui-sidebar
|
||||
|
||||
English | [中文](README.zh.md)
|
||||
|
||||
Sidebar plugin: real Host Workspaces in stable Host order, each containing its `sessionIds` in Workspace order with `parentId` nesting; Sessions outside every Workspace appear in a trailing `Ungrouped` section. Search, state dots, and collapse into the layout-owned 56px rail are presentation-local. Contract: the [slot system standard](../../../.agents/notes/implemented/architecture/2026-07-22-slot-type-chain-implementation.md).
|
||||
|
||||
New Session starts the runtime's page-local frontend Session Intent; a real Workspace's "+" starts one targeted to that Workspace. The Workspace header "+" opens ui-workspace's shared picker, whose selection also targets a frontend Session. A Workspace Intent does not appear in the sidebar.
|
||||
|
||||
27
packages/client/ui-sidebar/README.zh.md
Normal file
27
packages/client/ui-sidebar/README.zh.md
Normal file
@@ -0,0 +1,27 @@
|
||||
# @deepseek-ai/dsh-client-ui-sidebar
|
||||
|
||||
[English](README.md) | 中文
|
||||
|
||||
侧边栏插件:真实 Host Workspace 按稳定的 Host 顺序排列;每个 Workspace 按自身顺序包含其 `sessionIds`,并以 `parentId` 嵌套;不属于任何 Workspace 的 Session 显示在末尾的 `Ungrouped` 分区。搜索、状态点以及折叠到布局拥有的 56px 轨道,都只属于呈现层。契约:[slot 系统标准](../../../.agents/notes/implemented/architecture/2026-07-22-slot-type-chain-implementation.md)。
|
||||
|
||||
New Session 会启动运行时的页面局部前端 Session Intent;真实 Workspace 的「+」会启动一项以该 Workspace 为目标的 Intent。Workspace 标题栏的「+」打开 ui-workspace 的共享选择器,选择结果同样以一个前端 Session 为目标。Workspace Intent 不会出现在侧边栏中。
|
||||
|
||||
`SidebarRootComponentProps` 组合布局 owner share、全局 `useSessions` 和 `useWorkspaces` hook、已声明的 `sidebar.workspace` 与 `sidebar.settings` 子 slot,以及注入的 `startSession`、`open` 和侧边栏切换回调。这里没有插件 store:`deriveGroups` 消费对象层快照与组件局部的展开/搜索状态。
|
||||
|
||||
页脚承载 `sidebar.settings`:侧边栏只渲染固定在底部的布局 slot,并共享其栏状态(`wide`);ui-settings 在此注册触发行和设置面板。
|
||||
|
||||
`/client` 导出表层只包含插件主体(`apply`/`inject`)及契约类型:SidebarRoot、行组件和树派生均属于内部实现(slot 注册通过闭包引用它们;测试直接导入 src 路径)。
|
||||
|
||||
## 模型体验
|
||||
|
||||
无。侧边栏渲染浏览器会话列表;这里没有任何内容进入模型请求。
|
||||
|
||||
#### KV Cache 影响
|
||||
|
||||
无;该包既不组装也不发送提供方请求。
|
||||
|
||||
## 已知限制与暂缓事项
|
||||
|
||||
- **状态点只有两种实时数据状态(running/none)**:done/error/amber 数据源随 P-II 审批与通知到来;四色原语已经接线。
|
||||
- **分组选单只提供按 Workspace 分组**:Update/Status 分组策略只有图稿而没有规范,暂缓实现。
|
||||
- **「New task completed」未读标记是本地查看状态**:完成时间 > 上次查看时间这一事实永远不会到达主机。
|
||||
6
packages/client/ui-slots/README.i18n.yaml
Normal file
6
packages/client/ui-slots/README.i18n.yaml
Normal 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: ed6f052b3a47e08d693928b6763e32427b829467
|
||||
README.zh.md: 8f15352d09a33a862203507ac89841da91a43e59
|
||||
@@ -1,5 +1,7 @@
|
||||
# @deepseek-ai/dsh-client-ui-slots
|
||||
|
||||
English | [中文](README.zh.md)
|
||||
|
||||
Slot registry pure core, slot terminal design: SlotMap declaration merging, the single `register` composition API on SlotCore, the four-share component-props type family, the store-seat type family, and the renderer install-seam contract. React types only at runtime — the package is React-free and cordis-free.
|
||||
|
||||
One `register({ name, children?, store?, inject?, ...kind }, Component)` call contributes a component into a declared slot and, in the same breath, declares child slots (declaration = render authorization = runtime spec, one table), a store seat, and the registrant's business face. The component is checked at the call site against `ComposedProps` — the intersection of four shares, each derived from its single source of truth:
|
||||
|
||||
35
packages/client/ui-slots/README.zh.md
Normal file
35
packages/client/ui-slots/README.zh.md
Normal file
@@ -0,0 +1,35 @@
|
||||
# @deepseek-ai/dsh-client-ui-slots
|
||||
|
||||
[English](README.md) | 中文
|
||||
|
||||
Slot 注册表纯核心、slot 终端设计:SlotMap 声明合并、SlotCore 上唯一的 `register` 组合 API、四 share 组件 props 类型家族、store seat 类型家族,以及 renderer 安装 seam 契约。React 类型仅在运行时使用,该包不依赖 React,也不依赖 cordis。
|
||||
|
||||
一次 `register({ name, children?, store?, inject?, ...kind }, Component)` 调用会向已声明 slot 贡献一个组件,同时声明子 slot(声明 = 渲染授权 = 运行时规范,三者共用一张表)、store seat 以及注册方的业务表层。组件会在调用点依据 `ComposedProps` 接受检查;该类型是四个 share 的交集,每个 share 都从各自的唯一真源派生:
|
||||
|
||||
| share | 类型 | 来源 |
|
||||
|---|---|---|
|
||||
| runtime | `PropsRuntime<K>` | SlotMap 配置项:`owner`(父级 renderSlot 调用点)+ Session 标准工具包 + 全局 seat |
|
||||
| child render | `PropsRenderSlots<S>` | register 调用的 `children` key 集合(静态缩窄的 `renderSlot`) |
|
||||
| store | `PropsStore<H>` | 已声明 handle:`useStore` selector hook + 移除 draft 的 `actions` |
|
||||
| business | `I` | 从 `inject` factory 返回值推断 |
|
||||
|
||||
chain-kind slot 会反转键控路由:配置项自行提名,而不是由分发点选择 `entryKey`。每次注册都携带一个纯 `ChainSelect` selector(另有可选的升序 `priority`,相同值按注册顺序处理);第一个非 null 返回值选中其配置项,并成为组件的 `matched` prop;全部返回 null 时则使用 owner 的 `renderSlotChain` fallback(`ChainRenderOpts`)。
|
||||
|
||||
标准工具包接口(`SessionStandardProps`、`GlobalStandardProps`)在这里声明为空,由 runtime 包合并(与 SlotMap key 相同的 declare-merge 模式)。renderer 会把运行时 Session 和 Workspace observable source 绑定为 selector hook。Inject factory 参数从声明派生(`InjectParams`):Session slot 获得 `sessionId`;声明 store 时追加 baked `actions`;没有其他参数,数据访问位于 apply 闭包的 ctx 中。
|
||||
|
||||
store 家族(输入 `defineStore` 规范/输出 `StoreHandle<T, A>`)为 store seat 建模:`init` 推断状态 schema;`actions` 是完整的 draft-transform 写入集合;`BakedActions` 移除 draft 参数,成为组件和 inject factory 收到的回调。`defineStore` 值实现位于 runtime 包(引擎所属位置),并满足这里导出的 `DefineStore` 契约。引擎产物与 renderer host 契约携带裸快照 source(`getSnapshot`/`subscribe`),绝不携带 React hook;hook 绑定属于渲染机制这一侧的 seam,只有 props 契约 hook 类型(`SnapshotSelectorHook`)位于这里。
|
||||
|
||||
`SlotCore` 在构造时播种先验的 `'root'` slot,并强制执行加载时验证(注册未声明 slot、重复声明子项、在两个 scope 下使用同一个共享 handle、chain 注册缺少 `select`,这些情况都在 register 时抛出)。配置项的 disposer 会递归折叠其声明的子 slot:账本行、贡献和 store 挂载都沿同一生命周期轴消失。`renderer.ts` 携带安装 seam(`SlotRenderer`、`SlotRendererHost`)以及 `StaleAuthorizationError`/`SlotOwnershipError`;实现在 web-react 中,安装则在外壳启动中完成。
|
||||
|
||||
## 模型体验
|
||||
|
||||
无。slot 注册表属于浏览器侧 UI 接线;这里没有任何内容进入模型请求。
|
||||
|
||||
#### KV Cache 影响
|
||||
|
||||
无;该包既不组装也不发送提供方请求。
|
||||
|
||||
## 已知限制与暂缓事项
|
||||
|
||||
- **`isLive` 会线性扫描所有记录**:在 UI 插件的注册规模(数十项)下没有问题;如果账本变得频繁访问,再使用配置项→记录反向引用改进。
|
||||
- **`__renders` 幻象锚点在 `PropsRenderSlots` 上可见**:这是与类型链设计的 `__accepts` 相同且已接受的噪声;泛型方法签名在 key 联合之间比较宽松,因此必须依靠逆变标记强制执行「组件 key 集合 ⊆ children 声明」。
|
||||
6
packages/client/ui-theme/README.i18n.yaml
Normal file
6
packages/client/ui-theme/README.i18n.yaml
Normal 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: 5c9794d4f5faea42861f47423d4e8980cbf89216
|
||||
README.zh.md: 2e0f76133ee38ba2fdc385e7fbb2a4a03b733cfa
|
||||
@@ -1,5 +1,7 @@
|
||||
# @deepseek-ai/dsh-client-ui-theme
|
||||
|
||||
English | [中文](README.zh.md)
|
||||
|
||||
Theme plugin: ThemeService over the --dsw-* token base stylesheets (static scale + alias semantic layers). The service owns the theme preference (`light`/`dark`/`system`, persisted under `dsh.theme`), resolves `system` through `prefers-color-scheme`, and publishes immutable `ThemeSnapshot`s on the `theme/change` event; it never touches the DOM — ui-layout's presenter applies the resolved snapshot (`body[data-ds-dark-theme]` + inline alias tokens). Contract: api-contracts v3 §8.
|
||||
|
||||
## Model Experience
|
||||
|
||||
18
packages/client/ui-theme/README.zh.md
Normal file
18
packages/client/ui-theme/README.zh.md
Normal file
@@ -0,0 +1,18 @@
|
||||
# @deepseek-ai/dsh-client-ui-theme
|
||||
|
||||
[English](README.md) | 中文
|
||||
|
||||
主题插件:基于 --dsw-* token 基础样式表(静态尺度 + 别名语义层)的 ThemeService。该服务拥有主题偏好(`light`/`dark`/`system`,以 `dsh.theme` 为键持久化),将 `system` 通过 `prefers-color-scheme` 解析为实际主题,并发布不可变的 `ThemeSnapshot`,通过 `theme/change` 事件通知变化;它绝不接触 DOM:ui-layout 的呈现器会应用解析后的快照(依据当前配色方案设置 `body[data-ds-dark-theme]`,并将主题的别名 token 设为内联变量)。契约:api-contracts v3 §8。
|
||||
|
||||
## 模型体验
|
||||
|
||||
无。主题服务管理浏览器偏好;这里没有任何内容进入模型请求。
|
||||
|
||||
#### KV Cache 影响
|
||||
|
||||
无;该包既不组装也不发送提供方请求。
|
||||
|
||||
## 已知限制与暂缓事项
|
||||
|
||||
- **第三方主题是表层,不是产品**:注册主题意味着覆盖同名别名变量;目前不会验证一组覆盖是否完整。
|
||||
- **token 样式表是颜色的唯一权威**:不会追加 cssdesign 中缺失的值(例如设计中的 #4176E6 标签页蓝色);应使用最接近的语义 token(裁定于 2026-07-22)。
|
||||
6
packages/client/ui-trajectory/README.i18n.yaml
Normal file
6
packages/client/ui-trajectory/README.i18n.yaml
Normal 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: 9e7dee8d5572baad13d7598d1fbde7b042dd5ab4
|
||||
README.zh.md: da14d5265c16acb4e75d21bc445ef9702c83e697
|
||||
@@ -1,5 +1,7 @@
|
||||
# @deepseek-ai/dsh-client-ui-trajectory
|
||||
|
||||
English | [中文](README.zh.md)
|
||||
|
||||
Trajectory turn-list chrome (sticky Turn / Message·Step groups / step cells) plus Waterfall placeholder; the pure-consumer minimal plugin exemplar (registers two view tabs into the conversation's `'conversation.view'` slot ring, provides no service, declares no Context merge). Contract: api-contracts v3 §8.
|
||||
|
||||
## Model Experience
|
||||
|
||||
17
packages/client/ui-trajectory/README.zh.md
Normal file
17
packages/client/ui-trajectory/README.zh.md
Normal file
@@ -0,0 +1,17 @@
|
||||
# @deepseek-ai/dsh-client-ui-trajectory
|
||||
|
||||
[English](README.md) | 中文
|
||||
|
||||
轨迹轮次列表 chrome(吸顶 Turn/Message·Step 分组/步骤单元格)及 Waterfall 占位符;这是纯消费方最小插件范例(向会话的 `'conversation.view'` slot 环注册两个视图标签页,不提供服务,也不声明 Context 合并)。契约:api-contracts v3 §8。
|
||||
|
||||
## 模型体验
|
||||
|
||||
无。轨迹视图在浏览器中渲染会话数据;这里没有任何内容进入模型请求。
|
||||
|
||||
#### KV Cache 影响
|
||||
|
||||
无;该包既不组装也不发送提供方请求。
|
||||
|
||||
## 已知限制与暂缓事项
|
||||
|
||||
- **进行中的 Time 保持空白**:`partial`/`runningCalls` 行在实时钟策略落地前渲染为 `—`;选中样式只在本地生效(未连接到聊天详情);锚点深链接仍暂缓实现。
|
||||
6
packages/client/ui-workspace/README.i18n.yaml
Normal file
6
packages/client/ui-workspace/README.i18n.yaml
Normal 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: e0247b3e26f617f86e9c0094afa1cbc920f02d33
|
||||
README.zh.md: 92ef463faab4b1ccda85d7f3cec1678a338d4010
|
||||
@@ -1,5 +1,7 @@
|
||||
# @deepseek-ai/dsh-client-ui-workspace
|
||||
|
||||
English | [中文](README.zh.md)
|
||||
|
||||
Shared Workspace picker plugin. `WorkspacePicker` is registered into the sidebar's `sidebar.workspace` slot and the page-local Session Intent hero's `conversation.empty.workspace` slot, so both surfaces use the same menu and creation modals.
|
||||
|
||||
The picker lists real Host Workspace entities through the global `useWorkspaces` hook. Selecting a Workspace invokes the slot owner's `onPick` callback to retarget the frontend Session object; the existing-folder and create-new actions first create a real Workspace through the object layer, then select it. Create-new disables names already present in that list, while the Host remains authoritative for concurrent or non-UI callers. The runtime Session and Workspace services own materialization.
|
||||
|
||||
22
packages/client/ui-workspace/README.zh.md
Normal file
22
packages/client/ui-workspace/README.zh.md
Normal file
@@ -0,0 +1,22 @@
|
||||
# @deepseek-ai/dsh-client-ui-workspace
|
||||
|
||||
[English](README.md) | 中文
|
||||
|
||||
共享 Workspace 选择器插件。`WorkspacePicker` 注册到侧边栏的 `sidebar.workspace` slot,以及页面局部 Session Intent 主视觉区的 `conversation.empty.workspace` slot,因此两个表层使用同一菜单和创建模态框。
|
||||
|
||||
该选择器通过全局 `useWorkspaces` hook 列出真实的 Host Workspace 实体。选择 Workspace 会调用 slot owner 的 `onPick` 回调,重新定位前端 Session 对象;使用现有文件夹和新建操作时,系统会先通过对象层创建真实 Workspace,再将其选中。新建操作会禁用列表中已有的名称,而 Host 对并发或非 UI 调用方仍具有最终决定权。运行时 Session 与 Workspace 服务负责物化。
|
||||
|
||||
两个目标 slot 都由其他插件声明,因此 `apply` 通过声明感知的延迟机制完成注册,并在声明该 slot 的插件恢复后重新注册。
|
||||
|
||||
## 模型体验
|
||||
|
||||
无。选择器属于浏览器 chrome;这里没有任何内容进入模型请求。
|
||||
|
||||
#### KV Cache 影响
|
||||
|
||||
无;该包既不组装也不发送提供方请求。
|
||||
|
||||
## 已知限制与暂缓事项
|
||||
|
||||
- **没有 Workspace 重命名/删除控件**:选择器仅支持选择和创建。
|
||||
- **现有文件夹入口仅支持手动输入路径**:Host 创建失败会显示在模态框中。
|
||||
6
packages/client/web-react/README.i18n.yaml
Normal file
6
packages/client/web-react/README.i18n.yaml
Normal 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: 7cc80f22bd5527838288d11c819e81b7ec4d17c4
|
||||
README.zh.md: ec7143db9a1fe97145a07a0a1fde45c9268c2425
|
||||
@@ -1,5 +1,7 @@
|
||||
# @deepseek-ai/dsh-client-web-react
|
||||
|
||||
English | [中文](README.zh.md)
|
||||
|
||||
Shell-side React glue for the slot terminal design: createSlotRenderer (the SlotRenderer implementation the shell installs into the runtime SlotsService), SessionProvider (framework-wired render prop, also injected as a standard seat to entries declaring session-scope children), bindSnapshotSelector (the one hook constructor — hosts and engines traffic in bare observable sources; every hook binds here, cached per source), useInvoke. Chain-slot outlets run the registered selectors in chain order at render time and mount only the elected entry, its select return joining the props as `matched`; the `renderSlotChain` binding is per-entry cached like `renderSlot`. The snapshot-store engine and defineStore live in runtime (store relocation); business plugins depend on ui-slots types only, never on this package.
|
||||
|
||||
## Model Experience
|
||||
|
||||
19
packages/client/web-react/README.zh.md
Normal file
19
packages/client/web-react/README.zh.md
Normal file
@@ -0,0 +1,19 @@
|
||||
# @deepseek-ai/dsh-client-web-react
|
||||
|
||||
[English](README.md) | 中文
|
||||
|
||||
slot 终端设计的外壳侧 React 胶水:createSlotRenderer(外壳安装到运行时 SlotsService 的 SlotRenderer 实现)、SessionProvider(框架接线的 render prop,也作为标准 seat 注入到声明会话 scope 子项的配置项)、bindSnapshotSelector(唯一的 hook 构造器:主机与引擎只传递裸 observable source;每个 hook 在此绑定,并按 source 缓存)、useInvoke。链式 slot outlet 在渲染时按链顺序运行已注册 selector,只挂载被选中的配置项,其 select 返回值以 `matched` 加入 props;`renderSlotChain` binding 与 `renderSlot` 一样按配置项缓存。快照 store 引擎与 defineStore 位于 runtime(store 已迁移);业务插件只依赖 ui-slots 类型,绝不依赖该包。
|
||||
|
||||
## 模型体验
|
||||
|
||||
无。ctx↔React 机制完全在浏览器中运行;这里没有任何内容进入模型请求。
|
||||
|
||||
#### KV Cache 影响
|
||||
|
||||
无;该包既不组装也不发送提供方请求。
|
||||
|
||||
## 已知限制与暂缓事项
|
||||
|
||||
- **persist 中间件会损坏原始值状态 store**:保存时它会对状态执行对象展开,因此 `SnapshotStore<string>` 往返后会变成字符 map;引擎改为自行实现持久化(见 `attachPersistence`)。
|
||||
- **`UseSession` 有意保持宽泛(`object` 快照)**:依赖方向(runtime → web-react,绝不反向)使真实 `ConversationSnapshot` 类型不可访问;会话 slot 消费方在其边界处缩窄一次。
|
||||
- **renderSlot 是唯一的 P-I 形式**:没有 Suspense,也没有逐配置项惰性加载;渐进式渲染表层会随其独立项目回归。
|
||||
6
packages/client/web/README.i18n.yaml
Normal file
6
packages/client/web/README.i18n.yaml
Normal 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: a4325f5dbe8ddd9bbe77086eb16fdb7aed9adc83
|
||||
README.zh.md: 9c1eab795145cf0a1b69528bc9822a26ed226023
|
||||
@@ -1,5 +1,7 @@
|
||||
# @deepseek-ai/dsh-client-web
|
||||
|
||||
English | [中文](README.zh.md)
|
||||
|
||||
Web shell kernel: `new AppWebEntry(el, seams?).run()` mounts the whole client through the two-stage boot (web2). Stage one (module face): build the client module system (`@deepseek-ai/dsh-client-modules`) over the host-pushed entry graph (`window.__DSH_BOOT__`) and prefetch the `immediately` tier in parallel — bundle execution registers factories only. Stage two (plugin face): mount the vendored cordis Loader with the module system injected as its `internal` seam, create one loader entry per graph row plus the shell-own app-shell assembly entry (tree.import materializes each module), and gate AppRoot on the settle (loader quiesced + every entry fiber ACTIVE → full UI in one switch). Composition is entirely the host graph's: the roster and the immediately tier live in the composing app; the shell makes zero composition decisions.
|
||||
|
||||
Shell self-sufficiency (web2 hard rule): the kernel value-imports no plugin package — the boot status store and signals are hand-rolled here (`loader-status.ts`), so the loading page works while (and especially when) plugins fail. The app-shell assembly (`@deepseek-ai/dsh-client-app-shell`, a shell-owned pseudo entry with no npm package behind it) is the only module registered through `registerStatic`; it inject-waits on slots/sessions/layout like any plugin.
|
||||
|
||||
26
packages/client/web/README.zh.md
Normal file
26
packages/client/web/README.zh.md
Normal file
@@ -0,0 +1,26 @@
|
||||
# @deepseek-ai/dsh-client-web
|
||||
|
||||
[English](README.md) | 中文
|
||||
|
||||
Web 外壳内核:`new AppWebEntry(el, seams?).run()` 通过两阶段启动(web2)挂载整个客户端。第一阶段(模块表层):构建客户端模块系统(`@deepseek-ai/dsh-client-modules`),以主机推送的配置项图(`window.__DSH_BOOT__`)为基础,并行预抓取 `immediately` 层级;执行组合包只会注册 factory。第二阶段(插件表层):挂载 vendored cordis Loader,并把模块系统作为其 `internal` seam 注入;为每一行图数据创建一个 loader 配置项,另创建外壳自身的 app-shell 组装配置项(tree.import 会物化各模块);以 settle 作为 AppRoot 的门禁(loader 完全停稳 + 每个配置项 fiber 都为 ACTIVE → 一次切换显示完整 UI)。组合完全由主机图决定:花名册和 immediately 层级都位于负责组合的应用中;外壳不作任何组合决策。
|
||||
|
||||
外壳自给自足(web2 硬性规则):内核不对任何插件包执行值导入;启动状态 store 与信号在这里手写(`loader-status.ts`),因此插件失败时(尤其在失败时)加载页面仍能工作。app-shell 组装(`@deepseek-ai/dsh-client-app-shell`,由外壳拥有、背后没有 npm 包的伪配置项)是唯一通过 `registerStatic` 注册的模块;它与任何插件一样,通过 inject 等待 slots/sessions/layout。
|
||||
|
||||
`PLATFORM_MODULES`(src/platform.ts)是共享模块表层的唯一真源:种子表 key、tsdown 客户端 external 和 vite alias 集都是它的投影。
|
||||
|
||||
可选 `seams` 参数会转发模块系统的 `fetchBundle`/`executeBundle` 传输覆盖(`BootSeams`);生产调用方省略此参数。它用于测试环境,因为此类环境中的 `<script>` 执行无法到达页面上下文(jsdom)。
|
||||
|
||||
外壳拥有浏览器标题投影。选中带有持久标题的会话时,它会渲染 `<session title> — <existing HTML title>` 并响应后续标题修订;未选择会话或选中无标题会话时,会保留现有标题;外壳卸载时恢复标题。现有 HTML 标题仍是可配置的产品后缀。
|
||||
|
||||
## 模型体验
|
||||
|
||||
无。配置项外壳负责启动浏览器插件树;这里没有任何内容进入模型请求。
|
||||
|
||||
#### KV Cache 影响
|
||||
|
||||
无;该包既不组装也不发送提供方请求。
|
||||
|
||||
## 已知限制与暂缓事项
|
||||
|
||||
- **有意采用一次性渲染**:UI 等待启动 settle;只要一个配置项失败,加载页面就会保留并高声逐项报告,不提供部分可用性(渐进式渲染会随其独立项目回归)。
|
||||
- **窄窗口验收暂缓**:ui-layout 已实现让步链,但外壳级窄视口演练是 P-II 验收项。
|
||||
6
packages/code-runtime/README.i18n.yaml
Normal file
6
packages/code-runtime/README.i18n.yaml
Normal 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: dbe6b37ffa01d07c6902672a06ebf6f88548ff99
|
||||
README.zh.md: fd73e1376afe5ae4390457fa648b9f19591ee71c
|
||||
@@ -1,5 +1,7 @@
|
||||
# code-runtime/ — code-execution capability family
|
||||
|
||||
English | [中文](README.zh.md)
|
||||
|
||||
The code-execution capability seam (see [capability seams](../../.agents/notes/implemented/architecture/2026-06-13-capability-seams.md)): an abstract runtime interface for executing one model-written program against host-provided async bindings, capturing what it printed and returned. The consumer is the tool registry's [Code Mode](../core/tools/README.md) (`tools: { mode: code }` — the `run_code` tool and the generated TypeScript SDK); design in the [Code Mode Agent Note](../../.agents/notes/implemented/feature/2026-06-15-code-mode.md). **Product** packages.
|
||||
|
||||
| Package | Role | ctx key |
|
||||
|
||||
12
packages/code-runtime/README.zh.md
Normal file
12
packages/code-runtime/README.zh.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# code-runtime/:代码执行能力家族
|
||||
|
||||
[English](README.md) | 中文
|
||||
|
||||
代码执行能力 seam(参见[能力 seam](../../.agents/notes/implemented/architecture/2026-06-13-capability-seams.md)):一个抽象运行时接口,用于针对宿主提供的异步绑定执行一段模型编写的程序,并捕获程序打印和返回的内容。消费方是工具注册表的 [Code Mode](../core/tools/README.md)(`tools: { mode: code }`,即 `run_code` 工具与生成的 TypeScript SDK);设计记录在 [Code Mode Agent Note](../../.agents/notes/implemented/feature/2026-06-15-code-mode.md) 中。这些都是**产品** 包。
|
||||
|
||||
| 包 | 职责 | ctx 键 |
|
||||
|---|---|---|
|
||||
| `code-runtime/` | 抽象代码执行 seam(接口 + 词汇) | `ctx.codeRuntime` |
|
||||
| [`code-runtime-worker/`](code-runtime-worker/README.md) | worker 线程后端:每次运行使用全新 worker,由宿主侧剥离 TypeScript 类型(类型注解仅供参考,绝不执行类型检查)、端口桥接绑定、预算/堆隔离 | 注册 `ctx.codeRuntime` |
|
||||
|
||||
接口位于 `code-runtime/code-runtime/`,随附后端位于 `code-runtime/code-runtime-worker/`。不同后端可以采用不同执行基底(worker 线程、进程、容器)与源语言;二者都是服务上的只读描述符。后端注册 `ctx.codeRuntime`,无需修改接口或消费方;正是这种拆分,使未来可以直接换入强化后端。
|
||||
@@ -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: acc0e37e73d3887c70a77d16311305e52f5a4030
|
||||
README.zh.md: 15983dba00eff6fbc6e6d32a4d22df3a4249af76
|
||||
@@ -1,5 +1,7 @@
|
||||
# @deepseek-ai/dsh-code-runtime-worker
|
||||
|
||||
English | [中文](README.zh.md)
|
||||
|
||||
Worker-thread implementation of the [`@deepseek-ai/dsh-code-runtime`](../code-runtime/README.md) seam: `WorkerCodeRuntime` runs each program in ONE fresh Node `worker_threads.Worker` — TypeScript in, type-stripped host-side, bindings bridged over the message port, `{ value, logs, error? }` out. **Containment, not a security boundary**: trust posture is bash-equivalent by design (the [Code Mode Agent Note](../../../.agents/notes/implemented/feature/2026-06-15-code-mode.md) § Trust posture), with containment bash does not have — separate isolate, empty environment, heap cap, hard termination.
|
||||
|
||||
## Config
|
||||
|
||||
54
packages/code-runtime/code-runtime-worker/README.zh.md
Normal file
54
packages/code-runtime/code-runtime-worker/README.zh.md
Normal file
@@ -0,0 +1,54 @@
|
||||
# @deepseek-ai/dsh-code-runtime-worker
|
||||
|
||||
[English](README.md) | 中文
|
||||
|
||||
这是 [`@deepseek-ai/dsh-code-runtime`](../code-runtime/README.md) seam 的 worker 线程实现:`WorkerCodeRuntime` 会在每次运行中使用一个全新的 Node `worker_threads.Worker`,输入 TypeScript,由宿主侧剥离类型,通过消息端口桥接绑定,输出 `{ value, logs, error? }`。**这是隔离措施,而非安全边界**:其信任立场有意与 bash 等价(参见 [Code Mode Agent Note](../../../.agents/notes/implemented/feature/2026-06-15-code-mode.md) 的 Trust posture 章节),但提供 bash 没有的隔离:独立 isolate、空环境、堆上限与强制终止。
|
||||
|
||||
## 配置
|
||||
|
||||
```yaml
|
||||
- id: code-runtime
|
||||
name: '@deepseek-ai/dsh-code-runtime-worker'
|
||||
config:
|
||||
computeMs: 60000 # busy-time budget (measured event-loop active time)
|
||||
maxWallMs: 600000 # wall-clock ceiling; never pauses for anything
|
||||
maxOutputBytes: 67108864 # combined serialized outer-output cap (64 MiB)
|
||||
maxOldGenerationSizeMb: 512 # worker heap cap (resourceLimits)
|
||||
```
|
||||
|
||||
每个字段都会验证并提供默认值;`maxOutputBytes` 必须是至少 4 字节的安全整数,其余字段必须是有限正数,此外没有其他可调项。
|
||||
|
||||
## 设计
|
||||
|
||||
- **每次运行使用一个全新 worker,不设池化**:程序所在的世界会随 worker 一同终止,不会留下需要记录的跨运行状态,也无法发生状态泄漏;仅凭会话日志即可重建运行。
|
||||
- **在执行上下文中,由宿主侧剥离类型**:程序会包裹在异步函数外壳中,通过 `node:module` 的 `stripTypeScriptTypes` 剥离类型(只支持可擦除语法;`enum`/namespace 会作为程序 `exception` 被拒绝,且不会启动 worker),再按字节位置切回原内容。之后程序作为 `AsyncFunction` 的函数体执行,因此顶层 `await`/`return` 可用。
|
||||
- **端口把对端视为不可信**:模型代码能够访问 `parentPort` 并伪造通信,因此任何代码读取入站消息前,系统都会验证其形状并重新构建(`null`、原始值、无效类型和格式错误的载荷会被静默丢弃;伪造的额外字段绝不会被带入);宿主对每个调用 id 最多响应一次,只将绑定名称解析为自有属性(伪造的 `constructor` 无法沿原型链访问),丢弃结算后的回复,并验证每个绑定 resolve 值与完成值是否为无损 JSON。伪造的 `log`/`done` 消息无法绕过外层上限:宿主会再次验证,并统计每条获准日志以及完成值或诊断。worker 侧命名空间使用 null-prototype 和 `defineProperty`,因此形似 `__proto__` 的绑定名称只是普通键。
|
||||
- **绑定 reject 类属于请求数据**:可选命名空间描述符会指定构造器全局变量,以及用于接收失败成员名称的自有属性。worker 会创建并注入该真实类,使 `instanceof` 生效,同时无需硬编码 `tools` 或 `ToolCallError`;全局变量无效或冲突的声明会在启动 worker 前失败。失败路径使用模块捕获的错误与属性定义 intrinsic,以及 null-prototype 描述符,因此模型之后的修改无法把被拒绝的绑定变成 worker 崩溃。
|
||||
- **两个独立预算,因为对端不可信**:`computeMs` 统计 worker 实际测得的忙碌时间(轮询 `worker.performance.eventLoopUtilization()`);热循环无法借助待完成的诱饵 dispatch 隐藏,程序等待慢工具时则不累计。`maxWallMs` 为忙碌时间无法观测的情况兜底(例如等待永远不会 resolve 的 promise)。二者最终都会调用 `worker.terminate()`,连同步热循环也能终止;堆溢出会表现为 worker 的 OOM 退出(`kind: 'worker-exit'`)。
|
||||
- **中间绑定值是完整 JSON**:绑定参数与 resolve 值会接受迭代式无损 JSON 验证。程序执行前,worker 会捕获自己 realm 中的普通容器原型身份,以及只用于外部 realm 的原生函数源码检查,因此构造器槽修改和用户编写的仿冒对象都无法改变容器分类。它还会捕获该 JSON 边界使用的每一个结构与计量 intrinsic,以无原型对象创建属性描述符,并绕过可变集合原型管理私有遍历状态;因此,模型对全局对象、原型方法或 `Object.prototype` 上形似描述符字段的修改,都无法改变验证、wire 传输或字节计量。值会展平为有深度上限的前序 wire 值,供 structured clone 使用,并在另一侧迭代式重建。它们没有字节、JavaScript 调用栈或嵌套 structured-clone 深度上限,绝不会进入外层输出账本或模型上下文;上限仍来自提供方/执行器获取限制与进程/worker 内存。
|
||||
- **日志主动流入一个外层账本**:console/stdout/stderr 文本按发送顺序穿过端口,因此超时或被终止的程序仍会显示已经打印的内容。worker 会按 JSON 字符串精确计费,并在发送完成值和异常诊断前,根据组合预算的剩余量预检;因此,抛出的百万字节 stack 会在 worker 边界变成固定的 `output-limit` 诊断。绕过补丁 stream 槽的原生写入会到达独立于完成端口的 pipe,因此宿主会针对这些字节和不可信伪造通信再次执行账本统计;在物化结果前,结算过程会持续进行有界 pipe 捕获,直到 worker 完成终止。`maxOutputBytes` 统计外层 `logs` 数组加完成值或失败消息载荷的 JSON 序列化;固定的 `CodeRunResult` 字段名、花括号、有界错误 kind 标签,以及后续呈现空白不计入这份可变载荷账本。未超过上限时会返回精确值;有损完成值属于 `invalid-output`,组合溢出属于 `output-limit`,不会用 inspected string 代替。失败会保留能容纳的已捕获前缀,之后按普通外层 `run_code` 落盘策略处理。
|
||||
- **空环境**:worker 使用 `env: {}` 和 `execArgv: []`,既没有环境凭据(比 spawn 命令的清理环境规则更严格),也不会继承 loader 标志。
|
||||
- **释放资源时等待完全停稳**:清理会把进行中的运行标记为 `abort`,并在 resolve 前等待每个 worker 退出。
|
||||
|
||||
## 未构建与已构建的 worker 入口
|
||||
|
||||
源代码模式通过 Node 原生类型剥离加载只包含可擦除语法的 `src/worker.ts`。其传递运行时闭包只包含 Node 内置模块和相对源模块,因此全新 checkout 绝不需要兄弟工作区包尚未构建的 `lib/` 导出。worker 本地 JSON 快照器会与会话自有的规范边界执行一致性测试;消息端口两侧都会展平并重建已验证值,使应用嵌套永远不会进入 structured clone。构建模式会把兄弟文件 `lib/worker.cjs` 作为文件系统路径传入,因为 pkg 的 VFS Worker hook 要求 CommonJS;同一路径也可在普通 Node 下使用。`tests/built-lib.e2e.ts` 固定了 [docs/testing.md](../../../docs/testing.md) 要求的真实加载路径。
|
||||
|
||||
SDK 接口是默认/具名 `WorkerCodeRuntime` 类与 `Config`。可操作的 `./worker` 子路径仅作为打包后的 spawn 入口存在;wire 协议与启动辅助模块是源代码私有的实现细节。
|
||||
|
||||
## 模型体验
|
||||
|
||||
通过 [`dsh-tools`](../../core/tools/README.md) 中的 Code Mode 间接提供;如果外层值能容纳则原样渲染,否则返回明确的 `invalid-output`/`output-limit` 失败。只有外层 `run_code` 结果进入模型上下文并使用普通落盘策略;绑定通信与中间值始终只存在于执行环境中。
|
||||
|
||||
#### KV Cache 影响
|
||||
|
||||
不会直接失效;由具名消费方负责请求前缀变更。
|
||||
|
||||
## 已知限制与暂缓工作
|
||||
|
||||
- **程序 spawn 的 OS 进程在终止后仍会存活**:`worker.terminate()` 只结束线程,比 bash-local 的进程组终止更弱;在容器后端出现前,孤儿清理属于部署职责。
|
||||
- **类型剥离依赖 Node 的实验性 `stripTypeScriptTypes` API**:依赖的行为由单元测试固定;如其发生变化,amaro/sucrase 是已经点名的直接替代品。
|
||||
- **`computeMs` 到期最多可能超过一个轮询间隔**:系统每 25 ms 采样一次忙碌时间(内部常量,有意不做成配置)。
|
||||
- **程序获得一个含 5 种方法的 `console` shim**(`log`/`info`/`warn`/`error`/`debug`):有意不提供 Node 的完整 console 接口。
|
||||
- **中间绑定值没有字节上限**:程序可以用永远不会成为外层输出的值耗尽进程或 worker 内存。
|
||||
- **默认 64 MiB 是拒绝边界,不是可恢复存储**:外层落盘只能保存发生 `output-limit` 后返回的有界日志和诊断;在运行时上限之外被拒绝的字节永远不会到达落盘层。
|
||||
6
packages/code-runtime/code-runtime/README.i18n.yaml
Normal file
6
packages/code-runtime/code-runtime/README.i18n.yaml
Normal 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: c7a2d519e47d160f5ab123bfc887e7e9f24ec602
|
||||
README.zh.md: 10c1b900165e255a3ea57197ae323283822ab7bc
|
||||
@@ -1,5 +1,7 @@
|
||||
# @deepseek-ai/dsh-code-runtime
|
||||
|
||||
English | [中文](README.zh.md)
|
||||
|
||||
The **code-execution seam**: an abstract `CodeRuntime` service (`ctx.codeRuntime`) defining WHAT a code runtime does — run one model-written program against a set of host-provided async bindings and report `{ value, logs, error? }` — without saying HOW.
|
||||
|
||||
This package is the interface third of the capability (the bash trio is the template — see [capability seams](../../../.agents/notes/implemented/architecture/2026-06-13-capability-seams.md)): implementations subclass `CodeRuntime` and register the service; the consumer is the tool registry's Code Mode, which generates the model-facing SDK and bridges tool dispatch — both specified in the [Code Mode Agent Note](../../../.agents/notes/implemented/feature/2026-06-15-code-mode.md), whose first implementation is a Node worker-thread backend. The runtime knows nothing about tools or sessions: it is handed named async functions and a program string, and everything tool-shaped stays with the consumer.
|
||||
|
||||
36
packages/code-runtime/code-runtime/README.zh.md
Normal file
36
packages/code-runtime/code-runtime/README.zh.md
Normal file
@@ -0,0 +1,36 @@
|
||||
# @deepseek-ai/dsh-code-runtime
|
||||
|
||||
[English](README.md) | 中文
|
||||
|
||||
这是**代码执行 seam**:抽象的 `CodeRuntime` 服务(`ctx.codeRuntime`)只定义代码运行时做什么,即针对宿主提供的一组异步绑定运行一段模型编写的程序,并报告 `{ value, logs, error? }`,而不规定如何实现。
|
||||
|
||||
此包是该能力的接口层(以 bash 三包结构为模板,参见[能力 seam](../../../.agents/notes/implemented/architecture/2026-06-13-capability-seams.md)):实现通过继承 `CodeRuntime` 并注册服务接入;消费方是工具注册表的 Code Mode,它生成面向模型的 SDK,并桥接工具分发。两者都由 [Code Mode Agent Note](../../../.agents/notes/implemented/feature/2026-06-15-code-mode.md) 规定,首个实现是 Node worker 线程后端。运行时不了解工具或会话:调用方只向它提供具名异步函数与程序字符串;所有工具形状的内容都留在消费方。
|
||||
|
||||
## 服务 API(`ctx.codeRuntime`)
|
||||
|
||||
| 成员 | 语义 |
|
||||
|---|---|
|
||||
| `run(request)` | 针对请求的绑定执行一段程序。**每一种程序结果都通过 error 字段完成 resolve**:包括解析/转换失败、抛出异常、无效完成值、输出溢出、预算到期、中止或执行基底死亡(由 `CodeRunFailure` 的正交 `kind` 分类表示);只有调用方误用 seam 本身时才 reject(例如资源释放后仍提交运行)。程序作为异步函数的函数体运行,因此顶层 `await`/`return` 可用,无损 JSON 完成值会成为 `result.value`。 |
|
||||
| `language` | 只读描述符:`run` 期望的源语言(已知值为 `'typescript'`)。仅供参考,不作门禁;生成语言专用呈现的消费方会对该值执行分支,遇到无法呈现的语言时明确失败。 |
|
||||
| `isolation` | 只读描述符:执行基底(`'worker-thread'`、`'process'`、`'container'`)。供部署与诊断使用,**不构成安全声明**。 |
|
||||
|
||||
每个实现都必须遵守以下语义(完整契约见类 JSDoc):绑定调用会桥接完整的无损 JSON 参数与 resolve 值,seam 层不设字节上限;程序被视为不可信对等方(任意绑定名称都是自有属性,格式错误的通信绝不能使宿主崩溃);不同运行之间不保留任何状态;资源释放会终止进行中的运行,并且在完成前等待其退出。
|
||||
|
||||
## 词汇
|
||||
|
||||
`CodeRunRequest`(`program`、`bindings`、`signal?`)携带运行时操作所需的全部内容;默认值解析(时间预算与外层输出上限)属于实现的已验证配置,绝不能是隐藏的 `??`,更不能藏在 `run()` 内部。`bindings` 是 `CodeBindingNamespace` 列表(`global` + `functions` + 可选 `errorClass`);每个命名空间会作为一个由异步可调用函数组成的全局对象公开给程序,这些函数返回 `CodeJsonValue`。后者是 seam 本地、与规范 `JsonValue` 结构等价的类型,使接口包保持独立于会话。`errorClass` 描述符点名真实的程序全局构造器,以及用于接收 reject 成员名称的自有属性;运行时不依赖 `ToolCallError` 等消费方术语。`CodeRunResult` 报告无损 JSON 完成值 `value?`、有序的 `logs: string[]` 和 `error?`(`CodeRunFailure`:`kind` + 可反馈给模型的 `message`)。完整契约见 `src/types.ts`。
|
||||
|
||||
## 模型体验
|
||||
|
||||
通过 `dsh-tools` 中的 Code Mode 间接提供;后者公开 `run_code`,并将程序日志、值或失败作为保留的工具结果 token 返回。
|
||||
|
||||
#### KV Cache 影响
|
||||
|
||||
不会直接失效;由具名消费方负责请求前缀变更。
|
||||
|
||||
## 已知限制与暂缓工作
|
||||
|
||||
- **`run()` 是一次性的**:`logs` 只有在 `CodeRunResult` resolve 后才能获得;seam 不提供活跃程序输出的流式日志或进度接口。
|
||||
- **持久 REPL 风格内核已记录为未来工作**:在持久内核后端带来自己的日志方案前,运行之间不保留状态的契约继续有效(参见 [Code Mode Agent Note](../../../.agents/notes/implemented/feature/2026-06-15-code-mode.md))。
|
||||
- **目前只提供 worker 线程后端**:`'process'`/`'container'` 是已经声明但没有实现的已知 `isolation` 值;硬安全边界需要等待容器后端。
|
||||
- **中间绑定值没有字节上限**:实现仍受 structured-clone 成本与进程内存约束,而提供方或执行器可能已经应用自己的获取上限。
|
||||
6
packages/compact/README.i18n.yaml
Normal file
6
packages/compact/README.i18n.yaml
Normal 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: 3c3644adce23c12db37241bf797ea614d273a0fb
|
||||
README.zh.md: ad3abfd4f6064a44ecb22cd22b6c969247484de3
|
||||
@@ -1,5 +1,7 @@
|
||||
# compact/ — compaction capability family
|
||||
|
||||
English | [中文](README.zh.md)
|
||||
|
||||
A compaction capability family (see [capability seams](../../.agents/notes/implemented/architecture/2026-06-13-capability-seams.md)): an abstract interface, a summarizing backend, a model-free tool-result pruning companion, and a deferred model-facing consumer. All **product** packages.
|
||||
|
||||
| Package | Role | ctx key |
|
||||
|
||||
14
packages/compact/README.zh.md
Normal file
14
packages/compact/README.zh.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# compact/:压缩能力家族
|
||||
|
||||
[English](README.md) | 中文
|
||||
|
||||
一个压缩(compaction)能力家族(见[能力 seam](../../.agents/notes/implemented/architecture/2026-06-13-capability-seams.md)):抽象接口、摘要后端、不依赖模型的工具结果剪枝配套组件,以及暂缓实现的面向模型消费方。这些全是**产品** 包。
|
||||
|
||||
| 包 | 职责 | ctx key |
|
||||
|---|---|---|
|
||||
| `compact/` | 抽象压缩 seam(接口 + `compact/*` 事件 + `CompactionResult`) | `ctx.compact` |
|
||||
| `compact-basic/` | 后端:`ctx.tokenMeter` 压力 + token 预算保留 + `llm.stream()` 摘要生成 | (注册 `ctx.compact`) |
|
||||
| `compact-tool-result-prune/` | 可选的不依赖模型的头/中/尾重写,在摘要压缩之前运行 | `ctx.toolResultPrune` |
|
||||
| `tool-compact/`(暂缓) | 面向模型的 `/compact` 工具,基于 `ctx.compact` | (注册到 `ctx.tools`) |
|
||||
|
||||
接口位于 `compact/compact/`,后端位于 `compact/compact-basic/`,确定性剪枝位于 `compact/compact-tool-result-prune/`。与 bash seam 不同,该接口依赖 `dsh-session` 和 `dsh-llm`,因为它的动词基于 `Session` 定义,输出则使用 `ContentBlock`。这项偏差记录在[压缩能力 seam Agent Note](../../.agents/notes/implemented/feature/2026-06-18-compaction-capability-seam.md) 中。token 测量仍是可复用的 LLM 家族服务;模板或模型支持的压缩器可以替换 `compact-basic`,而无需更改计量器、剪枝器或调用方。
|
||||
6
packages/compact/compact-basic/README.i18n.yaml
Normal file
6
packages/compact/compact-basic/README.i18n.yaml
Normal 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: 2f65b0d8f223c4de8999006d005778e7087e8a4d
|
||||
README.zh.md: c0be5d7dc92a60c649b792bfa181c0df7a12db9f
|
||||
@@ -1,5 +1,7 @@
|
||||
# @deepseek-ai/dsh-compact-basic
|
||||
|
||||
English | [中文](README.zh.md)
|
||||
|
||||
The **basic compaction backend**: a `BasicCompactService` implementing the `@deepseek-ai/dsh-compact` seam with reusable `ctx.tokenMeter` pressure, token-budget retention, and summarization as a direct one-shot `ctx.llm.stream()` call that replays the conversation prefix to reuse the provider's KV cache (interceptable at `llm/stream`).
|
||||
|
||||
This is the implementation tier of the compaction capability — see the [interface package](../compact/README.md) for the seam and the [capability-seam Agent Note](../../../.agents/notes/implemented/feature/2026-06-18-compaction-capability-seam.md) for the design.
|
||||
|
||||
161
packages/compact/compact-basic/README.zh.md
Normal file
161
packages/compact/compact-basic/README.zh.md
Normal file
@@ -0,0 +1,161 @@
|
||||
# @deepseek-ai/dsh-compact-basic
|
||||
|
||||
[English](README.md) | 中文
|
||||
|
||||
**基础压缩(compaction)后端**:`BasicCompactService` 实现 `@deepseek-ai/dsh-compact` seam,使用可复用的 `ctx.tokenMeter` 压力、token 预算保留与摘要。摘要是直接的一次性 `ctx.llm.stream()` 调用,它会回放会话前缀以复用提供方的 KV cache(可在 `llm/stream` 处拦截)。
|
||||
|
||||
这是压缩能力的实现层。seam 见 [接口包](../compact/README.md),设计见 [能力 seam Agent Note](../../../.agents/notes/implemented/feature/2026-06-18-compaction-capability-seam.md)。
|
||||
|
||||
## 拥有的职责
|
||||
|
||||
该后端拥有压缩策略:
|
||||
|
||||
- **测量**:单例 `ctx.tokenMeter` 会在同一个已消费日志 revision 上为最新规范已记录 envelope 与当前表层计价。因此,步骤后压力会包含实际系统提示词、工具、前缀、路由、assistant 完成、工具结果、缓冲上下文与 steering。
|
||||
- **路由策略**:主动压力从拥有最新持久提供方/模型路由的适配器解析容量,再将默认策略与可选的精确目标覆盖缩放为具体 token 预算。模型发现仍只提供建议,不会被咨询。
|
||||
- **不依赖模型的剪枝**:在压力或规范溢出符合条件后,可选的 [`ctx.toolResultPrune`](../compact-tool-result-prune/README.md) 服务会在选择范围之前改写超大工具结果。Compact-basic 通过 `ctx.tokenMeter` 重新测量;如果压力已回到安全范围,就跳过摘要,否则摘要已剪枝表层。低于压力的步骤后检查绝不剪枝。
|
||||
- **保留**:压缩最旧的完整表层单元,同时保留近期尾部,并通过 [`dsh-compact` 边界 helper](../compact/README.md#tool-pairing-boundaries) 保持工具调用/结果 cut 平衡。轮次边界不会保护失控轮次内的旧步骤。开启且不可分的尾部在关闭前会拒绝压缩。当闭合的超大工具单元以文本型结果为可移除主体时,可选 pruner 可以修复它;不可分的非工具单元与不可剪枝的工具剩余部分不在范围内。
|
||||
- **收敛**:最多按 `compactionRetries` 重试头部检查点压缩;拒绝不能缩小源内容的摘要,如果重试仍无法回到阈值以下,则抛出异常。
|
||||
- **摘要**:直接 `llm/stream` 调用使用已配置的提供方/模型对与上限,回退到最新已记录请求目标,然后再回退到 agent(智能体)目标,而不运行仅用于 loop 的 `agent/request` seam。该调用会逐字回放会话自身的系统提示词、工具与已遮蔽区域消息,并将压缩指令作为最后一条 user 消息追加,从而复用提供方的热前缀 cache,而非使它失效。它将 `GenerateOptions.purpose` 设为 `compaction`,适配器可将其作为请求归因转发(DeepSeek 适配器发送 `x-deepseek-harness-compact: 1`),但不会触碰模型可见主体。只有返回文本会进入检查点;会排除可能泄露私有推理或产生遗留调用的 reasoning 与工具调用。
|
||||
- **框定**:替换 user 消息使用 `<compacted-summary>` 标签标记已建立的检查点上下文。原始摘要保留在溯源事件上,后续自动周期会合并之前的检查点。
|
||||
- **生命周期**:`compactRegion()` 会更改 `agent.session`,并记录开始、摘要、替换与结束。异步摘要后,它会拒绝已改变的表层节点快照,而不相关的仅日志事件可以追加,不会使已选 span 失效。串行 `agent/post-step` listener 会在成功输出与工具工作持久后、`step/end` 之前检查压力。规范提供方溢出会在失败步骤关闭后通过 `agent/request-error` 处理。
|
||||
- **溢出恢复**:提供方已确认的溢出不需容量元数据。它会绕过常规压力与保留,执行剪枝,再尝试一次最大平衡头部缩减,并留下最新不可分单元。只要 `surface.replaceGeneration` 前进,就允许重试,包括剪枝在后续摘要工作抛出异常前已落地的情况。如果没有替换、精确目标上限已耗尽、已取消,或遇到未知/非规范错误,则保留原始提供方失败。
|
||||
- **失败处理**:不匹配的 `compact/start` 是惰性崩溃标记,因为没有摘要替换落地。区域失败会记录错误结束;除非剪枝已落地,否则表层保持不变。操作性步骤后失败会发出警告并继续;只当之前没有替换使表层前进时,溢出恢复失败才保留原始提供方错误。取消在任何进展后仍具有最高权威。
|
||||
|
||||
受保护的 `summarize()` 方法是唯一的子类 hook。基于模板或远程摘要器的子类可以覆盖该方法,同时压力、保留、溯源、缩减验证与已遮蔽 token 计量仍位于 `ctx.tokenMeter`。hook 会将摘要块与它使用的调用 envelope 一并返回(`{ summary, provider, model, maxTokens? }`),并记录在 `compact/summary` 上。
|
||||
|
||||
## 配置(`BasicCompactConfig`)
|
||||
|
||||
所有设置都可选。顶层策略字段是每个已路由模型的默认值;`modelPolicies` 对精确提供方/模型对应用部分覆盖。出现压力时,compact-basic 会请求所属 LLM 适配器提供该路由的上下文容量,并解析绝对预算。无法识别的 key、重复目标、互斥保留形式,以及合并后的 `retainRatio` 不低于 `thresholdRatio`,都会使插件加载失败。不低于缩放后阈值的绝对 `retainTokens` 预算会在第一个可解析目标上失败,因为该比较需要模型容量。
|
||||
|
||||
| Key | 必填 | 含义 |
|
||||
|---|---|---|
|
||||
| `thresholdRatio` | 否(默认 `0.8`) | 在 `floor(routedContextWindow × ratio)` 处压缩。 |
|
||||
| `retainRatio` | 否(默认 `0.16`) | 以已路由上下文窗口的一部分表示逐字保留的近期表层预算;与 `retainTokens` 互斥。 |
|
||||
| `retainTokens` | 否 | 逐字保留的近期表层绝对预算;与 `retainRatio` 互斥,并且必须低于已解析阈值。 |
|
||||
| `summarizationProvider` | 否(默认 `''`) | 与 `summarizationModel` 一起设置;空对会解析为最新已记录请求目标,再回退到 `AgentOptions` 对。 |
|
||||
| `summarizationModel` | 否(默认 `''`) | 与 `summarizationProvider` 一起设置;空对会解析为最新已记录请求目标,再回退到 `AgentOptions` 对。 |
|
||||
| `maxTokens` | 否(默认 `8192`) | 摘要调用的提供方生成上限;可包含 reasoning token。 |
|
||||
| `compactionRetries` | 否(默认 `1`) | 压力仍高于阈值时,在首次尝试后进行的额外尝试次数。 |
|
||||
| `maxOverflowRetries` | 否(默认 `1`) | 规范上下文窗口溢出后的最大重试次数;`0` 只禁用恢复。 |
|
||||
| `modelPolicies` | 否(默认 `[]`) | 精确的 `{ provider, model, ...partialPolicy }` 覆盖;匹配使用两个字段,不依赖 `listModels()`。 |
|
||||
| `auto` | 否(默认 `true`) | 注册步骤后压力与溢出恢复 listener。设为 `false` 则仅手动执行。 |
|
||||
|
||||
每个 `modelPolicies` 配置项都接受上述策略字段,但不接受 `auto` 和 `modelPolicies` 自身。如果配置项提供任意一个保留字段,就替换默认策略的保留选择;否则继承保留设置。摘要提供方/模型在每个配置项内仍然成对。
|
||||
|
||||
适配器可能无法为有效动态路由返回容量,已解析容量也可能暴露无效的绝对保留预算。此时手动压力检查会抛出目标特定配置错误;自动 listener 会对该精确目标警告一次,并携带完整历史继续。不相关的操作性失败仍会独立可见。规范提供方溢出仍会尝试恢复,因为提供方已确立压缩的必要性。
|
||||
|
||||
## 用法
|
||||
|
||||
```ts
|
||||
import type { Context } from 'cordis'
|
||||
import { BasicCompactService } from '@deepseek-ai/dsh-compact-basic'
|
||||
import TokenMeterService from '@deepseek-ai/dsh-token-meter'
|
||||
|
||||
export const name = 'compact-basic'
|
||||
export const inject = ['llm', 'tokenMeter']
|
||||
|
||||
export function apply(ctx: Context): void {
|
||||
ctx.plugin(TokenMeterService)
|
||||
ctx.plugin(BasicCompactService)
|
||||
}
|
||||
```
|
||||
|
||||
加载插件会注册 `ctx.compact`。在该插件之前添加同级 [`dsh-compact-tool-result-prune`](../compact-tool-result-prune/README.md) 以启用可选的不依赖模型 pass。当 `auto: true`(默认)时,它会在 token 压力下自动压缩;消费方(未来的 `/compact` 工具)也可直接调用 `ctx.compact.compactIfNeeded(...)` 或 `ctx.compact.compactRegion(...)`。
|
||||
|
||||
例如,同一个 compact 插件可以安全服务于容量不同的模型,并应用一项目标特定策略:
|
||||
|
||||
```yaml
|
||||
- name: '@deepseek-ai/dsh-compact-basic'
|
||||
config:
|
||||
thresholdRatio: 0.8
|
||||
retainRatio: 0.16
|
||||
modelPolicies:
|
||||
- provider: local
|
||||
model: small-context
|
||||
thresholdRatio: 0.7
|
||||
retainTokens: 2048
|
||||
```
|
||||
|
||||
## 模型体验
|
||||
|
||||
### 会话历史
|
||||
|
||||
#### 模型看到的内容
|
||||
|
||||
成功步骤越过阈值后,如果已加载可选 pruner,超大工具结果会先被改写。如果仍需摘要,下一个请求会收到下方检查点前导、一个空行、`<compacted-summary>`、取决于数据的摘要以及 `</compacted-summary>`。溢出恢复会根据使表层前进的任何替换重建立即重试。检查点会替换已选较早范围,后面跟随已保留的近期单元。
|
||||
|
||||
##### 会话检查点前导
|
||||
|
||||
```markdown
|
||||
This is an automatically generated checkpoint condensing an earlier span of the conversation to free up context. Treat the captured context as established background and build on it without restating it. Continue the task directly from the messages that follow, without acknowledging this checkpoint.
|
||||
```
|
||||
|
||||
#### Token 影响
|
||||
|
||||
不依赖模型的剪枝可以完全避免辅助调用;否则它会在摘要替换较早范围之前缩减该调用的 transcript。替换会缩减未来输入历史,而非追加第二份副本。摘要会保留到后续压缩将其替换,但不可分的非工具单元仍可能超出预算。
|
||||
|
||||
#### KV Cache 影响
|
||||
|
||||
它是替换,而非仅追加。每个检查点都会使从第一个已替换历史 token 起的复用失效;该范围之前未更改的请求前缀仍可复用。
|
||||
|
||||
### 辅助摘要器请求
|
||||
|
||||
#### 模型看到的内容
|
||||
|
||||
摘要模型会接收逐字回放的会话:与上次已路由请求为已遮蔽区域发送的相同系统提示词、工具 schema 与消息,后面跟随一条最终 user 消息,即下方压缩指令。会话模型绝不会看到该私有请求或其推理;只有返回文本会被存储。
|
||||
|
||||
##### 压缩指令(最终 user 消息)
|
||||
|
||||
```markdown
|
||||
You are now acting as a compaction engine for this AI coding assistant. Condense the conversation ABOVE into a structured checkpoint that lets another model resume the work with no loss of essential context.
|
||||
|
||||
Output EXACTLY the Markdown structure below: keep every section, in order. Use terse bullets, not prose paragraphs. Write "(none)" for an empty section — never drop a section.
|
||||
|
||||
## Primary Request and Intent
|
||||
- [the user's original and evolving goals; quote verbatim where the exact wording matters]
|
||||
|
||||
## Key Technical Concepts
|
||||
- [technologies, frameworks, patterns, and conventions in play]
|
||||
|
||||
## Files and Code
|
||||
- [exact path: why it matters, key changes or snippets]
|
||||
|
||||
## Errors and Fixes
|
||||
- [error: how it was resolved, plus any related user feedback]
|
||||
|
||||
## Pending Tasks
|
||||
- [explicitly requested work not yet completed]
|
||||
|
||||
## Current Work
|
||||
- [precisely what was in progress at this checkpoint]
|
||||
|
||||
## Next Step
|
||||
- [the single next action, directly in line with the most recent request, or "(none)"]
|
||||
|
||||
## Critical Context
|
||||
- [decisions and their rationale, constraints, user preferences, open questions, data needed to continue]
|
||||
|
||||
Rules:
|
||||
- Preserve exact file paths, commands, error strings, identifiers, and function signatures.
|
||||
- Capture user feedback and explicit instructions faithfully, especially corrections.
|
||||
- Do NOT mention this summarization request or that the context was compacted.
|
||||
- Output only the checkpoint text: do not call any tool or take any other action.
|
||||
- If the conversation already contains a <compacted-summary> block, it is a PRIOR checkpoint. Do not copy it forward verbatim: preserve still-true facts, drop stale ones, and merge newer information into a single consolidated summary under the same structure.
|
||||
```
|
||||
|
||||
#### Token 影响
|
||||
|
||||
这是一次独立模型调用:输入是已回放会话前缀加固定指令,输出受 `maxTokens` 限制。收敛重试可能多次支付这项成本。
|
||||
|
||||
#### KV Cache 影响
|
||||
|
||||
已回放系统提示词、工具与已遮蔽区域消息与会话最后一个已路由请求逐字匹配,因此提供方的热前缀 cache 可复用至尾随指令之前;只有该指令与摘要输出未缓存。将摘要器路由到不同提供方/模型,或压缩非头部范围,都会放弃该复用。
|
||||
|
||||
## 已知限制与暂缓事项
|
||||
|
||||
- **Meter 准确度遵循固定启发式规则**:可复用提供方用量缺失时,会回退到字符数加结构开销,而非精确 tokenization。
|
||||
- **溢出分类由适配器维护**:提供方措辞可能改变;两个 DeepSeek 适配器将当前可识别的上下文限制失败规范化为 `CONTEXT_WINDOW_EXCEEDED`。
|
||||
- **部分不可分单元与仅 envelope 溢出仍不在表层压缩范围内**:恢复无法缩减系统/工具/前缀、拆分不可分的非工具节点,或修复不可剪枝剩余部分仍超出窗口的工具单元。可选 pruner 可以缩减原本不可分工具对内的文本型工具结果主体。
|
||||
- **`compactRegion` 要求开启轮次**:在完全关闭的会话上手动调用会抛出异常(「no open turn」),而不是执行压缩。
|
||||
- **摘要失败会保留最新持久表层**:任何替换前,自动路径会记录警告,并携带完整超预算历史继续。如果剪枝已落地,后续摘要失败会从该持久剪枝表层继续。在 `maxTokens` 处的摘要截断(可能由隐藏 reasoning token 耗尽)遵循同一规则。
|
||||
- **摘要调用没有 transcript 快照覆盖**:`dsh-llm-replay` 从 `assistant/chunk` 事件派生调用,因此这次不含 chunk 的直接 `ctx.llm.stream()` 调用无法回放([seam Agent Note](../../../.agents/notes/implemented/feature/2026-06-18-compaction-capability-seam.md) 中明确的暂缓回放基础设施)。
|
||||
@@ -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: edeba52b189b3cee5530faf7efc04043a326917f
|
||||
README.zh.md: fa471c0817cc937162b386cd3d249ce5ecd8c3ff
|
||||
@@ -1,5 +1,7 @@
|
||||
# @deepseek-ai/dsh-compact-tool-result-prune
|
||||
|
||||
English | [中文](README.zh.md)
|
||||
|
||||
The replay-safe model-free pruning service (`ctx.toolResultPrune`). It rewrites over-budget `tool/result` surface nodes to a bounded head, a fixed omission marker, and a bounded tail while retaining the full original event in the append-only session log.
|
||||
|
||||
This is a concrete companion to [`dsh-compact-basic`](../compact-basic/README.md), not a compaction backend or model-facing tool. Compact-basic reads it through optional `ctx.get('toolResultPrune')`, so either package remains independently composable.
|
||||
|
||||
62
packages/compact/compact-tool-result-prune/README.zh.md
Normal file
62
packages/compact/compact-tool-result-prune/README.zh.md
Normal file
@@ -0,0 +1,62 @@
|
||||
# @deepseek-ai/dsh-compact-tool-result-prune
|
||||
|
||||
[English](README.md) | 中文
|
||||
|
||||
可安全回放、不依赖模型的剪枝服务(`ctx.toolResultPrune`)。它会将超出预算的 `tool/result` 表层节点改写为有界头部、固定省略标记和有界尾部,同时在仅追加会话日志中保留完整原始事件。
|
||||
|
||||
这是 [`dsh-compact-basic`](../compact-basic/README.md) 的具体配套服务,不是压缩后端或面向模型的工具。Compact-basic 通过可选的 `ctx.get('toolResultPrune')` 读取它,因此两个包都保持可独立组合。
|
||||
|
||||
## 服务 API
|
||||
|
||||
`pruneSession(session)` 会扫描当前表层的一个稳定快照。每个超出预算的工具结果都会被一个新追加的 `tool/result` 替换,其携带 `{ surfaceOp: { op: 'replace', start: originalSeq, end: originalSeq }, sourceEventSeqs: [originalSeq] }`。替换会展开完整原始数据,只更改 `content`,保留 `turn`、`step`、`callId`、错误字段、`meta` 以及后续添加的数据。原始事件仍可用于持久化、回放和精确日志检查。
|
||||
|
||||
当会话拒绝替换时,该方法会同步抛出异常。本次 pass 中较早提交的替换仍然持久。
|
||||
|
||||
`measureContent(blocks)` 会统计 `text` 块中的 Unicode 码点。`pruneContent(blocks)` 会返回有界替换;如果内容已在阈值内,则返回 `null`。非文本块保持原始相对位置;文本切片绝不会拆分 UTF-16 surrogate pair,但可能拆分由多个码点组成的 grapheme cluster。
|
||||
|
||||
每个发出的结果在文本码点上都精确包含已配置的头部预算、固定标记和尾部预算,不大于 `thresholdChars`,且严格小于触发输入。因此第二次 pass 不会发出替换。
|
||||
|
||||
## 配置
|
||||
|
||||
无法识别的 key 会使插件在构造时失败。已解析配置与输入脱离,并且深度不可变。
|
||||
|
||||
| Key | 必填 | 含义 |
|
||||
|---|---|---|
|
||||
| `thresholdChars` | 否(默认 `8192`) | 合并文本超过此 Unicode 码点数时剪枝。 |
|
||||
| `headChars` | 否(默认 `4096`) | 保留的开头 Unicode 码点数。 |
|
||||
| `tailChars` | 否(默认 `1024`) | 保留的末尾 Unicode 码点数。 |
|
||||
|
||||
所有值都必须是整数;阈值必须为正数,头部/尾部必须为非负数。`headChars + marker + tailChars` 必须能容纳在 `thresholdChars` 内,因此有效配置可以剪枝每个超出预算的结果,不会增长或重复改写。
|
||||
|
||||
## 用法
|
||||
|
||||
```ts
|
||||
import type { Context } from 'cordis'
|
||||
import ToolResultPruneService from '@deepseek-ai/dsh-compact-tool-result-prune'
|
||||
|
||||
export function apply(ctx: Context): void {
|
||||
ctx.plugin(ToolResultPruneService)
|
||||
}
|
||||
```
|
||||
|
||||
## 模型体验
|
||||
|
||||
### 已剪枝的工具结果
|
||||
|
||||
#### 模型看到的内容
|
||||
|
||||
一旦压缩触发器成立,后续请求会看到保留的头部、`\n\n[... tool result middle pruned ...]\n\n` 和保留的尾部,用它们替换已移除文本。富内容块保持顺序。模型不会看到原文的第二份副本。
|
||||
|
||||
#### Token 影响
|
||||
|
||||
每个已改写工具结果最多包含 `thresholdChars` 个文本码点。剪枝本身不会发起模型调用;重新测量的请求低于压力阈值时,compact-basic 会跳过摘要,否则摘要器会读取已剪枝的表层。
|
||||
|
||||
#### KV Cache 影响
|
||||
|
||||
替换较早的结果会使从第一个改变的 token 起的复用失效。当其路由、envelope 与之前的历史保持一致时,已剪枝前缀可以复用。
|
||||
|
||||
## 已知限制与暂缓事项
|
||||
|
||||
- **字符预算不是 token 预算**:不同提供方的 token 密度各异,因此 `ctx.tokenMeter` 仍负责判定剪枝是否缓解了请求压力。
|
||||
- **剪枝只基于语法**:它保留开头与结尾,不解释中间哪些行在语义上重要。
|
||||
- **Grapheme cluster 可能被拆分**:按码点切片可保护 surrogate pair,但不会执行感知 locale 的 grapheme 分割。
|
||||
6
packages/compact/compact/README.i18n.yaml
Normal file
6
packages/compact/compact/README.i18n.yaml
Normal 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: 17a5420ae9fa23ce4021b4d4927ae5b95962f979
|
||||
README.zh.md: d98251649cfdcf6b12e89a192a43b08b0f071f38
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user