# agpa-dsh-plugin [English](README.md) | 中文 把 AGPA(Agent Player Achievements,npm `@eiainano/agpa`,源码在 `~/WorkSpace/forClaude/AgentPlayerAchievements`)接到 **DeepSeek Harness (dsh)** 的 Cordis 插件。 **设计目标(最高性价比)**:DSH 侧**不复制任何成就逻辑**。所有 `achievement_*` 工具都是薄壳,把参数原样转发给已发布的 AGPA MCP 服务(`@eiainano/agpa` 的 `agpa-mcp` bin)。于是 AGPA 的引擎、成就定义、profile、`~/.agent-achievements` 数据在 Claude Code / DSH / 其他工具之间完全共享——`cross_agent` 成就自动生效。 ## 分层与文件 | 层 | 文件 | 说明 | |---|---|---| | 入口(Cordis 行) | `src/index.ts` + `cordis.patch.yml` | `name='agpa'`,`id` 必须一致 | | 工具桥 | `src/tools.ts` | 7 个 `achievement_*` 原生工具壳 | | MCP 客户端 | `src/agpa-bridge.ts` | 零运行时依赖的 MCP-over-stdio(仅 Node 内建),懒启动一个 AGPA 子进程 | | 自动采集 | `src/events.ts` | 订阅 dsh `session/event`,归一成 CC-style payload(`source:'dsh'`) | | 摄入子进程 | `src/hook-runner.ts` | 串行 spawn 短命 `agpa-hook auto`,把 payload 喂 stdin | | 模型工作流手册 | `skills/agpa/SKILL.md` | 教模型何时 track / poll / 展示解锁 | ## 目录结构 ``` forDSH/agpa-dsh-plugin/ ├─ cordis.patch.yml # insert 行 id=agpa name=agpa-dsh-plugin ├─ package.json # dsh.bundle.patch → cordis.patch.yml ├─ tsconfig.json # NodeNext → lib/ ├─ src/ │ ├─ index.ts # export name='agpa'; inject=['tools']; apply() │ ├─ tools.ts # 7 × ctx.tools.register(defineTool(...)) │ ├─ agpa-bridge.ts # 最小 MCP 客户端(spawn agpa-mcp) │ ├─ events.ts # session/event → CC-style 归一(AutoTrackFeed) │ └─ hook-runner.ts # 串行 spawn `agpa-hook auto` 摄入子进程 ├─ scripts/ │ ├─ install-skills.mjs # 复制 skills → $DSH_AGENTS_HOME/skills │ └─ smoke-bridge.mjs # 真机冒烟:调 AGPA 只读 stats └─ skills/agpa/SKILL.md # AGPA 工作流手册 ``` ## 命令 ```bash npm install --legacy-peer-deps # 仅用于类型检查的开发依赖 npm run typecheck # 对着真实 @deepseek-ai/dsh-tools 类型检查 npm run build # tsc → lib/ npm run smoke:bridge # 真机验证 bridge ↔ AGPA MCP(只读 stats) npm run install-skills # 复制 skills/agpa → ~/.agents/skills/agpa npm pack # 产出 agpa-dsh-plugin-<版本>.tgz ``` ## 装进 dsh 已发布到 npm:**`agpa-dsh-plugin`**。 ```bash # 1) 从 registry 加入 profile(bundle 层,重启生效) dsh plugin --profile web add agpa-dsh-plugin # 2) 安装模型工作流 skill:包内已带 skills/agpa,复制到 skills 根即可 # (git clone 开发时用:npm run install-skills) cp -r ~/.dsh/profiles/web/node_modules/agpa-dsh-plugin/skills/agpa ~/.agents/skills/ # 3) 重启后离线检查合成树里是否出现 agpa 行 dsh --profile web --dump-config | grep -A3 agpa ``` 本地开发(改源码时): ```bash npm run build && npm pack # prepack 会自动先 build dsh plugin --profile web add ./agpa-dsh-plugin-<版本>.tgz ``` 出现行但工具列表里没有 → 代码问题(看 dsh 日志);行都没出现 → 组合问题 (name 未解析 / `files` 漏了 `cordis.patch.yml`)。 ## 环境变量 | 变量 | 说明 | |---|---| | `AGPA_MCP_CMD` | 覆盖 AGPA MCP 启动命令(空格分隔)。默认 `npx -y -p @eiainano/agpa@0.1.10 agpa-mcp`。本地开发可用 `tsx /path/to/agpa/src/main.ts` | | `AGPA_AUTOTRACK=1` | 启用事件自动采集:每个归一事件 spawn 一个 `agpa-hook auto` 摄入进程 | | `AGPA_HOOK_CMD` | 覆盖摄入命令(空格分隔)。默认 `npx -y -p @eiainano/agpa@0.1.10 agpa-hook auto`(开箱即用);本地开发可指 `tsx /path/to/agpa/src/cli/hook.ts auto` | | `AGPA_DEBUG=1` | 打印 AGPA MCP stderr + 每个收到事件类型 `[agpa][ev]` 与归一 payload `[agpa][autotrack]` | | `DSH_AGENTS_HOME` | `install-skills` 的目标 skills 根(默认 `~/.agents`) | 桥接/摄入子进程固定注入 `AGPA_TOOL_SOURCE=dsh`,让事件正确打上工具来源 (落库为 `tool_source:"dsh"`,与 Claude Code 的 `claude-code` 并存于同一 store)。 ## 状态 / 路线 - [x] **Phase 1(本仓库)**:7 个工具壳 + MCP 桥(已验证可连真实 AGPA,返回 stats 且 `tool_source=dsh`)+ SKILL - 2026-09-09 已在**真实 dsh 0.1.2-rc.1 端到端验证**:`dsh plugin --profile web|headless add ` 装进两个 profile; headless 实跑任务成功调用 `achievement_stats`,经桥接返回共享 store 真实数据(75/212、level 6、10,592 XP)。 - [x] **Phase 2(本仓库,0.1.11 已发布 npm)**:事件自动采集,真机 e2e 通过、开箱即用。 - `events.ts` 订阅 dsh `session/event`,把 `tool/call`+`tool/result` → PostToolUse(Failure)、 `user/message`(`source.kind==='user'`)→ UserPromptSubmit 归一成 CC-style payload(`source:'dsh'`); 每个 payload spawn 一个 `agpa-hook auto` 摄入进程(`hook-runner.ts`)。 - headless 实跑(Write/Bash)后,`~/.agent-achievements/profiles/neo/event.log` 出现 `tool_source:"dsh"` 的 `file.create`/`file.write`/`command.run`/`tool.complete` 等行。 - **实测关键坑**:`tool/result.data` 顶层**没有** `callId`(tool/call 才有); 关联键 `${turn}:${step}:${callId}` 的 callId 藏在 `result.data.message.source.callId` (= `content[].toolCallId`)。事件名一律以锁定的 dsh 0.1.2-rc.1 实测为准 (`session/event` 还广播 `permission/preset`、`assistant/chunk` 等噪音类型,均已忽略)。 - AGPA **0.1.10 已发布**并带 `agpa-hook` bin,插件的默认摄入命令 `npx -y -p @eiainano/agpa@0.1.10 agpa-hook auto` 开箱即用(仅 `AGPA_AUTOTRACK=1` 即验证通过)。 本地开发仍可用 `AGPA_HOOK_CMD` 指 checkout 的 `tsx src/cli/hook.ts auto`。 - 摄入子进程 `detached` 启动:短命 headless 进程退出不会 SIGTERM 掉在途摄入 (首次 `npx` 冷缓存下载时可能较慢,detached 保证事件不丢;常驻 web 会话本就不受影响)。 - [ ] **Phase 3**:可选 `dsh.client` 的 XP/成就小组件,或直接复用 AGPA dashboard(:3867)。 ## 已知注意点 1. ~~本机 dsh 暂无法启动~~(2026-09-09 修,2026-09-15 二次修):workbuddy 的 binary manager 升级 node 时会**整个替换带版本的 prefix**(`versions/22.22.2-2` → `versions/22.22.2-3`), 清空其中全局包。所以 dsh/pnpm 已**不再装在版本 prefix 里**,改到稳定目录 `~/.local/share/dsh-runtime`;`~/.local/bin/dsh` 动态读 `~/.workbuddy/binaries/node/versions/current` 取 node 版本,并把 `$DSH_HOME/bin`(pnpm) 与该 node 的 bin 加进 PATH。安装 prefix 内全局包务必显式用 `"$NODE" "$PREFIX/lib/node_modules/npm/bin/npm-cli.js" i -g --prefix "$PREFIX"`, 否则 npm wrapper 的 shebang 会落到 PATH 上的 homebrew node。 2. **运行期解析**:外部插件裸 import `@deepseek-ai/dsh-tools`(value)与 `@deepseek-ai/cordis`(type-only)经 dsh host 映射到 in-box 树,均可在 0.1.2-rc.1 解析(本插件的 `defineTool` value import 已实跑验证)。 3. **DSH 是 developer preview**:`cordis.patch.yml`/`dsh` 字段/事件名都可能随版本变化。 `package.json` 的 peer 只声明 `@deepseek-ai/cordis`(类型与闭包注入由 dsh 提供)。 4. **事件名以 pinned 版本为准**:采集所订阅的类型已在锁定的 0.1.2-rc.1 上真机核过 (见 Phase 2);若 dsh 升级,先打开对应版本的 `SessionEventMap` 复核,别照搬 master 文档。 5. 工具 schema 用了 JSON-schema 风格字面量;如需数值范围校验,AGPA 侧目前未做 强校验,描述里已注明允许范围。 6. 若装不进 profile,先确认 `npm pack` 的 `files` 里确实有 `cordis.patch.yml`。