chore: remove remaining SDK toolchain residue

This commit is contained in:
Tianyi Cui
2026-08-11 16:37:29 +08:00
parent 454e06c8c1
commit 175d252f77
16 changed files with 19 additions and 20 deletions
@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-07-24-single-harness-home-resolver.md
2026-07-24-single-harness-home-resolver.md: dd1bc3ac59091d0b4405b164ddcb3ba00929fd9e
2026-07-24-single-harness-home-resolver.zh.md: a203d33186ec102f9a9380964ad9daf8ab6cc215
2026-07-24-single-harness-home-resolver.md: 27db7e23b1ae3d2c9a05259bfb3047591589627d
2026-07-24-single-harness-home-resolver.zh.md: 5eec850c9c7ecc70b2327eacca422662ec39a9cc
@@ -25,6 +25,8 @@ An empty or whitespace-only `$DSH_HOME` is treated as unset; otherwise `resolve(
`@deepseek-ai/dsh-home` is deleted. Its three importers (`dsh-tool-bash`, `dsh-skill-local`, `dsh-agent-spine-demo`) import `resolveDshHome` from `dsh-paths`.
`dsh-telemetry` and its separate home policy are absent under the [SDK project toolchain removal](../simplification/2026-08-11-remove-sdk-project-toolchain.md), leaving this resolver as the sole home policy.
## Alternatives considered
**Leave the two `resolveDshHome` copies in place.** They had already drifted (one expands tildes, one didn't) and encode the same cross-cutting fact twice. Consolidation is the point of the `util/` layer; a duplicate resolver is a latent divergence bug.
@@ -25,6 +25,8 @@ explicit configured path > $DSH_HOME > ~/.dsh
`@deepseek-ai/dsh-home` 被删除。它的三个引用方(`dsh-tool-bash``dsh-skill-local``dsh-agent-spine-demo`)从 `dsh-paths` 导入 `resolveDshHome`
`dsh-telemetry` 及其独立 home 策略已随 [SDK 项目工具链移除](../simplification/2026-08-11-remove-sdk-project-toolchain.md)一并消失,因此该解析器是唯一的 home 策略。
## 备选方案
**保留两份 `resolveDshHome` 副本。** 它们早已漂移(一个展开波浪号,一个不展开),并把同一条横切事实编码了两遍。`util/` 层的意义正是在于合并,重复的解析器是一个潜在的分歧 bug。
@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/feature/2026-07-21-continuable-background-subagents.md
2026-07-21-continuable-background-subagents.md: c1f60a4718a903e7dd55f5ccba3811aa3a0e9e81
2026-07-21-continuable-background-subagents.zh.md: cc13c5eac98ebf687c180bdffb54a7540706e853
2026-07-21-continuable-background-subagents.md: 06095e644f8c7e33ce262e2cb62c7f8622b4f405
2026-07-21-continuable-background-subagents.zh.md: bcdfb67553ef7452e25fe56246f854092f720092
@@ -111,8 +111,7 @@ Task records and active-run associations are process-local. Persistence makes th
- `packages/subagent/subagent-inprocess/tests/subagent-inprocess.spec.ts` pins the continuable durability boundary: an absent or detached flush listener and a permanent listener failure reject with `DURABILITY_FAILED`, a transient loop-checkpoint failure can succeed on the final confirmation, cancellation owns either final-checkpoint outcome, resume also confirms durability, and foreground runs remain best-effort. `packages/subagent/subagent/tests/continuation.spec.ts` drives the real stack (agent loop, JSONL persistence, spawn/fork providers, Task service, and `ctx.subagents`) keylessly: initial and resumed activations create fresh Tasks and dispose their runs before terminal; the descriptor event is pre-turn, model-hidden, versioned, durable under the service-allocated child id, and survives blocked or throwing initial prompt admission; cancellation, steering, cold follow-up, authorization, ownership conflicts, and resume races retain the contracts described above.
- `packages/subagent/tool-subagent-control/tests/tool-subagent-control.spec.ts` pins the `send_message` schema, coordinator attribution, both route renderings, the not-delivered failure, the no-agent rejection, and HMR disposal.
- `packages/subagent/tool-subagent/tests/tool-subagent.spec.ts` covers the configured background route: continuable mode requires a resumable provider and returns both ids without requiring `send_message`, while one-shot mode keeps the plain Task acknowledgement even when the provider can resume.
- `packages/subagent/tool-subagent/tests/tool-subagent.spec.ts` pins Task service integration and the model-facing Task controls.
- `packages/subagent/tool-subagent/tests/tool-subagent.spec.ts` covers the configured background route: continuable mode requires a resumable provider and returns both ids without requiring `send_message`, while one-shot mode keeps the plain Task acknowledgement even when the provider can resume; it also pins Task service integration and the model-facing Task controls.
- The keyless ACP snapshot scenario `subagent-continuable` (examples/acp-agent) pins the model-visible transcript: the two-id acknowledgement, a final durability-confirmation failure rendered through `task_output` without unconfirmed child output, and a `send_message` follow-up whose started Task fails with the id unavailable.
## Consequences
@@ -111,8 +111,7 @@ Task 记录和活跃 run 关联都位于进程内。持久化使 child 会话可
- `packages/subagent/subagent-inprocess/tests/subagent-inprocess.spec.ts` 固定可继续执行的持久性边界:缺少 flush 监听器、flush 监听器已脱离或监听器持续失败时,均会以 `DURABILITY_FAILED` 拒绝;循环检查点的瞬时失败可在最终确认成功后继续完成,发生取消时最终检查点无论成功还是失败都由取消优先决定结果,resume 同样会确认持久性,而前台运行仍采用尽力而为策略。`packages/subagent/subagent/tests/continuation.spec.ts` 以无密钥方式驱动真实栈(agent loop、JSONL 持久化、spawnfork 提供方、Task 服务和 `ctx.subagents`):初始及恢复后的激活都会创建新 Task,并在进入终态前 dispose 各自的 run;描述符事件位于轮次前、对模型隐藏、带版本、在服务分配的 child id 下持久化,并在初始 prompt admission 阻止请求或抛出异常时仍保留;取消、steering、cold follow-up、授权、所有权冲突与 resume 竞态保留上述约定。
- `packages/subagent/tool-subagent-control/tests/tool-subagent-control.spec.ts` 固定 `send_message` 的 schema、coordinator 来源标记、两种路由渲染、未送达失败、无 agent 时的拒绝,以及 HMR(热模块替换)dispose。
- `packages/subagent/tool-subagent/tests/tool-subagent.spec.ts` 覆盖配置的后台路由:可继续模式要求提供方可恢复,并在不要求 `send_message` 的情况下返回两个 id;即使提供方可以恢复,一次性模式仍保持普通的 Task 确认消息。
- `packages/subagent/tool-subagent/tests/tool-subagent.spec.ts` 固定 Task 服务集成及面向模型的 Task 控制工具。
- `packages/subagent/tool-subagent/tests/tool-subagent.spec.ts` 覆盖配置的后台路由:可继续模式要求提供方可恢复,并在不要求 `send_message` 的情况下返回两个 id;即使提供方可以恢复,一次性模式仍保持普通的 Task 确认消息;它还固定 Task 服务集成及面向模型的 Task 控制工具
- 无密钥 ACP 快照场景 `subagent-continuable`examples/acp-agent)固定模型可见的 transcript:双 id 确认消息、最终持久性确认失败(该失败通过 `task_output` 呈现,且不包含未经确认的 child 输出),以及一次 `send_message` 后续操作——其已启动的 Task 会带着「id 不可用」失败。
## 影响
@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/process/2026-08-10-vendor-package-rescope.md
2026-08-10-vendor-package-rescope.md: f2a142cec4e3c28fae54af8063cd730931fa738b
2026-08-10-vendor-package-rescope.zh.md: 994064fc869e1ccd95609ec67010eae794ed1c48
2026-08-10-vendor-package-rescope.md: 3ad442a681229b7b9df8feb1c487a925b6123f23
2026-08-10-vendor-package-rescope.zh.md: d45fd3c389204e832917f0749c7d5bc360dea3a1
@@ -26,7 +26,7 @@ All nine packages move into the `@deepseek-ai` scope. Directory names, upstream
The rewrite touches only **delimited, complete package-name tokens**: quoted or backticked specifiers (optionally with a `/subpath`), `package.json` names and dependency keys, `cordis.yml` `name:` values, and `tsconfig.base.json` `paths` keys. Identically spelled strings that are not package names therefore stayed as they were: the `cordis.yml` config-file family, the Loader's literal `cordis:` builtin prefix (`cordis:include`, `cordis:group` — see `vendor/loader/src/config/tree.ts`), kind strings like `cordis-config-entry`, `@deepseek-ai/dsh-tool-cordis`, Schemastery's upstream `Symbol.for('schemastery')` and `vendor:` metadata field, the `packages/<group>/` directory names in `GROUP_ORDER` (`scripts/gen-module-graph.ts`, `scripts/gen-doc-graphs.ts`), and the upstream install instructions in `vendor/*/README.md`.
Two classes are invisible to a token rule and were renamed site by site. First, property access and unquoted object keys `manifest.peerDependencies?.cordis`, and the manifest keys the scaffold generates in `npm-dependency-policy.ts` and `local-plugin-blueprint.ts` — where TypeScript cannot catch a stale `Record<string, string>` key. Second, constants that carry the name as data: the vendored set in `check-workspace-constraints.ts`, the group/include names in `verify-cordis-config.ts`, the `declare module` target strings in `cordis-walk.ts`, `gen-scoped-events.ts`, and typert's `analyzer.ts`, and `alwaysBundle` in `app-boot/tsdown.config.ts`.
Two classes are invisible to a token rule and were renamed site by site. First, property access — `manifest.peerDependencies?.cordis` — where TypeScript cannot catch a stale `Record<string, string>` key. Second, constants that carry the name as data: the vendored set in `check-workspace-constraints.ts`, the group/include names in `verify-cordis-config.ts`, the `declare module` target strings in `cordis-walk.ts`, `gen-scoped-events.ts`, and typert's `analyzer.ts`, and `alwaysBundle` in `app-boot/tsdown.config.ts`.
Markdown splits along what a reader does with it. Every fence follows the rename regardless of its info string, because a fence is code they copy or configuration they mount — the `yaml` fences naming Loader plugins and the `ts ignore-check` fences beside compiled ones included. Prose follows it under `docs/`, where a tutorial sentence quoting a name teaches something this repository no longer resolves. Prose elsewhere — `vendor/*/README.md`, package READMEs, and `.agents/notes/` — keeps the names it was written with, both because it records what was true then and because the same spelling can mean something else: the Python SDK's `cordis` option, the unvendored `@cordisjs/plugin-http`, or an agent-preset id.
@@ -26,7 +26,7 @@ Status: implemented
改写只落在**带定界符的完整包名 token** 上:引号或反引号包裹的 specifier(可带 `/子路径`)、`package.json``name` 与依赖键、`cordis.yml``name:` 值、`tsconfig.base.json``paths` 键。因此以下同形串一律未改,它们不是包名:`cordis.yml` 及其家族文件名、Loader 的 `cordis:` 内建前缀(`cordis:include``cordis:group`,见 `vendor/loader/src/config/tree.ts`)、`cordis-config-entry` 这类 kind 串、`@deepseek-ai/dsh-tool-cordis`、Schemastery 上游的 `Symbol.for('schemastery')``vendor:` 元数据、`scripts/gen-module-graph.ts``gen-doc-graphs.ts``GROUP_ORDER``packages/<group>/` 目录名,以及 `vendor/*/README.md` 里的上游安装指引。
Token 规则看不见两类点位,它们按名字逐处改:一是属性访问与未加引号的对象键(`manifest.peerDependencies?.cordis`、脚手架 `npm-dependency-policy.ts``local-plugin-blueprint.ts` 生成的清单键)——TypeScript 抓不到过期的 `Record<string, string>` 键;二是把名字当数据的常量(`check-workspace-constraints.ts` 的 vendored 集合、`verify-cordis-config.ts` 的 group/include 名、`cordis-walk.ts``gen-scoped-events.ts` 与 typert `analyzer.ts` 里识别 `declare module` 目标的字符串、`app-boot/tsdown.config.ts``alwaysBundle`)。
Token 规则看不见两类点位,它们按名字逐处改:一是属性访问 `manifest.peerDependencies?.cordis`——TypeScript 抓不到过期的 `Record<string, string>` 键;二是把名字当数据的常量(`check-workspace-constraints.ts` 的 vendored 集合、`verify-cordis-config.ts` 的 group/include 名、`cordis-walk.ts``gen-scoped-events.ts` 与 typert `analyzer.ts` 里识别 `declare module` 目标的字符串、`app-boot/tsdown.config.ts``alwaysBundle`)。
Markdown 按「读者拿它做什么」一分为二。围栏一律跟着改,不看 info string——围栏里是读者要照抄的代码或要挂载的配置,包括写着 Loader 插件名的 `yaml` 围栏和紧邻编译围栏的 `ts ignore-check` 围栏。散文只在 `docs/` 下跟着改:教程里引用某个名字的句子,教的是本仓已不解析的东西。`docs/` 之外的散文——`vendor/*/README.md`、各包 README、`.agents/notes/`——保留写作当时的名字:既因为它记录的是当时的事实,也因为同一个拼写可能指别的东西,比如 Python SDK 的 `cordis` 选项、我们没 vendor 的 `@cordisjs/plugin-http`,或某个 agent-preset 的 id。
@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/simplification/2026-07-23-acp-automation-only-protocol.md
2026-07-23-acp-automation-only-protocol.md: 56c433acf59d3a0c4b5c8b6605e422d3c4efede2
2026-07-23-acp-automation-only-protocol.zh.md: bf326ce9f6fea8c55b842bc61e3d8521032ea4d1
2026-07-23-acp-automation-only-protocol.md: 56dcaf8b4327a008f26b884264958cac02d6541a
2026-07-23-acp-automation-only-protocol.zh.md: a34e179a1d38c1867ea8165b149a9ec7716c1c0e
@@ -20,7 +20,7 @@ The bridge emits only committed `assistant/message` text. Reasoning, raw chunks,
One-shot `session/request_permission` remains. It is a machine policy channel for bridge-owned agents, not a human approval UI: the answerer accepts only an exact agent object in the bridge's live session map, delegates foreign or call-less requests, and maps failed RPCs to the fail-closed unavailable outcome. The client chooses allow once, reject once, or cancel, and the bridge never turns that response into a durable grant. Asking policy stays in the approval seam and its producers; [`dsh-subagent-acp`](../../../../packages/subagent/subagent-acp/README.md) uses this channel programmatically.
The app composition contains the agent spine, persistence, checkpoint policy, and ACP transport. It does not mount command, session-query, session-reference, plan-mode, permission-picker, or user-interaction services for ACP. SDK scaffolding likewise treats `ask_user_question` as TUI-only.
The app composition contains the agent spine, persistence, checkpoint policy, and ACP transport. It does not mount command, session-query, session-reference, plan-mode, permission-picker, or user-interaction services for ACP.
The transport programs interface-level agent, session, and approval services rather than the concrete agent loop. Tool execution stays inside the harness; ACP never delegates shell execution to an editor. stdout carries framed JSON-RPC only, so the app mounts no stdout logger and the bridge does not monkey-patch process output.
@@ -20,7 +20,7 @@ ACP 仍有一个有用的职责:另一个 agent(智能体)或自动化控
保留一次性 `session/request_permission`。它是为桥接层拥有的 agent 提供的机器策略通道,而不是面向人类的审批 UI:应答者只接受桥接层当前会话映射中登记的同一 agent 对象;外部请求或缺少调用标识的请求会继续委派;RPC 失败则映射为拒绝请求的 `unavailable` 结果。客户端可选择允许一次、拒绝一次或取消,桥接层绝不会将该响应转换为持久授权。询问策略仍归审批 seam 及其生产者所有;[`dsh-subagent-acp`](../../../../packages/subagent/subagent-acp/README.md) 会以程序化方式使用该通道。
应用组装包含 agent 主干、持久化、检查点策略和 ACP 传输层。它不会为 ACP 挂载命令、会话查询、会话引用、plan mode、权限选择器或用户交互服务。SDK 脚手架同样将 `ask_user_question` 视为 TUI 专属功能。
应用组装包含 agent 主干、持久化、检查点策略和 ACP 传输层。它不会为 ACP 挂载命令、会话查询、会话引用、plan mode、权限选择器或用户交互服务。
传输层调用 agent、会话和审批的接口服务,而不依赖具体的 agent loop。工具执行仍留在 harness 内;ACP 绝不会把 shell 执行委派给编辑器。stdout 只承载分帧 JSON-RPC,因此 app 不挂载 stdout logger,桥接层也不会 monkey-patch 进程输出。
-1
View File
@@ -27,7 +27,6 @@ const PATTERNS = [
'AGENTS.md',
'packages/AGENTS.md',
'.agents/skills/**/*.md',
'skills/**/*.md',
]
/** A broken relative link: a missing target path or a missing anchor on it. */
-1
View File
@@ -26,7 +26,6 @@ const PATTERNS = [
'AGENTS.md',
'packages/AGENTS.md',
'.agents/skills/**/*.md',
'skills/**/*.md',
]
interface Block {
+1 -1
View File
@@ -68,7 +68,7 @@ function isDriftedPackageReference(ref: string): boolean {
// A missing reference is drift only when a path segment names a live package.
// A leading segment that is itself an existing group directory is explained by
// the group, not by a relocated leaf sharing its name (`client` is both the
// client-modules group and the scaffold leaf), so only later segments count.
// client-modules group and the sdk leaf), so only later segments count.
const segments = ref.split('/').slice(1)
const [group] = segments
const scanned = group !== undefined && segments.length > 1 && existsSync(resolve(root, 'packages', group))
-1
View File
@@ -51,7 +51,6 @@ export default defineConfig({
...(process.env.DSH_EXAMPLE_MODE === 'lib' ? ['apps/web/tests/**/*.snapshot.ts'] : []),
'apps/cli/tests/**/*.snapshot.ts',
'examples/*/tests/**/*.snapshot.ts',
'packages/sdk/*/tests/**/*.snapshot.ts',
],
// Replay never writes committed outputs and every scenario owns its
// mutable runtime state (the subprocess suites use a unique temp dir and