mirror of
https://github.com/deepseek-ai/deepseek-harness
synced 2026-08-15 21:04:50 +00:00
chore: remove remaining SDK toolchain residue
This commit is contained in:
@@ -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 持久化、spawn/fork 提供方、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 进程输出。
|
||||
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -26,7 +26,6 @@ const PATTERNS = [
|
||||
'AGENTS.md',
|
||||
'packages/AGENTS.md',
|
||||
'.agents/skills/**/*.md',
|
||||
'skills/**/*.md',
|
||||
]
|
||||
|
||||
interface Block {
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user