@xdxer/dingtalk-agent 0.1.2 → 0.1.4-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 dingtalk-agent contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,79 +1,135 @@
1
+ <div align="center">
2
+
1
3
  # dingtalk-agent
2
4
 
3
- Claude Code、Codex 或其他 Agent 在获得一个全局 Skill 后,像钉钉里的真实同事一样处理消息和协作事项。
5
+ **让 AI Agent 像钉钉里的可靠同事一样感知、判断、行动与留痕。**
6
+
7
+ [![npm](https://img.shields.io/npm/v/%40xdxer%2Fdingtalk-agent?logo=npm&color=cb3837)](https://www.npmjs.com/package/@xdxer/dingtalk-agent)
8
+ [![CI](https://github.com/D1-2004/dingtalk-agent/actions/workflows/ci.yml/badge.svg)](https://github.com/D1-2004/dingtalk-agent/actions/workflows/ci.yml)
9
+ [![Node.js](https://img.shields.io/node/v/%40xdxer%2Fdingtalk-agent)](https://nodejs.org/)
10
+ [![License](https://img.shields.io/badge/license-MIT-2ea44f)](LICENSE)
11
+
12
+ [快速开始](#两分钟开始) · [核心模型](#核心模型) · [架构](#架构) · [行为协议](#数字员工行为协议) · [评测](#评测与验证)
13
+
14
+ </div>
15
+
16
+ `dingtalk-agent` 是一个 **Skill-first 的钉钉数字员工行为框架**。它不内置模型,也不复制 DWS;它把“像同事一样工作”拆成三层:
17
+
18
+ - **Basic Behavior Skill**:判断何时响应、追问、确认或保持沉默;
19
+ - **CLI Runtime**:冻结身份、目标和事务边界,提供可审计的员工级原子动作;
20
+ - **DWS**:执行钉钉消息、文档、待办、日历等具体产品能力。
21
+
22
+ 它可以被 Claude Code、Codex 或其他 Agent Host 使用,也可以作为更完整数字员工系统的基础蓝本。
23
+
24
+ ![dingtalk-agent Skill-first 架构](docs/architecture/dingtalk-agent-blueprint.png)
25
+
26
+ ## 为什么需要它
4
27
 
5
- 它不内置模型,也不复制 DWS
28
+ “会调用钉钉 API”不等于“会像员工一样工作”。真实协作还要求 Agent
6
29
 
7
- - Basic Behavior Skill 判断何时响应、追问、沉默,以及如何使用记忆;
8
- - `dingtalk-agent` 包装需要目标冻结、幂等、回读和状态迁移的员工级动作;
9
- - DWS 负责钉钉消息、文档、待办、日历等具体产品能力。
30
+ - 群里未被提及时默认不抢话,被 `@` 或私聊时才获得响应资格;
31
+ - 信息完整就直接交付,只有真正阻塞时才问一个问题;
32
+ - 不从消息正文猜收件人、身份、文档 ID 或权限;
33
+ - 长任务能确认收到、等待依赖、从下一条事件继续,而不是假装一直在线;
34
+ - 区分“命令执行过”“平台写入成功”“回读可见”和“对方确认”;
35
+ - 将任务状态、长期记忆、运行时锁和幂等回执放在正确的存储层。
10
36
 
11
- ![Skill-first 架构](docs/architecture/dingtalk-agent-blueprint.png)
37
+ 本项目把这些约束从一段巨型 Prompt 中拆出来:**Skill 负责判断,CLI 负责硬边界,DWS 负责平台能力。**
12
38
 
13
- ## 两步开始
39
+ ## 两分钟开始
40
+
41
+ > 要求 Node.js 18.3+。不需要先全局安装命令;`npx` 是不会受 PATH 影响的 bootstrap 入口。
14
42
 
15
43
  ```bash
16
- npm i -g @xdxer/dingtalk-agent
17
- dingtalk-agent skill install
44
+ npx --yes --registry=https://registry.npmjs.org @xdxer/dingtalk-agent@beta setup
18
45
  ```
19
46
 
20
- 这会安装一个 canonical Skill:
47
+ `setup` 会按顺序完成四件事:
48
+
49
+ 1. 将 CLI 安装到用户目录 `~/.local/bin`,必要时幂等补充 shell PATH;
50
+ 2. 检查 Node.js、DWS 版本和 `dws auth status`;
51
+ 3. 安装并验证 Basic Behavior Skill;
52
+ 4. 报告 Claude Code、Codex、OpenCode 是否能够发现 Skill。
53
+
54
+ 当前终端尚未加载新 PATH 时,setup 会打印一条可直接执行的 `export PATH=...`。验证结果:
55
+
56
+ ```bash
57
+ dingtalk-agent doctor
58
+ ```
59
+
60
+ 安装后,Skill 只有一份 canonical copy:
21
61
 
22
62
  ```text
23
- ~/.agents/skills/dingtalk-basic-behavior/ # Codex 直接发现
24
- ~/.claude/skills/dingtalk-basic-behavior # 相对 symlink → canonical
63
+ ~/.agents/skills/dingtalk-basic-behavior/ # Codex、OpenCode 直接发现
64
+ ~/.claude/skills/dingtalk-basic-behavior # Claude Code → canonical 相对链接
25
65
  ```
26
66
 
27
- 它不会初始化当前目录,也不会修改项目的 `AGENTS.md`、`CLAUDE.md` `.gitignore`。新 Agent 会话会自动发现 Skill;检查状态:
67
+ 如果只想临时运行、不做用户级安装,任何命令都可以通过 npm exec 执行:
28
68
 
29
69
  ```bash
30
- dingtalk-agent skill status
70
+ npx --yes --registry=https://registry.npmjs.org @xdxer/dingtalk-agent@beta doctor
71
+ npx --yes --registry=https://registry.npmjs.org @xdxer/dingtalk-agent@beta skill install
31
72
  ```
32
73
 
33
- ## 每个 Agent Session
74
+ 也兼容开放的 `skills` CLI。仓库有访问权限时,可只安装 Skill 到三个客户端:
34
75
 
35
- 普通会话不要求 init:
76
+ ```bash
77
+ npx skills add D1-2004/dingtalk-agent \
78
+ --skill dingtalk-basic-behavior --global --yes \
79
+ --agent claude-code --agent codex --agent opencode
80
+ ```
81
+
82
+ 从本地 checkout 安装则使用:
36
83
 
37
84
  ```bash
38
- dingtalk-agent bootstrap --json
85
+ npx skills add ./skills/dingtalk-basic-behavior \
86
+ --global --yes --agent claude-code --agent codex --agent opencode
39
87
  ```
40
88
 
41
- 如果当前目录存在 `WORKSPACE.md`、`MEMORY.md`、`knowledge/INDEX.md`,bootstrap 会直接挂载;都不存在也不是错误,不会自动创建文件。
89
+ `npx skills` 只安装行为说明,不安装 `dingtalk-agent` CLI,也不检查 DWS;需要真实执行钉钉动作时仍应运行 `setup` 或 `doctor`。完整排障见 [安装与首次使用](docs/INSTALLATION.md)。
42
90
 
43
- 也可显式选择存储:
91
+ 普通 Agent 会话无需初始化项目。进入任意目录后可直接发现上下文:
44
92
 
45
93
  ```bash
46
- # 本地开发:直接挂载,不复制
47
- dingtalk-agent bootstrap --storage local-dir:/path/to/workspace --json
94
+ dingtalk-agent bootstrap --json
95
+ ```
48
96
 
49
- # 远端员工:DWS probe 后拉成隐藏只读快照
50
- dingtalk-agent bootstrap \
51
- --storage 'dingtalk-doc:<nodeId-or-url>' \
52
- --state-dir /path/to/session-state \
53
- --json
97
+ 只有可信事件宿主需要冻结目标并建立 Prepared Run:
98
+
99
+ ```bash
100
+ mkdir fde-coach && cd fde-coach
101
+ dingtalk-agent init
102
+ dingtalk-agent prepare --event-file event.json --json
54
103
  ```
55
104
 
56
- ## 三种模式
105
+ ## 核心模型
57
106
 
58
- | 模式 | 是否需要 init | 用途 |
59
- |---|---:|---|
60
- | Direct Session | 否 | 普通 Claude Code/Codex 会话;应用同事行为,按需使用 DWS |
61
- | Mounted Session | 否 | 读取已有本地或钉钉文档中的身份、记忆、知识 |
62
- | Prepared Run | 是,一次 | 可信事件宿主冻结目标、身份、Session/Run、Wait、预算和回执 |
107
+ ### 三种运行模式
63
108
 
64
- 只有第三种模式需要显式初始化:
109
+ | 模式 | 初始化 | 上下文 | 适用场景 |
110
+ |---|---:|---|---|
111
+ | **Direct Session** | 不需要 | 当前请求与宿主提供的信息 | 普通 Claude Code / Codex 会话 |
112
+ | **Mounted Session** | 不需要 | 本地 Markdown 或钉钉文档快照 | 带身份、记忆和知识的长期员工 |
113
+ | **Prepared Run** | Workspace 一次性初始化 | 可信事件冻结的目标、身份与策略 | 自动化事件处理和强可靠外发 |
114
+
115
+ 本地内容直接挂载,不复制:
65
116
 
66
117
  ```bash
67
- mkdir fde-coach && cd fde-coach
68
- dingtalk-agent init # contextId 可省略,由目录名稳定派生
69
- dingtalk-agent prepare --event-file event.json --json
118
+ dingtalk-agent bootstrap --storage local-dir:/path/to/workspace --json
70
119
  ```
71
120
 
72
- 重复 `init` 只检查现有 Workspace,不重绑 Context、不复制 Skill、不覆盖用户内容。
121
+ 远端内容由 DWS 探测并拉成隐藏的只读快照:
73
122
 
74
- ## 员工级原子行为
123
+ ```bash
124
+ dingtalk-agent bootstrap \
125
+ --storage 'dingtalk-doc:<node-id-or-url>' \
126
+ --state-dir /path/to/session-state \
127
+ --json
128
+ ```
75
129
 
76
- Prepared Run 目前只开放四个消息行为:
130
+ ### 四个消息原子行为
131
+
132
+ Prepared Run 只开放四个消息动作:
77
133
 
78
134
  ```bash
79
135
  dingtalk-agent act ack
@@ -82,31 +138,110 @@ dingtalk-agent act ask --text "一个真正阻塞的问题"
82
138
  dingtalk-agent act silence --reason unmentioned
83
139
  ```
84
140
 
85
- - `ack` 是“看到了且需要时间”,不等于接单或完成;
86
- - `reply` 只交付给原消息;CLI 没有 `--to`;
87
- - `ask` 一次只问一个阻塞问题,并由宿主建立等待;
88
- - `silence` 是有意识地不打扰,也有本地回执。
141
+ | 动作 | 员工语义 | 关键边界 |
142
+ |---|---|---|
143
+ | `ack` | 看到了,确实需要时间处理 | 不等于接单、承诺或完成 |
144
+ | `reply` | 已有可交付结果 | 只回复原消息,CLI 没有 `--to` |
145
+ | `ask` | 缺少阻塞信息 | 一次只问一个问题,随后释放沙箱等待事件 |
146
+ | `silence` | 有意识地不打扰 | 仍留下结构化 reason 和本地回执 |
147
+
148
+ 文档写入、待办创建等能力继续由 DWS 提供。只有当一个员工意图需要固定作用域、权限、幂等、回读、状态迁移或跨产品组合时,才值得包装成新的 CLI 动作。
149
+
150
+ ## 架构
151
+
152
+ ```mermaid
153
+ flowchart TB
154
+ SIGNAL["钉钉消息 / @ / DM / 心跳"] --> HOST["Claude Code / Codex / Agent Host"]
155
+ BASIC["Basic Behavior Skill\n响应资格与员工协议"] --> HOST
156
+ ROLE["岗位 / Workflow Skill\nFDE、周报、事故处理"] --> HOST
157
+ HOST --> BOOT["bootstrap\n按需水合身份、记忆与知识"]
158
+ BOOT --> LOCAL["Local Markdown"]
159
+ BOOT --> DOC["DingTalk Doc Snapshot"]
160
+ HOST --> MODE{"可信事件?"}
161
+ MODE -- "否" --> DIRECT["Direct / Mounted Session"]
162
+ MODE -- "是" --> RUNTIME["Prepared Run Runtime\nSession / Run / Wait / Gate"]
163
+ RUNTIME --> ACTION["ack / reply / ask / silence"]
164
+ DIRECT --> DWS["DWS"]
165
+ ACTION --> DWS
166
+ DWS --> PRODUCTS["消息 / 文档 / 待办 / 日历"]
167
+ ```
168
+
169
+ ### 事件驱动的异步进程
170
+
171
+ 每条新信号可以启动一个新沙箱,但同一件事仍回到同一个 Session:
172
+
173
+ ```text
174
+ Field / Workspace = 长期身份、知识与 Skill(Heap)
175
+ Session = 一件工作的显式上下文(Stack)
176
+ Run = 一次事件唤醒的新沙箱
177
+ Wait = await continuation,由宿主持久化和恢复
178
+ Action = 受约束的系统调用
179
+ Receipt = 可审计的外部效果证据
180
+ ```
181
+
182
+ `ask` 后当前 Run 结束;匹配事件到达时,宿主恢复原 Session 并创建新 Run。系统持久化显式 checkpoint,而不是序列化 JavaScript 或模型的隐藏调用栈。
183
+
184
+ ### 存储边界
185
+
186
+ | Markdown / 钉钉文档 | 宿主状态存储 |
187
+ |---|---|
188
+ | 身份、长期知识、社交记忆、任务 checkpoint、Skill 候选 | EventIndex、Wait、锁、generation、幂等键、Action intent/receipt |
189
+
190
+ Why:文档适合人和 Agent 共同审查,但没有可靠 CAS;请求超时也不能证明写失败,因此不能承担并发控制或副作用去重。
191
+
192
+ ## 数字员工行为协议
193
+
194
+ 新任务遵循:
89
195
 
90
- 文档写、待办创建等裸 API 不在这里重复包装。只有当一个员工意图需要固定作用域、权限、幂等、回读、状态迁移或跨产品组合时,才值得成为新的 `dingtalk-agent` 动作。
196
+ ```text
197
+ UNDERSTAND → CLARIFY → PLAN → EXECUTE → WAIT → VERIFY → COMPLETE
198
+ ```
199
+
200
+ - **UNDERSTAND**:从当前消息和可信 continuation 还原目标、交付物、范围、完成条件、权限与时点;
201
+ - **CLARIFY**:先查线程、附件、Workspace 和岗位 Skill;信息足够就做,真阻塞才问;
202
+ - **PLAN**:单步任务不表演计划,多步任务建立 2~5 个可观察检查点;
203
+ - **EXECUTE**:外部副作用前重新核对对象、权限、幂等和最新状态;
204
+ - **WAIT**:记录等待谁、什么输入、从哪里继续,然后释放沙箱;
205
+ - **VERIFY**:通过工具结果和必要回读区分生成、保存、送达与确认;
206
+ - **COMPLETE**:回到原线程交付结果、证据、遗留项和下一责任人。
91
207
 
92
- ## 新任务承接
208
+ 只有跨消息、等待依赖、已经产生副作用、需要换沙箱接手或用户明确要求跟踪的事项才创建 checkpoint。单轮问答不制造“伪任务”。
93
209
 
94
- Basic Behavior 使用一条极简协议:`UNDERSTAND CLARIFY → PLAN → EXECUTE → WAIT → VERIFY → COMPLETE`。“澄清”先在内部检查目标、交付物、完成条件和权限;信息完整就直接做,只有阻塞才向人问一个问题。
210
+ ## Skill、CLI DWS 如何组合
95
211
 
96
- 跨消息、等待依赖或已经产生副作用的事项才写 task checkpoint;单轮问答不建状态。Prepared Run 使用 `$DTA_SESSION/memory/task.md`,本地 Mounted Session 只写显式配置的 state root,远端钉钉文档必须通过授权 Provider 写入并回读。控制面的 Wait、锁、幂等和 Receipt 不进入 Markdown。详见 [任务承接与 Checkpoint](skills/dingtalk-basic-behavior/references/task-lifecycle.md)。
212
+ ```text
213
+ Basic Behavior Skill 每个钉钉员工共享的社交与安全底座
214
+ +
215
+ Role / Workflow Skill 某个岗位如何完成 FDE 评价、周报、事故处理
216
+ +
217
+ Agent Definition 身份、服务对象、知识源、记忆与权限
218
+ +
219
+ dingtalk-agent CLI 需要强约束的员工级事务边界
220
+ +
221
+ DWS 钉钉标准产品能力
222
+ ```
97
223
 
98
- ## 可选事件宿主
224
+ 这意味着一个 FDE 教练只需在基础行为之上叠加教练身份、评价方法与学员资料;基础层无需知道任何 FDE 业务细节。
99
225
 
100
- `listen` 只是开发联调适配器,不是 Agent 的主入口:
226
+ ## 常用命令
101
227
 
102
228
  ```bash
229
+ dingtalk-agent --help
230
+ dingtalk-agent doctor
231
+ dingtalk-agent setup
232
+ dingtalk-agent skill install
233
+ dingtalk-agent skill status
234
+ dingtalk-agent bootstrap --json
235
+ dingtalk-agent init
236
+ dingtalk-agent prepare --event-file event.json --json
103
237
  dingtalk-agent help runtime
104
238
  dingtalk-agent help adapters
239
+ dingtalk-agent eval contract
105
240
  ```
106
241
 
107
- 云端 Driver、Claude Code 插件或本地 DWS 都可以提供事件;它们从标准化事件以后共享同一 Session/Run/Action 内核和唯一外发 owner。
242
+ `listen` 是可选的开发联调 Adapter,不是 Agent 主进程。云端 Driver、Claude Code 插件或本地 DWS 都可以提供事件,并从标准化事件之后复用同一 Session / Run / Action 内核。
108
243
 
109
- ## 自测
244
+ ## 评测与验证
110
245
 
111
246
  ```bash
112
247
  npm ci
@@ -114,13 +249,48 @@ npm run typecheck
114
249
  npm run eval:contract
115
250
  ```
116
251
 
117
- 当前确定性合同包含 26 个场景,覆盖全局 Skill 安装与生命周期、无 init bootstrap、本地/远端 Storage、类型闸门、Direct Session 外发闸门,以及原有的 Session、Wait、幂等、目标防篡改和 Skill 冻结。评测页面见 [review.html](evals/results/contract/review.html)。
252
+ 当前确定性合同包含 **28 个场景**,覆盖:
253
+
254
+ - 全局 Skill 安装、发现、升级和漂移保护;
255
+ - 首次 setup、用户级 PATH、DWS 版本/认证和三端客户端发现;
256
+ - 无 init bootstrap、本地/远端 Storage 与类型闸门;
257
+ - Direct Session 外发边界;
258
+ - Session continuation、Wait、幂等和目标防篡改;
259
+ - Skill 冻结、动作预算和 Receipt。
260
+
261
+ 模型行为还可通过 Claude shadow 做 with-skill / baseline 对照;它只允许读取冻结输入并输出 ActionRequest,不产生任何钉钉副作用。完整晋级门禁见 [自测与持续进化](docs/SELF-TEST.md)。
262
+
263
+ ## 项目结构
264
+
265
+ ```text
266
+ bin/ CLI composition root
267
+ src/ TypeScript runtime
268
+ skills/dingtalk-basic-behavior/ 可安装的基础行为 Skill
269
+ templates/ Workspace 与行为模板
270
+ evals/ 合同、fixture 与 shadow runner
271
+ docs/ 架构、决策和调研文档
272
+ .github/ CI 与协作模板
273
+ ```
274
+
275
+ ## 深入阅读
118
276
 
119
277
  - [代码与运行架构](docs/ARCHITECTURE.md)
278
+ - [安装与首次使用](docs/INSTALLATION.md)
120
279
  - [最小 Workspace 决策记录](docs/MINIMAL-WORKSPACE-V1.md)
121
280
  - [自测与持续进化](docs/SELF-TEST.md)
122
281
  - [开源项目差异与共同范式](docs/OPEN-SOURCE-REFERENCES.md)
282
+ - [贡献指南](CONTRIBUTING.md)
283
+ - [安全策略](SECURITY.md)
284
+
285
+ ## 当前边界
286
+
287
+ - 不把 `listen` 作为 Agent 的强制主入口;
288
+ - 不自动初始化或污染任意代码仓库;
289
+ - 不复制整个 DWS 命令面;
290
+ - 不把钉钉文档当锁、事务数据库或副作用回执;
291
+ - 不允许在线 Run 自动扩大身份、权限或启用新 Skill;
292
+ - 当前 `dingtalk-doc` 只读水合,远端写入必须经过显式授权 Provider 并回读。
123
293
 
124
294
  ## License
125
295
 
126
- MIT
296
+ [MIT](LICENSE)
@@ -23,8 +23,11 @@ import { readEventFile, consumeNdjson, heartbeatEvent } from '../src/driver.js';
23
23
  import { findRun, previewAction, executeAction } from '../src/actions.js';
24
24
  import { resolvePackageRoot } from '../src/package-root.js';
25
25
  import { bootstrap } from '../src/bootstrap.js';
26
+ import { doctor } from '../src/doctor.js';
27
+ import { setup } from '../src/setup.js';
26
28
  import { installGlobalSkill, skillStatus, uninstallGlobalSkill, upgradeGlobalSkill, } from '../src/skill-manager.js';
27
29
  const PACKAGE_ROOT = resolvePackageRoot(import.meta.url);
30
+ const PACKAGE_JSON = JSON.parse(readFileSync(join(PACKAGE_ROOT, 'package.json'), 'utf8'));
28
31
  // ROOT = **你的工作区**(当前目录),不是包所在的目录。
29
32
  // 全局装 / npx 跑的时候,包住在 node_modules 里 —— 那不是 agent 的家。
30
33
  const ROOT = process.env.DTA_ROOT
@@ -33,8 +36,12 @@ const ROOT = process.env.DTA_ROOT
33
36
  const HELP = `
34
37
  dingtalk-agent —— Skill-first 的钉钉数字员工行为容器
35
38
 
36
- 一次安装(不要求 Workspace
37
- skill install 安装全局 Basic Behavior(Codex + Claude Code)
39
+ 首次使用(无全局命令时: npx --yes --registry=https://registry.npmjs.org @xdxer/dingtalk-agent@${PACKAGE_JSON.version} setup
40
+ setup 用户级安装 CLI、修复 PATH、安装 Skill、检查 DWS
41
+ doctor 检查 PATH / Node / DWS / Skill / Agent 客户端
42
+
43
+ Skill(不要求 Workspace)
44
+ skill install 安装全局 Basic Behavior(Claude Code + Codex + OpenCode)
38
45
  skill status 检查版本、漂移和客户端可发现性
39
46
  skill upgrade 升级本工具管理的全局 Skill
40
47
  skill uninstall 安全卸载本工具管理的全局 Skill
@@ -126,6 +133,47 @@ async function main() {
126
133
  console.log(HELP);
127
134
  return;
128
135
  }
136
+ if (cmd === '--version' || cmd === '-V' || cmd === 'version') {
137
+ console.log(PACKAGE_JSON.version);
138
+ return;
139
+ }
140
+ // ── setup / doctor:npx 永远可启动的首次使用入口。──
141
+ if (cmd === 'setup') {
142
+ const { values: o } = parseArgs({
143
+ args: argv.slice(1),
144
+ options: {
145
+ prefix: { type: 'string' }, 'dry-run': { type: 'boolean' },
146
+ 'no-shell-write': { type: 'boolean' }, 'skip-cli-install': { type: 'boolean' },
147
+ json: { type: 'boolean' },
148
+ },
149
+ });
150
+ const out = setup(PACKAGE_ROOT, {
151
+ prefix: o.prefix,
152
+ dryRun: o['dry-run'],
153
+ writeShell: !o['no-shell-write'],
154
+ skipCliInstall: o['skip-cli-install'],
155
+ });
156
+ if (o.json)
157
+ console.log(JSON.stringify(out, null, 2));
158
+ else
159
+ printSetup(out);
160
+ if (!out.doctor.ready)
161
+ process.exitCode = 2;
162
+ return;
163
+ }
164
+ if (cmd === 'doctor') {
165
+ const { values: o } = parseArgs({
166
+ args: argv.slice(1), options: { json: { type: 'boolean' } },
167
+ });
168
+ const out = doctor(PACKAGE_ROOT);
169
+ if (o.json)
170
+ console.log(JSON.stringify(out, null, 2));
171
+ else
172
+ printDoctor(out);
173
+ if (!out.ready)
174
+ process.exitCode = 2;
175
+ return;
176
+ }
129
177
  // ── skill:唯一一次性的主入口;完全不依赖 Workspace。──
130
178
  if (cmd === 'skill') {
131
179
  const { values: o } = parseArgs({
@@ -674,7 +722,9 @@ function printSkillStatus(out, action, dryRun) {
674
722
  console.log(` canonical=${out.canonical.path}`);
675
723
  console.log(` installed=${out.canonical.exists} managed=${out.canonical.managed} ` +
676
724
  `modified=${out.canonical.modified} current=${out.canonical.current}`);
677
- console.log(` Claude=${out.claude.state}${out.claude.target ? ` (${out.claude.target})` : ''}`);
725
+ for (const client of out.clients) {
726
+ console.log(` ${client.label}=${client.state} (${client.discovery}: ${client.path})`);
727
+ }
678
728
  if (out.legacyCodex.conflict) {
679
729
  console.log(` ⚠️ legacy Codex 同名路径存在: ${out.legacyCodex.path}`);
680
730
  }
@@ -682,4 +732,32 @@ function printSkillStatus(out, action, dryRun) {
682
732
  console.log(' 新 Agent 会话将自动发现;当前会话未发现时请重启 Claude Code/Codex。');
683
733
  }
684
734
  }
735
+ function printDoctor(out) {
736
+ console.log(`dingtalk-agent doctor · ${out.ready ? 'READY' : 'NOT READY'}`);
737
+ for (const check of out.checks) {
738
+ const mark = check.level === 'pass' ? '✅' : check.level === 'warn' ? '⚠️' : '❌';
739
+ console.log(`${mark} ${check.summary}`);
740
+ if (check.detail)
741
+ console.log(` ${check.detail}`);
742
+ if (check.fix)
743
+ console.log(` 修复: ${check.fix}`);
744
+ }
745
+ if (out.nextSteps.length) {
746
+ console.log('\n下一步:');
747
+ for (const step of out.nextSteps)
748
+ console.log(` ${step}`);
749
+ }
750
+ }
751
+ function printSetup(out) {
752
+ console.log(`${out.dryRun ? 'DRY-RUN' : '✅'} dingtalk-agent setup`);
753
+ console.log(` CLI: ${out.cli.executable}`);
754
+ console.log(` Skill: ${out.skill.canonical.path}`);
755
+ if (!out.shell.pathReady) {
756
+ console.log(` 当前 shell 尚未加载 PATH;本次终端执行: ${out.shell.activateCommand}`);
757
+ if (out.shell.rcFile)
758
+ console.log(` 新终端会从 ${out.shell.rcFile} 自动加载`);
759
+ }
760
+ printDoctor(out.doctor);
761
+ console.log(`\n开始使用: ${out.nextCommand}`);
762
+ }
685
763
  //# sourceMappingURL=dingtalk-agent.js.map