@di-code/coding-agent 0.1.3 → 0.1.6

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.
Files changed (147) hide show
  1. package/README.md +91 -30
  2. package/dist/cli.d.ts +15 -0
  3. package/dist/cli.d.ts.map +1 -1
  4. package/dist/cli.js +96 -17
  5. package/dist/cli.js.map +1 -1
  6. package/dist/core/clipboard-image.d.ts +3 -3
  7. package/dist/core/clipboard-image.d.ts.map +1 -1
  8. package/dist/core/clipboard-image.js +26 -13
  9. package/dist/core/clipboard-image.js.map +1 -1
  10. package/dist/core/context-builder.d.ts.map +1 -1
  11. package/dist/core/context-builder.js +6 -2
  12. package/dist/core/context-builder.js.map +1 -1
  13. package/dist/core/image-input.d.ts +1 -1
  14. package/dist/core/image-input.d.ts.map +1 -1
  15. package/dist/core/image-input.js +55 -10
  16. package/dist/core/image-input.js.map +1 -1
  17. package/dist/core/resources/loader.d.ts.map +1 -1
  18. package/dist/core/resources/loader.js +15 -42
  19. package/dist/core/resources/loader.js.map +1 -1
  20. package/dist/core/resources/types.d.ts +6 -9
  21. package/dist/core/resources/types.d.ts.map +1 -1
  22. package/dist/core/resources/types.js.map +1 -1
  23. package/dist/core/session/session-manager.d.ts +12 -1
  24. package/dist/core/session/session-manager.d.ts.map +1 -1
  25. package/dist/core/session/session-manager.js +66 -3
  26. package/dist/core/session/session-manager.js.map +1 -1
  27. package/dist/core/session/session-storage.d.ts.map +1 -1
  28. package/dist/core/session/session-storage.js +30 -15
  29. package/dist/core/session/session-storage.js.map +1 -1
  30. package/dist/core/session/types.d.ts +6 -1
  31. package/dist/core/session/types.d.ts.map +1 -1
  32. package/dist/core/session/types.js +1 -1
  33. package/dist/core/session/types.js.map +1 -1
  34. package/dist/core/session.d.ts +38 -3
  35. package/dist/core/session.d.ts.map +1 -1
  36. package/dist/core/session.js +167 -9
  37. package/dist/core/session.js.map +1 -1
  38. package/dist/core/system-prompt.js +2 -2
  39. package/dist/core/system-prompt.js.map +1 -1
  40. package/dist/core/tools/bash.d.ts +2 -2
  41. package/dist/core/tools/bash.d.ts.map +1 -1
  42. package/dist/core/tools/bash.js.map +1 -1
  43. package/dist/core/tools/edit-diff.d.ts +25 -0
  44. package/dist/core/tools/edit-diff.d.ts.map +1 -0
  45. package/dist/core/tools/edit-diff.js +136 -0
  46. package/dist/core/tools/edit-diff.js.map +1 -0
  47. package/dist/core/tools/edit.d.ts +13 -4
  48. package/dist/core/tools/edit.d.ts.map +1 -1
  49. package/dist/core/tools/edit.js +64 -30
  50. package/dist/core/tools/edit.js.map +1 -1
  51. package/dist/core/tools/file-search.d.ts +14 -0
  52. package/dist/core/tools/file-search.d.ts.map +1 -0
  53. package/dist/core/tools/file-search.js +99 -0
  54. package/dist/core/tools/file-search.js.map +1 -0
  55. package/dist/core/tools/glob.d.ts +11 -0
  56. package/dist/core/tools/glob.d.ts.map +1 -0
  57. package/dist/core/tools/glob.js +44 -0
  58. package/dist/core/tools/glob.js.map +1 -0
  59. package/dist/core/tools/grep.d.ts +13 -0
  60. package/dist/core/tools/grep.d.ts.map +1 -0
  61. package/dist/core/tools/grep.js +67 -0
  62. package/dist/core/tools/grep.js.map +1 -0
  63. package/dist/core/tools/load-skill.d.ts +10 -0
  64. package/dist/core/tools/load-skill.d.ts.map +1 -0
  65. package/dist/core/tools/load-skill.js +22 -0
  66. package/dist/core/tools/load-skill.js.map +1 -0
  67. package/dist/core/tools/path-boundary.d.ts +2 -0
  68. package/dist/core/tools/path-boundary.d.ts.map +1 -1
  69. package/dist/core/tools/path-boundary.js +4 -0
  70. package/dist/core/tools/path-boundary.js.map +1 -1
  71. package/dist/core/tools/read.d.ts +2 -2
  72. package/dist/core/tools/read.d.ts.map +1 -1
  73. package/dist/core/tools/read.js.map +1 -1
  74. package/dist/core/tools/write.d.ts +2 -2
  75. package/dist/core/tools/write.d.ts.map +1 -1
  76. package/dist/core/tools/write.js.map +1 -1
  77. package/dist/core/user-data.d.ts +3 -0
  78. package/dist/core/user-data.d.ts.map +1 -0
  79. package/dist/core/user-data.js +8 -0
  80. package/dist/core/user-data.js.map +1 -0
  81. package/dist/entry.js +22 -2
  82. package/dist/entry.js.map +1 -1
  83. package/dist/extensions/runtime.js +2 -2
  84. package/dist/extensions/runtime.js.map +1 -1
  85. package/dist/i18n.d.ts +5 -0
  86. package/dist/i18n.d.ts.map +1 -0
  87. package/dist/i18n.js +223 -0
  88. package/dist/i18n.js.map +1 -0
  89. package/dist/index.d.ts +3 -0
  90. package/dist/index.d.ts.map +1 -1
  91. package/dist/index.js +3 -0
  92. package/dist/index.js.map +1 -1
  93. package/dist/main.d.ts +20 -1
  94. package/dist/main.d.ts.map +1 -1
  95. package/dist/main.js +272 -17
  96. package/dist/main.js.map +1 -1
  97. package/dist/mcp/config.d.ts +33 -0
  98. package/dist/mcp/config.d.ts.map +1 -0
  99. package/dist/mcp/config.js +211 -0
  100. package/dist/mcp/config.js.map +1 -0
  101. package/dist/mcp/loader.d.ts +21 -0
  102. package/dist/mcp/loader.d.ts.map +1 -0
  103. package/dist/mcp/loader.js +60 -0
  104. package/dist/mcp/loader.js.map +1 -0
  105. package/dist/mcp/tool-adapter.d.ts +5 -0
  106. package/dist/mcp/tool-adapter.d.ts.map +1 -0
  107. package/dist/mcp/tool-adapter.js +149 -0
  108. package/dist/mcp/tool-adapter.js.map +1 -0
  109. package/dist/modes/interactive-components.d.ts +2 -0
  110. package/dist/modes/interactive-components.d.ts.map +1 -1
  111. package/dist/modes/interactive-components.js +55 -31
  112. package/dist/modes/interactive-components.js.map +1 -1
  113. package/dist/modes/interactive-diff.d.ts +8 -0
  114. package/dist/modes/interactive-diff.d.ts.map +1 -0
  115. package/dist/modes/interactive-diff.js +78 -0
  116. package/dist/modes/interactive-diff.js.map +1 -0
  117. package/dist/modes/interactive-layout.d.ts +4 -0
  118. package/dist/modes/interactive-layout.d.ts.map +1 -1
  119. package/dist/modes/interactive-layout.js +4 -0
  120. package/dist/modes/interactive-layout.js.map +1 -1
  121. package/dist/modes/interactive-state.d.ts +5 -0
  122. package/dist/modes/interactive-state.d.ts.map +1 -1
  123. package/dist/modes/interactive-state.js +65 -11
  124. package/dist/modes/interactive-state.js.map +1 -1
  125. package/dist/modes/interactive.d.ts +19 -0
  126. package/dist/modes/interactive.d.ts.map +1 -1
  127. package/dist/modes/interactive.js +351 -52
  128. package/dist/modes/interactive.js.map +1 -1
  129. package/dist/modes/tree-selector.d.ts +30 -0
  130. package/dist/modes/tree-selector.d.ts.map +1 -0
  131. package/dist/modes/tree-selector.js +205 -0
  132. package/dist/modes/tree-selector.js.map +1 -0
  133. package/dist/plugins/loader.d.ts +19 -1
  134. package/dist/plugins/loader.d.ts.map +1 -1
  135. package/dist/plugins/loader.js +21 -2
  136. package/dist/plugins/loader.js.map +1 -1
  137. package/dist/provider-onboarding.d.ts +8 -1
  138. package/dist/provider-onboarding.d.ts.map +1 -1
  139. package/dist/provider-onboarding.js +160 -40
  140. package/dist/provider-onboarding.js.map +1 -1
  141. package/dist/rpc-entry.js +1 -1
  142. package/dist/rpc-entry.js.map +1 -1
  143. package/dist/startup.d.ts +34 -3
  144. package/dist/startup.d.ts.map +1 -1
  145. package/dist/startup.js +407 -87
  146. package/dist/startup.js.map +1 -1
  147. package/package.json +7 -4
package/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  - `di-code`:面向人的交互式、单次输出和 JSON 事件 CLI;
6
6
  - `di-code-rpc`:供 Node.js 宿主程序管理的 JSONL RPC 子进程入口;
7
- - 内置的 `read`、`write`、`edit`、`bash` 工具、JSONL 会话、图片输入、上下文压缩;
7
+ - 内置的 `read`、`write`、`edit`、`glob`、`grep`、`bash` 工具、JSONL 会话、图片输入、上下文压缩;
8
8
  - 可复用的 **Skills(技能指令)**、`AGENTS.md` 项目说明,以及插件扩展机制。
9
9
 
10
10
  > **运行环境:**Node.js `>= 22.19.0`。真实 Provider 会产生网络请求和费用;首次体验可使用离线的 `faux` Provider。
@@ -40,12 +40,16 @@ di-code
40
40
 
41
41
  在向导中依次完成:
42
42
 
43
- 1. **选择 Provider**:例如 `OpenAI`、`Anthropic`、`DeepSeek`、`Zhipu AI`;如果只想离线试用,选择 `Faux (offline)`。
44
- 2. **选择模型**:向导会列出当前 Provider 支持的模型,选择你有权限使用的模型。
43
+ 1. **选择 Provider**:例如 `OpenAI`、`Anthropic`、`DeepSeek`、`Zhipu AI`;也可以选择 `Custom` 配置兼容网关;如果只想离线试用,选择 `Faux (offline)`。
44
+ 2. **选择模型**:内建 Provider 会列出当前支持的模型;Custom 会先选择 API 协议,再输入 Base URL、API key 和任意模型 ID。
45
45
  3. **填写 API key**:选择真实 Provider 时,在隐藏输入框中粘贴对应的 key;输入内容不会显示在终端中。
46
46
  4. **确认并开始对话**:向导完成后进入 interactive 模式,在底部输入框输入问题并按 `Enter`。
47
47
 
48
- 向导输入的 API key 只存在于当前进程内存,不会保存到 `.env`、`.di-code/settings.json`、会话文件或日志。退出后再次启动,如果没有环境变量或 settings 配置,向导会再次出现。
48
+ 向导输入的 API key 会保存到用户全局 `~/.di-code/settings.json`,供之后启动复用;不会写入 `.env`、项目 `.di-code/settings.json`、会话文件或日志。请保护用户目录的访问权限,不要复制或提交该文件。
49
+
50
+ 已经进入交互模式后,使用 `/login` 可以重新打开 Provider、模型和 key 向导。它总会要求真实 Provider 输入新的隐藏 key,写入用户全局 `settings.json` 成功后立即切换当前会话的 Provider 和模型。`/logout` 会移除当前 Provider 在该全局文件中的 `apiKey`,并在它是默认 Provider 时清除 `defaultProvider` 与 `defaultModel`;`api`、`baseUrl`、`models` 和其他 Provider 配置仍会保留。为避免登出后因缺少 key 重新构建失败,当前会话会继续使用已加载的运行时直到退出;下次交互启动时,如没有明确的 Provider 选择,会显示选择/登录向导。它不会也无法删除环境变量中的 key,因此环境变量仍可能继续生效。
51
+
52
+ `/login` 还会更新同一文件的 `defaultProvider` 和 `defaultModel`。当全局配置中有多个 Provider 时,下一次启动会使用这两个默认值;显式设置的 `DI_CODE_PROVIDER` 与 `DI_CODE_MODEL` 始终优先。
49
53
 
50
54
  向导完成后可以直接这样使用:
51
55
 
@@ -55,12 +59,14 @@ di-code
55
59
 
56
60
  ### 方式二:直接用 `settings.json` 配置
57
61
 
58
- 如果你已经知道 Provider、`baseUrl`、模型和 API key,可以不使用向导,直接在**当前项目根目录**创建 `.di-code/settings.json`。这是配置私有网关、自定义模型或希望配置可复用时推荐的方式。
62
+ 如果你已经知道 Provider、`baseUrl`、模型和 API key,可以不使用向导,直接创建 `settings.json`。启动时会先读取用户全局配置 `~/.di-code/settings.json`,再读取当前项目的 `.di-code/settings.json`;项目配置会覆盖同名 Provider 的已设置字段,并保留全局 Provider 中项目未设置的字段。全局配置适合个人常用 Provider,项目配置适合私有网关或项目专用模型。
63
+
64
+ 同名 Provider 的 `models` 在项目中出现时会整体替换全局的模型列表;项目未写 `models` 时继续使用全局模型列表。只存在于任一文件中的 Provider 都会保留。
59
65
 
60
66
  下面这个例子使用 OpenAI Responses 兼容接口。将示例中的 `baseUrl`、`apiKey` 和模型字段替换为实际值后即可使用:
61
67
 
62
68
 
63
- `.di-code/settings.json`:
69
+ `~/.di-code/settings.json` 或 `.di-code/settings.json`:
64
70
 
65
71
  ```json
66
72
  {
@@ -87,7 +93,7 @@ di-code
87
93
  默认使用第一个模型。可以添加多个模型然后使用`/model`切换
88
94
 
89
95
 
90
- `settings.json` 中的 `apiKey` 可以直接填写字符串,**但不建议这样做**,因为它很容易被提交到 Git。更安全的写法是引用环境变量:
96
+ `settings.json` 中的 `apiKey` 可以直接填写字符串,也可以引用环境变量。全局配置通常不进入项目 Git,因此适合保存个人配置;项目配置若使用明文 key,必须确保 `.di-code/settings.json` 不会提交。环境变量写法如下:
91
97
 
92
98
  ```json
93
99
  {
@@ -118,7 +124,10 @@ di-code "检查当前项目的测试状态"
118
124
  | 字段 | 作用 |
119
125
  | --- | --- |
120
126
  | `providers` | Provider 配置对象,key 是 Provider ID |
121
- | `api` | 接口类型:`openai-responses`、`deepseek-responses`、`zhipu-chat-completions` `anthropic-messages` |
127
+ | `defaultProvider` | 可选的默认 Provider;`/login` 自动更新,多个 Provider 时用于消除启动歧义 |
128
+ | `defaultModel` | `defaultProvider` 的可选默认模型;`/login` 自动更新 |
129
+ | `locale` | 仅用户全局 `~/.di-code/settings.json`:`en` 或 `zh-CN`;控制内置 CLI 与交互终端文案 |
130
+ | `api` | 接口类型:`openai-responses`、`openai-chat-completions` 或 `anthropic-messages` |
122
131
  | `baseUrl` | Provider 的接口地址,必须是绝对的 `http` 或 `https` URL |
123
132
  | `apiKey` | API key,推荐填写 `$ENV_VAR` 或 `${ENV_VAR}` |
124
133
  | `models` | 自定义 Provider 必填的模型列表 |
@@ -146,7 +155,7 @@ di-code "检查当前项目的测试状态"
146
155
  }
147
156
  ```
148
157
 
149
- 如果 `settings.json` 中只有一个 Provider,可以省略 `DI_CODE_PROVIDER`;如果有多个 Provider,则必须设置它。`DI_CODE_MODEL` 省略时使用该 Provider 模型列表的第一项。配置完成后,先用 print 模式验证:
158
+ 合并后的 `settings.json` 中只有一个 Provider 时,可以省略 `DI_CODE_PROVIDER`;如果有多个 Provider,则必须设置它。`DI_CODE_MODEL` 省略时使用该 Provider 模型列表的第一项。配置完成后,先用 print 模式验证:
150
159
 
151
160
  ```powershell
152
161
  di-code --print "用一句话介绍当前项目"
@@ -188,6 +197,7 @@ di-code "检查这个仓库的目录结构"
188
197
  | `anthropic` | `ANTHROPIC_API_KEY` | `ANTHROPIC_BASE_URL` |
189
198
  | `deepseek` | `DEEPSEEK_API_KEY` | `DEEPSEEK_BASE_URL` |
190
199
  | `zhipu` | `ZAI_API_KEY` | `ZHIPU_BASE_URL` |
200
+ | `kimi` | `KIMI_API_KEY` | `KIMI_BASE_URL` |
191
201
  | `faux` | 无 | 无(离线测试用) |
192
202
 
193
203
  例如 DeepSeek:
@@ -201,6 +211,14 @@ di-code "找出可能需要补测试的模块"
201
211
 
202
212
  `DI_CODE_MODEL` 必须属于当前 Provider;省略时会使用内建默认模型或该 Provider 列表中的第一个模型。选错模型时,CLI 会列出可用 ID。
203
213
 
214
+ Kimi Coding 使用 OpenAI Chat Completions 兼容 endpoint `https://api.kimi.com/coding/v1`,内建模型为 `k3`、`k3-256k`、`kimi-for-coding` 和 `kimi-for-coding-highspeed`。Kimi 官方也提供 Anthropic 兼容 endpoint,但当前内建 Provider 使用 OpenAI 兼容协议。
215
+
216
+ ### 终端语言
217
+
218
+ 设置 `DI_CODE_LOCALE=zh-CN` 可为当前进程显示中文内置终端文案;`en` 则显示英文。未设置时,di-code 读取用户全局 `~/.di-code/settings.json` 的 `locale`,默认 `en`。在 interactive 模式中通过 `/settings` 切换会立即刷新界面并保存该全局偏好。项目 `.di-code/settings.json` 不会覆盖语言偏好。
219
+
220
+ JSON/RPC 字段、slash command 名称、工具名、Provider 和模型 ID,以及插件提供的文本不随 locale 改变。
221
+
204
222
  ## 日常使用
205
223
 
206
224
  ```text
@@ -267,21 +285,31 @@ di-code --continue "继续上一次工作"
267
285
  | `/clear` | 仅清除屏幕可见消息,不删除会话文件 |
268
286
  | `/model` | 切换当前 Provider 的模型 |
269
287
  | `/session` | 选择或切换会话 |
288
+ | `/tree` | 打开紧凑的分支树;`Enter` 继续、`e` 编辑用户提示词、`s` 摘要后创建分支 |
270
289
  | `/theme` | 选择 dark 或 light 主题 |
271
- | `/settings` | 配置上下文压缩开关 |
290
+ | `/settings` | 配置上下文压缩开关和内置终端语言 |
291
+ | `/login` | 打开 Provider、模型和隐藏 API key 向导;保存到用户全局配置并切换当前会话 |
292
+ | `/logout` | 移除当前 Provider 的用户全局 `apiKey`,并在适用时清除默认 Provider/模型;不改环境变量或其他 Provider 配置,当前会话保持可用至退出 |
272
293
  | `/compact` | 立即压缩当前持久化会话的旧上下文 |
273
294
  | `/usage` | 查看请求数、token、费用和上下文占用 |
274
295
  | `/retry` | 重新提交最近失败或取消的 prompt |
296
+ | `/steer` | 在当前 prompt 运行期间向 Agent 追加引导内容(例如 `/steer 简短回答`);空闲时使用会报错 |
297
+ | `/skill:<name>` | 手动调用一个已加载的 Skill,可附带具体请求(见下文 Skills 部分) |
298
+
299
+ 插件和扩展也可以注册额外 slash command,名称与内置命令冲突时以加载诊断为准。
275
300
 
276
301
  | 按键 | 作用 |
277
302
  | --- | --- |
278
303
  | `Enter` | 发送当前 prompt |
304
+ | `Shift+Enter` | 在输入框中插入换行 |
279
305
  | `Esc` | 取消当前模型请求;没有请求时关闭补全或选择器 |
280
306
  | `Ctrl+C` | 退出并恢复终端状态 |
307
+ | `Tab` | 补全 slash command |
308
+ | `Alt+S` | 把编辑框当前内容作为引导发送给运行中的 Agent(与 `/steer` 等价) |
309
+ | `Shift+Tab` | 循环切换模型的 thinking 等级(模型不支持时提示错误) |
281
310
  | `Ctrl+O` / `Ctrl+L` | 打开模型 / 会话选择器 |
282
311
  | `Ctrl+T` / `Ctrl+S` | 打开主题 / 设置 |
283
312
  | `Ctrl+R` | 重试最近失败的 prompt |
284
- | `Tab` | 补全 slash command |
285
313
 
286
314
  取消只停止当前请求,不会删除已经追加到磁盘的会话记录。之后可使用 `/retry` 再试一次。
287
315
 
@@ -289,9 +317,9 @@ di-code --continue "继续上一次工作"
289
317
 
290
318
  ### 会话
291
319
 
292
- 交互式启动默认会在工作根目录的 `.di-code/sessions/` 创建版本化 JSONL 会话。记录为 append-only(只追加)格式;完整磁盘历史和发送给模型的压缩上下文分开保存。可通过 `/session`、`--session` `--continue` 恢复它们。
320
+ 交互式启动默认会在用户目录 `~/.di-code/sessions/<工作区哈希>/` 创建 v2 JSONL 会话。记录为 append-only(只追加)格式,可引用任意已提交父节点,因此一份文件可以保存多个分支;重启默认恢复物理文件末端记录所在的分支。`/tree` 只在 interactive 模式提供专用树浏览器:以紧凑单栏树显示节点摘要和当前路径,当前选择以 `›` 标识;选择用户消息会将其文本恢复到编辑器,并从它的父节点创建新的 sibling 分支;选择 assistant、tool result 或 summary 则将该节点作为活动叶节点。`s` 会在所选路径上执行现有上下文压缩,成功后的 summary 成为下一条 prompt 的分支父节点;没有有效压缩切点时会明确失败。图片附件不会自动恢复,导航只改变模型可见上下文,不能回滚工作区副作用。v1 或未知版本的会话文件不迁移,打开时返回 `UNSUPPORTED_VERSION`。完整磁盘历史和发送给模型的压缩上下文分开保存,summary 只作用于其所在分支。`/session` `--continue` 只显示或恢复当前工作区的默认会话;`--session` 可以打开任意指定路径。已有项目内 `.di-code/sessions/` 文件不会自动移动,仍可用 `--session <path>` 显式打开。
293
321
 
294
- 会话可能包含你的 prompt、模型回答、工具结果和图片内容。不要在 prompt 或图片中提交不应保留在项目本地历史中的密钥或敏感材料。
322
+ 会话可能包含你的 prompt、模型回答、工具结果和图片内容。不要在 prompt 或图片中提交不应保留在本地历史中的密钥或敏感材料。
295
323
 
296
324
  ### 图片
297
325
 
@@ -304,7 +332,7 @@ di-code --image .\before.png --image .\after.webp "比较两张图"
304
332
 
305
333
  只支持 PNG、JPEG、WebP、GIF;文件根据内容签名而不是扩展名校验。每条 prompt 最多 4 张、每张最多 5 MiB,并且当前模型必须声明支持图片输入。
306
334
 
307
- 交互模式中可输入 `@diagram.png`;有空格的路径使用 `@"architecture diagram.png"`。也可将图片拖入终端。读取剪贴板图片时,Windows 使用 `Alt+V`,macOS/Linux 使用 `Ctrl+V`。剪贴板临时文件放在 `.di-code/clipboard/`,发送、删除引用或退出后会清理。
335
+ 交互模式中可输入 `@diagram.png`;有空格的路径使用 `@"architecture diagram.png"`。也可将图片拖入终端。读取剪贴板图片时,Windows 使用 `Alt+V`,macOS/Linux 使用 `Ctrl+V`。剪贴板临时文件放在用户目录 `~/.di-code/clipboard/<工作区哈希>/<进程 ID>/`,发送、删除引用或退出后会清理;启动时也会清理当前工作区超过 24 小时的遗留文件。
308
336
 
309
337
  ### Agent 可调用的内置工具
310
338
 
@@ -315,15 +343,44 @@ di-code --image .\before.png --image .\after.webp "比较两张图"
315
343
  | `read` | 读取工作根目录中的 UTF-8 文本文件 | 最多 2,000 行、50 KiB;支持 `offset`、`limit` |
316
344
  | `write` | 创建或完全覆盖 UTF-8 文件 | 自动创建父目录 |
317
345
  | `edit` | 对文件做一次唯一的精确文本替换 | 找不到或匹配多处时拒绝写入;保留 BOM 和换行风格 |
346
+ | `glob` | 按 glob pattern 查找文件 | 返回排序后的相对路径;默认最多 200 个结果、50 KiB;跳过 symlink |
347
+ | `grep` | 在 UTF-8 文本文件中查找字面量文本 | 返回 `path:line` 匹配;默认最多 200 个结果、50 KiB;跳过二进制文件、symlink 和超过 2 MiB 的单文件 |
318
348
  | `bash` | 在工作根目录执行本地命令 | 默认 30 秒、最大 5 分钟;stdout/stderr 各截断至 50 KiB |
319
349
 
320
- 文件工具限制目标在工作根目录内并拒绝二进制文件。`bash` 在 Windows 使用 PowerShell,在其他平台使用 `/bin/sh`;它并不是操作系统级沙箱。模型和插件仍可能尝试执行危险操作,因此请审查任务和结果,并避免在包含无关敏感文件的目录运行。
350
+ 文件工具限制目标在工作根目录内并拒绝二进制文件。`glob` 和 `grep` 使用 Node 文件 API,不依赖系统安装的 `grep` 或 shell;它们不跟随 symlink,并支持取消信号。`grep` 的 `pattern` 是字面量匹配,不是正则表达式。`bash` 在 Windows 使用 PowerShell,在其他平台使用 `/bin/sh`;它并不是操作系统级沙箱。模型和插件仍可能尝试执行危险操作,因此请审查任务和结果,并避免在包含无关敏感文件的目录运行。
351
+
352
+ ## MCP Server
353
+
354
+ 受信任项目可在工作根目录创建 `.mcp.json` 来接入 MCP Server tools。支持本地 `stdio` 和远程 Streamable HTTP:
355
+
356
+ ```json
357
+ {
358
+ "mcpServers": {
359
+ "project-tools": { "command": "npx", "args": ["-y", "@example/project-mcp"] }
360
+ }
361
+ }
362
+ ```
363
+
364
+ HTTP 配置使用 `type: "http"`、绝对 `http`/`https` `url` 和可选 `headers`。Server ID 使用小写字母、数字、`-` 和 `_`;工具名会转换为 `mcp__project-tools__<tool-name>`。支持 resources/prompts 的 Server 还会显式注册 `mcp__project-tools__resources_list`、`resource_read`、`prompts_list` 和 `prompt_get`;资源和提示词不会自动注入模型上下文。`env` 和 `headers` 中可使用 `${ENV_VAR}`,缺失变量会阻止该配置加载且不会泄露变量值。项目未获 trust 时不会启动 local/project Server;user scope 仍可使用。连接、schema、认证或工具调用错误会产生脱敏 `mcp_diagnostic` 或正常的工具错误。MCP Server 是外部代码,项目 trust 不是权限沙箱。
365
+
366
+ 配置管理命令:
367
+
368
+ ```powershell
369
+ di-code mcp add project-tools -- npx -y @example/project-mcp
370
+ di-code mcp add --scope project project-tools -- npx -y @example/project-mcp
371
+ di-code mcp add --scope project --transport http company-api https://mcp.example.com/mcp
372
+ di-code mcp list --scope project
373
+ di-code mcp get company-api
374
+ di-code mcp remove company-api --scope project
375
+ ```
376
+
377
+ 配置范围按 `local` > `project` > `user` 生效:local 写入 `<work-root>/.di-code/mcp.local.json`,project 写入 `<work-root>/.mcp.json`,user 写入 `~/.di-code/mcp.json`。同一 Server ID 整体覆盖,不做字段级合并。interactive 启动时,每个 MCP Server 会先显示黄色 `[loading]`,并在完成时原位替换为绿色 `[ok]` 或红色 `[error]`;成功状态包含 tools、resources 和 prompts 数量,失败信息经过脱敏。`mcp add <id> -- <command> [args...]` 默认使用 local stdio;HTTP 必须显式指定 `--transport http`。`list` 和 `get` 会脱敏 header、环境变量和其他凭据;`add` 不安装或下载 Server 软件,stdio 的命令仍由用户提供并在连接时执行。
321
378
 
322
379
  ## 项目说明与 Skills
323
380
 
324
381
  ### `AGENTS.md`:给 Agent 的项目规则
325
382
 
326
- 启动时,di-code 会在全局 Agent 目录,以及当前工作目录到文件系统根目录的祖先路径中发现 `AGENTS.md`(或 `AGENTS.MD`)。这些文件会作为项目上下文提供给模型,适合记录构建命令、代码风格、测试要求和目录约定。
383
+ 启动时,di-code 会读取全局 Agent 目录中的 `AGENTS.md`(或 `AGENTS.MD`),以及当前工作目录中的同名文件。不会自动加载当前目录父级中的 `AGENTS.md`。这些文件会作为项目上下文提供给模型,适合记录构建命令、代码风格、测试要求和目录约定。
327
384
 
328
385
  项目文件是**不可信的上下文**,不能改变 CLI 的真实路径、权限或安全边界。临时忽略所有这类文件:
329
386
 
@@ -333,15 +390,15 @@ di-code --no-context-files "只分析当前文件,不遵循项目说明"
333
390
 
334
391
  ### Skills:可按需加载的专业工作流
335
392
 
336
- Skill 是带少量 YAML frontmatter 的 `SKILL.md` 文件。它不是可执行代码,而是一组可复用的 Markdown 指令,例如“如何发布版本”“如何处理数据库迁移”。默认情况下,模型看到 Skill 的名称和描述;任务匹配时,它会先用 `read` 读取完整 Skill,再按其步骤工作。
393
+ Skill 是带 YAML frontmatter 的 `SKILL.md` 文件。解析、发现、目录和正文读取由独立的 `@di-code/skills` 包提供;它不是可执行代码。默认情况下,模型只看到名称和描述;任务匹配时,它必须使用受控的 `load_skill` 工具按名称加载正文。
337
394
 
338
395
  Skill 的发现位置和优先级如下:
339
396
 
340
397
  1. `--skill <path>` 显式传入的文件或目录;
341
- 2. 已信任项目的 `.di-code/skills/` 与 `.pi/skills/`;
398
+ 2. 已信任项目的 `.di-code/skills/` 与 `.agents/skills/`;
342
399
  3. 用户全局目录 `~/.di-code/skills/`。
343
400
 
344
- 目录会递归查找名为 `SKILL.md` 的文件,跳过隐藏目录和 `node_modules`。同名时先发现的 Skill 生效;冲突和格式错误会产生诊断。项目 Skill 不会在项目未信任时加载。
401
+ 目录会递归查找名为 `SKILL.md` 的文件,跳过隐藏目录和 `node_modules`。同名时先发现的 Skill 生效;冲突和格式错误会产生诊断。项目 Skill 不会在项目未信任时加载。Skill metadata 不能授予文件、命令或网络权限。
345
402
 
346
403
  创建项目 Skill:
347
404
 
@@ -353,7 +410,7 @@ my-project/
353
410
  SKILL.md
354
411
  ```
355
412
 
356
- `.di-code/skills/release-check/SKILL.md`:
413
+ `.di-code/skills/release-check/SKILL.md`(或 `.agents/skills/release-check/SKILL.md`):
357
414
 
358
415
  ```markdown
359
416
  ---
@@ -373,14 +430,16 @@ description: Verify the release checklist before publishing a package.
373
430
  - 文件最大 256 KiB,首行和 frontmatter 结束行必须都是 `---`;
374
431
  - 可加 `disable-model-invocation: true` 隐藏该 Skill,使模型不自动选择它,但用户仍可手动调用。
375
432
 
376
- 首次使用项目本地 Skill 或插件前,明确授予信任:
433
+ 交互式 TTY 首次发现项目本地 Skill、插件或扩展目录时,di-code 会询问是否信任当前项目。回答 `y`/`yes` 会加载这些项目资源,其他输入(包括直接回车)会拒绝加载;选择会保存到用户全局 Agent 目录,后续启动不再重复询问。非交互模式不会等待询问,默认不信任。
434
+
435
+ 也可以显式授予信任:
377
436
 
378
437
  ```powershell
379
438
  Set-Location D:\work\my-project
380
439
  di-code --trust-project --interactive
381
440
  ```
382
441
 
383
- 该决定保存在用户全局 Agent 目录中,并按当前项目路径生效。撤销:
442
+ 撤销:
384
443
 
385
444
  ```powershell
386
445
  di-code --untrust-project --interactive
@@ -409,7 +468,7 @@ di-code --no-skills "不要加载任何 Skill"
409
468
  2. interactive 模式中的 slash command;
410
469
  3. Agent 与会话生命周期事件处理器。
411
470
 
412
- 插件不是 MCP Server,也没有热重载、插件市场或真正的权限沙箱。manifest 的 `permissions` 是声明和审计信息,**不会**阻止插件访问文件、网络或子进程。因此,只安装或信任可信来源的插件。
471
+ 插件不是 MCP Server,也没有热重载、插件市场或真正的权限沙箱。manifest 的 `permissions` 是声明和审计信息,**不会**阻止插件访问文件、网络或子进程。因此,只安装或信任可信来源的插件。interactive 启动时,每个实际加载的插件会先显示黄色 `[loading]`,并在完成时原位替换为绿色 `[ok]` 或红色 `[error]`;成功项会列出该插件新增的 tools 和 slash commands 数量。print 和 JSON 模式保持 `plugin_diagnostic` 输出。
413
472
 
414
473
  ### 使用项目本地插件
415
474
 
@@ -438,7 +497,7 @@ di-code --no-skills "不要加载任何 Skill"
438
497
  }
439
498
  ```
440
499
 
441
- 入口必须默认导出一个 factory 函数。项目插件仅在运行过 `di-code --trust-project --interactive` 后导入。插件工具名必须采用 `<plugin-id>__<tool-name>`,避免与内置工具或其他插件冲突。
500
+ 入口必须默认导出一个 factory 函数。项目插件仅在当前项目已获信任后导入。插件工具名必须采用 `<plugin-id>__<tool-name>`,避免与内置工具或其他插件冲突。
442
501
 
443
502
  完整的 TypeBox schema、工具、slash command、生命周期事件及安全责任,请阅读仓库文档:[插件使用指南](https://github.com/qddidi/di-code/blob/main/docs/%E6%8F%92%E4%BB%B6%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97.md)。
444
503
 
@@ -465,7 +524,9 @@ di-code plugin remove project-status
465
524
 
466
525
  ## 自定义 Provider
467
526
 
468
- 自定义 OpenAI Responses 兼容网关或私有模型时,在工作根目录创建 `.di-code/settings.json`。凭据推荐使用环境变量引用:
527
+ interactive TTY 的首次向导或 `/login` 中选择 `Custom`,可以按协议、Base URL、API key 和模型 ID 的顺序配置一个用户级固定 `custom` Provider。支持 `openai-responses`、`openai-chat-completions` 和 `anthropic-messages`。Base URL 必须是绝对 `http`/`https` URL,不能包含凭据、query、hash 或尾随 `/`。如果模型 ID 与内置目录中的同协议模型精确匹配,向导会复制其能力元数据;否则使用保守的文本模型默认值。重新配置会覆盖 `custom`,但保留其他用户级 Provider。
528
+
529
+ 自定义 OpenAI Responses 兼容网关或私有模型时,可在用户全局 `~/.di-code/settings.json` 或工作根目录 `.di-code/settings.json` 中声明 Provider。两个文件同时存在时,项目配置覆盖全局配置中的同名 Provider 字段。`apiKey` 可以直接填写,或使用环境变量引用:
469
530
 
470
531
  ```json
471
532
  {
@@ -499,9 +560,9 @@ $env:DI_CODE_MODEL = "company-coder"
499
560
  di-code "总结当前项目"
500
561
  ```
501
562
 
502
- `api` 可为 `openai-responses`、`deepseek-responses`、`zhipu-chat-completions` 或 `anthropic-messages`。自定义 Provider 必须提供 `models`;每个模型可设置 `id`、`name`、`input`、`reasoning`、`contextWindow`、`maxTokens`(或 `maxOutputTokens`)及按美元/百万 token 计的 `cost`。
563
+ `api` 可为 `openai-responses`、`openai-chat-completions` 或 `anthropic-messages`。自定义 Provider 必须提供 `models`;每个模型可设置 `id`、`name`、`input`、`reasoning`、`contextWindow`、`maxTokens`(或 `maxOutputTokens`)及按美元/百万 token 计的 `cost`。Chat Completions 模型还可声明 `chatCompletionsCompat`,用于 DeepSeek/GLM/Kimi 的 thinking、reasoning_effort、`max_tokens`、流式 usage 和 `tool_stream` 等兼容差异。Kimi 模型支持 `low`、`high`、`max` 推理等级;Kimi 不发送 DeepSeek/智谱的 `thinking` 对象,而是发送 `reasoning_effort`。
503
564
 
504
- `apiKey` 支持 `$NAME` 或 `${NAME}` 环境变量引用。虽然可以直接写入字符串,但不要把 key 写到 `settings.json` 或提交到 Git。`baseUrl` 必须是绝对 `http`/`https` URL。
565
+ `apiKey` 支持直接字符串,也支持 `$NAME` 或 `${NAME}` 环境变量引用。项目级 `settings.json` 若含明文 key,必须保持未提交;`baseUrl` 必须是绝对 `http`/`https` URL。
505
566
 
506
567
  ## 脚本和 RPC 集成
507
568
 
@@ -548,15 +609,15 @@ import { RpcClient, RPC_PROTOCOL_VERSION } from "@di-code/coding-agent/rpc";
548
609
  ## 安全边界与故障排查
549
610
 
550
611
  - 在可信项目根目录运行;`bash` 不是沙箱,插件也没有沙箱。
551
- - API key 只放环境变量或秘密管理工具。不要放入 prompt、Skill、插件源码、会话、图片或 Git。
552
- - 项目 Skill 与插件默认不加载,直到执行 `--trust-project`;该开关是“是否导入项目本地代码/指令”的决定,不会赋予额外系统权限。
612
+ - 向导会将输入的 API key 保存到用户全局 `~/.di-code/settings.json`;不要放入 prompt、Skill、插件源码、会话、图片、项目配置或 Git。
613
+ - 项目 Skill、插件和扩展默认不加载;交互式 TTY 首次发现这些目录时会询问一次,`--trust-project` / `--untrust-project` 可显式控制。该决定是“是否导入项目本地代码/指令”的选择,不会赋予额外系统权限。
553
614
  - Provider、模型、图片、配置和工具参数都会校验;外部项目内容和模型输出仍应视作不可信输入。
554
615
 
555
616
  | 问题 | 优先检查 |
556
617
  | --- | --- |
557
618
  | `Provider is not configured` | 设置 `DI_CODE_PROVIDER` 及对应 API key;或在 TTY 中运行 `di-code` 使用向导;离线测试使用 `faux` |
558
619
  | `Unknown model` | 确认 `DI_CODE_MODEL` 属于当前 `DI_CODE_PROVIDER` |
559
- | 项目 Skill / 插件没有加载 | 目录是否为 `.di-code/skills` 或 `.di-code/plugins`,并运行 `di-code --trust-project --interactive` |
620
+ | 项目 Skill / 插件没有加载 | Skill 目录是否为 `.di-code/skills` 或 `.agents/skills`,插件目录是否为 `.di-code/plugins`;交互式启动时确认 trust 提示,或运行 `di-code --trust-project --interactive` |
560
621
  | `Unknown skill` | Skill 是否有正确 `SKILL.md` frontmatter,名称是否匹配 `/skill:<name>`;检查是否被 `--no-skills` 禁用 |
561
622
  | `plugin_diagnostic` | 检查 `plugin.json`、默认导出、入口路径及 stderr 的 JSON 诊断;详见插件指南 |
562
623
  | 图片被拒绝 | 确认格式、4 张/5 MiB 限制,以及模型 `input` 包含 `image` |
package/dist/cli.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { type Locale } from "./i18n.ts";
1
2
  export type OutputMode = "print" | "json" | "interactive";
2
3
  export type CliCommand = {
3
4
  kind: "help";
@@ -7,6 +8,15 @@ export type CliCommand = {
7
8
  kind: "plugin";
8
9
  action: "install" | "list" | "enable" | "disable" | "update" | "remove";
9
10
  argument?: string;
11
+ } | {
12
+ kind: "mcp";
13
+ action: "add" | "list" | "get" | "remove";
14
+ scope?: "local" | "project" | "user";
15
+ serverId?: string;
16
+ transport?: "stdio" | "http";
17
+ command?: string;
18
+ args?: readonly string[];
19
+ url?: string;
10
20
  } | {
11
21
  kind: "run";
12
22
  mode: OutputMode;
@@ -23,6 +33,7 @@ export declare class CliUsageError extends Error {
23
33
  constructor(message: string);
24
34
  }
25
35
  export declare function parseCliArgs(args: readonly string[]): CliCommand;
36
+ export declare function helpText(locale: Locale): string;
26
37
  export interface CliDependencies {
27
38
  stdout(text: string): void;
28
39
  stderr(text: string): void;
@@ -32,7 +43,11 @@ export interface CliDependencies {
32
43
  plugin?(command: Extract<CliCommand, {
33
44
  kind: "plugin";
34
45
  }>): Promise<number>;
46
+ mcp?(command: Extract<CliCommand, {
47
+ kind: "mcp";
48
+ }>): Promise<number>;
35
49
  readonly version: string;
50
+ readonly locale?: Locale;
36
51
  }
37
52
  export declare function runCli(args: readonly string[], dependencies: CliDependencies): Promise<number>;
38
53
  //# sourceMappingURL=cli.d.ts.map
package/dist/cli.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,MAAM,GAAG,aAAa,CAAC;AAE1D,MAAM,MAAM,UAAU,GACnB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,GACnB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,SAAS,GAAG,MAAM,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,GAAG,QAAQ,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAC9G;IACA,IAAI,EAAE,KAAK,CAAC;IACZ,IAAI,EAAE,UAAU,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,IAAI,CAAC;IACvB,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,QAAQ,CAAC,EAAE,IAAI,CAAC;IAChB,cAAc,CAAC,EAAE,IAAI,CAAC;IACtB,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,YAAY,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AAEL,qBAAa,aAAc,SAAQ,KAAK;gBAC3B,OAAO,EAAE,MAAM;CAI3B;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,UAAU,CAkJhE;AAqBD,MAAM,WAAW,eAAe;IAC/B,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,UAAU,EAAE;QAAE,IAAI,EAAE,KAAK,CAAA;KAAE,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACpE,MAAM,CAAC,CAAC,OAAO,EAAE,OAAO,CAAC,UAAU,EAAE;QAAE,IAAI,EAAE,QAAQ,CAAA;KAAE,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC3E,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CACzB;AAED,wBAAsB,MAAM,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,YAAY,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAyBpG"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,MAAM,EAAa,MAAM,WAAW,CAAC;AAEnE,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,MAAM,GAAG,aAAa,CAAC;AAE1D,MAAM,MAAM,UAAU,GACnB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,GACnB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,SAAS,GAAG,MAAM,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,GAAG,QAAQ,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAC9G;IACA,IAAI,EAAE,KAAK,CAAC;IACZ,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,CAAC;IAC1C,KAAK,CAAC,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;IACrC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACzB,GAAG,CAAC,EAAE,MAAM,CAAC;CACZ,GACD;IACA,IAAI,EAAE,KAAK,CAAC;IACZ,IAAI,EAAE,UAAU,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,IAAI,CAAC;IACvB,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,QAAQ,CAAC,EAAE,IAAI,CAAC;IAChB,cAAc,CAAC,EAAE,IAAI,CAAC;IACtB,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,YAAY,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AAEL,qBAAa,aAAc,SAAQ,KAAK;gBAC3B,OAAO,EAAE,MAAM;CAI3B;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,UAAU,CAmJhE;AAmED,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAqB/C;AAED,MAAM,WAAW,eAAe;IAC/B,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,UAAU,EAAE;QAAE,IAAI,EAAE,KAAK,CAAA;KAAE,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACpE,MAAM,CAAC,CAAC,OAAO,EAAE,OAAO,CAAC,UAAU,EAAE;QAAE,IAAI,EAAE,QAAQ,CAAA;KAAE,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC3E,GAAG,CAAC,CAAC,OAAO,EAAE,OAAO,CAAC,UAAU,EAAE;QAAE,IAAI,EAAE,KAAK,CAAA;KAAE,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACrE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,wBAAsB,MAAM,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,YAAY,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CA4BpG"}
package/dist/cli.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { DEFAULT_LOCALE, translate } from "./i18n.js";
1
2
  export class CliUsageError extends Error {
2
3
  constructor(message) {
3
4
  super(message);
@@ -21,6 +22,8 @@ export function parseCliArgs(args) {
21
22
  throw new CliUsageError("Plugin command has invalid arguments.");
22
23
  return { kind: "plugin", action, ...(argument ? { argument } : {}) };
23
24
  }
25
+ if (args[0] === "mcp")
26
+ return parseMcpArgs(args.slice(1));
24
27
  const staticOption = args.find((argument) => ["-h", "--help", "-v", "--version"].includes(argument));
25
28
  if (staticOption !== undefined) {
26
29
  const kind = staticOption === "-h" || staticOption === "--help" ? "help" : "version";
@@ -143,24 +146,96 @@ export function parseCliArgs(args) {
143
146
  ...(projectTrust === undefined ? {} : { projectTrust }),
144
147
  };
145
148
  }
146
- const HELP_TEXT = `Usage: di-code [options] <prompt>
149
+ function parseMcpArgs(args) {
150
+ const action = args[0];
151
+ if (action !== "add" && action !== "list" && action !== "get" && action !== "remove")
152
+ throw new CliUsageError("MCP command must be add, list, get, or remove.");
153
+ let scope;
154
+ let transport;
155
+ const positional = [];
156
+ let separator = -1;
157
+ for (let index = 1; index < args.length; index++) {
158
+ const argument = args[index];
159
+ if (argument === "--") {
160
+ separator = index;
161
+ break;
162
+ }
163
+ if (argument === "--scope") {
164
+ const value = args[++index];
165
+ if (value !== "local" && value !== "project" && value !== "user")
166
+ throw new CliUsageError("Option --scope expects local, project, or user.");
167
+ if (scope !== undefined)
168
+ throw new CliUsageError("Option --scope may only be used once.");
169
+ scope = value;
170
+ continue;
171
+ }
172
+ if (argument === "--transport") {
173
+ const value = args[++index];
174
+ if (value !== "stdio" && value !== "http")
175
+ throw new CliUsageError("Option --transport expects stdio or http.");
176
+ if (transport !== undefined)
177
+ throw new CliUsageError("Option --transport may only be used once.");
178
+ transport = value;
179
+ continue;
180
+ }
181
+ if (argument.startsWith("-"))
182
+ throw new CliUsageError(`Unknown MCP option "${argument}".`);
183
+ positional.push(argument);
184
+ }
185
+ if (separator >= 0)
186
+ positional.push(...args.slice(separator + 1));
187
+ if (action === "list") {
188
+ if (transport !== undefined || positional.length > 0)
189
+ throw new CliUsageError("MCP list accepts only an optional --scope.");
190
+ return { kind: "mcp", action, ...(scope ? { scope } : {}) };
191
+ }
192
+ if (action === "get" || action === "remove") {
193
+ if (transport !== undefined || positional.length !== 1 || positional[0].trim() === "")
194
+ throw new CliUsageError(`MCP ${action} requires exactly one server id.`);
195
+ return { kind: "mcp", action, serverId: positional[0], ...(scope ? { scope } : {}) };
196
+ }
197
+ const selectedTransport = transport ?? (separator >= 0 ? "stdio" : undefined);
198
+ if (selectedTransport === undefined)
199
+ throw new CliUsageError("MCP add requires <server-id> -- <command> [args...] or --transport http <server-id> <url>.");
200
+ if (selectedTransport === "stdio") {
201
+ if (positional.length < 2 || separator < 0)
202
+ throw new CliUsageError("MCP stdio add requires <server-id> -- <command> [args...].");
203
+ return {
204
+ kind: "mcp",
205
+ action,
206
+ transport: "stdio",
207
+ serverId: positional[0],
208
+ command: positional[1],
209
+ ...(positional.length > 2 ? { args: positional.slice(2) } : {}),
210
+ ...(scope ? { scope } : {}),
211
+ };
212
+ }
213
+ if (separator >= 0 || positional.length !== 2)
214
+ throw new CliUsageError("MCP HTTP add requires <server-id> <url>.");
215
+ return { kind: "mcp", action, transport, serverId: positional[0], url: positional[1], ...(scope ? { scope } : {}) };
216
+ }
217
+ export function helpText(locale) {
218
+ const t = (key) => translate(locale, key);
219
+ return `${t("usage")}
147
220
 
148
- Options:
149
- -p, --print Print only the final assistant text (default)
150
- --mode <mode> Output mode: print, json, or interactive
151
- --interactive Start interactive terminal mode
152
- --continue, -c Continue the most recently modified session
153
- --session <path> Create or resume a JSONL session (relative to the work root)
154
- --image <path> Attach a local PNG, JPEG, WebP, or GIF image (repeatable)
155
- --skill <path> Add a SKILL.md file or skill directory (repeatable)
156
- --no-skills Disable all Skill loading
157
- --no-context-files Disable AGENTS.md discovery and loading
158
- --trust-project Persist trust for project-local Skill discovery
159
- --untrust-project Persist denial for project-local Skill discovery
160
- plugin <action> Install, list, enable, disable, update, or remove a plugin
161
- -h, --help Show help
162
- -v, --version Show version
221
+ ${t("options")}
222
+ -p, --print ${t("print")}
223
+ --mode <mode> ${t("mode")}
224
+ --interactive ${t("interactive")}
225
+ --continue, -c ${t("continueSession")}
226
+ --session <path> ${t("session")}
227
+ --image <path> ${t("image")}
228
+ --skill <path> ${t("skill")}
229
+ --no-skills ${t("noSkills")}
230
+ --no-context-files ${t("noContextFiles")}
231
+ --trust-project ${t("trustProject")}
232
+ --untrust-project ${t("untrustProject")}
233
+ plugin <action> ${t("plugin")}
234
+ mcp add|list|get|remove ${t("mcp")}
235
+ -h, --help ${t("help")}
236
+ -v, --version ${t("version")}
163
237
  `;
238
+ }
164
239
  export async function runCli(args, dependencies) {
165
240
  let command;
166
241
  try {
@@ -175,12 +250,16 @@ export async function runCli(args, dependencies) {
175
250
  }
176
251
  switch (command.kind) {
177
252
  case "help":
178
- dependencies.stdout(HELP_TEXT);
253
+ dependencies.stdout(helpText(dependencies.locale ?? DEFAULT_LOCALE));
179
254
  return 0;
180
255
  case "plugin":
181
256
  if (!dependencies.plugin)
182
257
  throw new Error("Plugin command handler is unavailable.");
183
258
  return dependencies.plugin(command);
259
+ case "mcp":
260
+ if (!dependencies.mcp)
261
+ throw new Error("MCP command handler is unavailable.");
262
+ return dependencies.mcp(command);
184
263
  case "version":
185
264
  dependencies.stdout(`${dependencies.version}\n`);
186
265
  return 0;
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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","sourcesContent":["export type OutputMode = \"print\" | \"json\" | \"interactive\";\n\nexport type CliCommand =\n\t| { kind: \"help\" }\n\t| { kind: \"version\" }\n\t| { kind: \"plugin\"; action: \"install\" | \"list\" | \"enable\" | \"disable\" | \"update\" | \"remove\"; argument?: string }\n\t| {\n\t\t\tkind: \"run\";\n\t\t\tmode: OutputMode;\n\t\t\tprompt: string;\n\t\t\tsessionPath?: string;\n\t\t\tcontinueSession?: true;\n\t\t\timagePaths?: readonly string[];\n\t\t\tnoSkills?: true;\n\t\t\tnoContextFiles?: true;\n\t\t\tskillPaths?: readonly string[];\n\t\t\tprojectTrust?: boolean;\n\t };\n\nexport class CliUsageError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"CliUsageError\";\n\t}\n}\n\nexport function parseCliArgs(args: readonly string[]): CliCommand {\n\tif (args[0] === \"plugin\") {\n\t\tconst action = args[1];\n\t\tif (\n\t\t\taction !== \"install\" &&\n\t\t\taction !== \"list\" &&\n\t\t\taction !== \"enable\" &&\n\t\t\taction !== \"disable\" &&\n\t\t\taction !== \"update\" &&\n\t\t\taction !== \"remove\"\n\t\t)\n\t\t\tthrow new CliUsageError(\"Plugin command must be install, list, enable, disable, update, or remove.\");\n\t\tconst argument = args[2];\n\t\tif (\n\t\t\targs.length > 3 ||\n\t\t\t(action !== \"list\" && (argument === undefined || argument.trim() === \"\")) ||\n\t\t\t(action === \"list\" && argument !== undefined)\n\t\t)\n\t\t\tthrow new CliUsageError(\"Plugin command has invalid arguments.\");\n\t\treturn { kind: \"plugin\", action, ...(argument ? { argument } : {}) };\n\t}\n\tconst staticOption = args.find((argument) => [\"-h\", \"--help\", \"-v\", \"--version\"].includes(argument));\n\tif (staticOption !== undefined) {\n\t\tconst kind = staticOption === \"-h\" || staticOption === \"--help\" ? \"help\" : \"version\";\n\t\tif (args.length !== 1) {\n\t\t\tthrow new CliUsageError(`--${kind} must be used on its own.`);\n\t\t}\n\t\treturn { kind };\n\t}\n\n\tlet mode: OutputMode = \"print\";\n\tlet printAlias = false;\n\tlet sessionPath: string | undefined;\n\tlet continueSession = false;\n\tlet noSkills = false;\n\tlet noContextFiles = false;\n\tlet projectTrust: boolean | undefined;\n\tconst skillPaths: string[] = [];\n\tconst imagePaths: string[] = [];\n\tconst promptParts: string[] = [];\n\n\tfor (let index = 0; index < args.length; index++) {\n\t\tconst argument = args[index];\n\t\tif (argument === \"-p\" || argument === \"--print\") {\n\t\t\tprintAlias = true;\n\t\t\tcontinue;\n\t\t}\n\t\tif (argument === \"--interactive\") {\n\t\t\tmode = \"interactive\";\n\t\t\tcontinue;\n\t\t}\n\t\tif (argument === \"-c\" || argument === \"--continue\") {\n\t\t\tcontinueSession = true;\n\t\t\tcontinue;\n\t\t}\n\t\tif (argument === \"--no-skills\") {\n\t\t\tnoSkills = true;\n\t\t\tcontinue;\n\t\t}\n\t\tif (argument === \"--no-context-files\") {\n\t\t\tnoContextFiles = true;\n\t\t\tcontinue;\n\t\t}\n\t\tif (argument === \"--trust-project\" || argument === \"--untrust-project\") {\n\t\t\tconst nextTrust = argument === \"--trust-project\";\n\t\t\tif (projectTrust !== undefined && projectTrust !== nextTrust) {\n\t\t\t\tthrow new CliUsageError(\"Cannot combine --trust-project with --untrust-project.\");\n\t\t\t}\n\t\t\tprojectTrust = nextTrust;\n\t\t\tcontinue;\n\t\t}\n\t\tif (argument === \"--skill\") {\n\t\t\tconst value = args[index + 1];\n\t\t\tif (value === undefined || value.trim().length === 0) {\n\t\t\t\tthrow new CliUsageError(\"Option --skill requires a non-empty value.\");\n\t\t\t}\n\t\t\tskillPaths.push(value);\n\t\t\tindex++;\n\t\t\tcontinue;\n\t\t}\n\t\tif (argument === \"--image\") {\n\t\t\tconst value = args[index + 1];\n\t\t\tif (value === undefined || value.trim().length === 0) {\n\t\t\t\tthrow new CliUsageError(\"Option --image requires a non-empty value.\");\n\t\t\t}\n\t\t\timagePaths.push(value);\n\t\t\tindex++;\n\t\t\tcontinue;\n\t\t}\n\t\tif (argument === \"--mode\") {\n\t\t\tconst value = args[index + 1];\n\t\t\tif (value === undefined) {\n\t\t\t\tthrow new CliUsageError(\"Option --mode requires a value.\");\n\t\t\t}\n\t\t\tif (value !== \"print\" && value !== \"json\" && value !== \"interactive\") {\n\t\t\t\tthrow new CliUsageError(`Unsupported mode \"${value}\". Expected print, json, or interactive.`);\n\t\t\t}\n\t\t\tmode = value;\n\t\t\tindex++;\n\t\t\tcontinue;\n\t\t}\n\t\tif (argument === \"--session\") {\n\t\t\tconst value = args[index + 1];\n\t\t\tif (value === undefined) {\n\t\t\t\tthrow new CliUsageError(\"Option --session requires a value.\");\n\t\t\t}\n\t\t\tif (value.trim().length === 0) {\n\t\t\t\tthrow new CliUsageError(\"Option --session requires a non-empty value.\");\n\t\t\t}\n\t\t\tsessionPath = value;\n\t\t\tindex++;\n\t\t\tcontinue;\n\t\t}\n\t\tif (argument?.startsWith(\"-\")) {\n\t\t\tthrow new CliUsageError(`Unknown option \"${argument}\".`);\n\t\t}\n\t\tif (argument !== undefined) {\n\t\t\tpromptParts.push(argument);\n\t\t}\n\t}\n\n\tif (printAlias && mode !== \"print\") {\n\t\tthrow new CliUsageError(`Cannot combine --print with --mode ${mode}.`);\n\t}\n\tif (continueSession && sessionPath !== undefined) {\n\t\tthrow new CliUsageError(\"Cannot combine --continue with --session.\");\n\t}\n\tif (mode === \"interactive\" && imagePaths.length > 0) {\n\t\tthrow new CliUsageError(\"--image is not available in interactive mode.\");\n\t}\n\tif (promptParts.length === 0 && mode !== \"interactive\") {\n\t\tthrow new CliUsageError(\"A prompt is required.\");\n\t}\n\n\treturn {\n\t\tkind: \"run\",\n\t\tmode,\n\t\tprompt: promptParts.join(\" \"),\n\t\t...(sessionPath ? { sessionPath } : {}),\n\t\t...(continueSession ? { continueSession: true as const } : {}),\n\t\t...(noSkills ? { noSkills: true as const } : {}),\n\t\t...(noContextFiles ? { noContextFiles: true as const } : {}),\n\t\t...(skillPaths.length > 0 ? { skillPaths } : {}),\n\t\t...(imagePaths.length > 0 ? { imagePaths } : {}),\n\t\t...(projectTrust === undefined ? {} : { projectTrust }),\n\t};\n}\n\nconst HELP_TEXT = `Usage: di-code [options] <prompt>\n\nOptions:\n -p, --print Print only the final assistant text (default)\n --mode <mode> Output mode: print, json, or interactive\n --interactive Start interactive terminal mode\n --continue, -c Continue the most recently modified session\n --session <path> Create or resume a JSONL session (relative to the work root)\n --image <path> Attach a local PNG, JPEG, WebP, or GIF image (repeatable)\n --skill <path> Add a SKILL.md file or skill directory (repeatable)\n --no-skills Disable all Skill loading\n --no-context-files Disable AGENTS.md discovery and loading\n --trust-project Persist trust for project-local Skill discovery\n --untrust-project Persist denial for project-local Skill discovery\n plugin <action> Install, list, enable, disable, update, or remove a plugin\n -h, --help Show help\n -v, --version Show version\n`;\n\nexport interface CliDependencies {\n\tstdout(text: string): void;\n\tstderr(text: string): void;\n\trun(command: Extract<CliCommand, { kind: \"run\" }>): Promise<number>;\n\tplugin?(command: Extract<CliCommand, { kind: \"plugin\" }>): Promise<number>;\n\treadonly version: string;\n}\n\nexport async function runCli(args: readonly string[], dependencies: CliDependencies): Promise<number> {\n\tlet command: CliCommand;\n\ttry {\n\t\tcommand = parseCliArgs(args);\n\t} catch (cause) {\n\t\tif (cause instanceof CliUsageError) {\n\t\t\tdependencies.stderr(`${cause.message}\\n`);\n\t\t\treturn 1;\n\t\t}\n\t\tthrow cause;\n\t}\n\n\tswitch (command.kind) {\n\t\tcase \"help\":\n\t\t\tdependencies.stdout(HELP_TEXT);\n\t\t\treturn 0;\n\t\tcase \"plugin\":\n\t\t\tif (!dependencies.plugin) throw new Error(\"Plugin command handler is unavailable.\");\n\t\t\treturn dependencies.plugin(command);\n\t\tcase \"version\":\n\t\t\tdependencies.stdout(`${dependencies.version}\\n`);\n\t\t\treturn 0;\n\t\tcase \"run\":\n\t\t\treturn dependencies.run(command);\n\t}\n}\n"]}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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","sourcesContent":["import { DEFAULT_LOCALE, type Locale, translate } from \"./i18n.ts\";\n\nexport type OutputMode = \"print\" | \"json\" | \"interactive\";\n\nexport type CliCommand =\n\t| { kind: \"help\" }\n\t| { kind: \"version\" }\n\t| { kind: \"plugin\"; action: \"install\" | \"list\" | \"enable\" | \"disable\" | \"update\" | \"remove\"; argument?: string }\n\t| {\n\t\t\tkind: \"mcp\";\n\t\t\taction: \"add\" | \"list\" | \"get\" | \"remove\";\n\t\t\tscope?: \"local\" | \"project\" | \"user\";\n\t\t\tserverId?: string;\n\t\t\ttransport?: \"stdio\" | \"http\";\n\t\t\tcommand?: string;\n\t\t\targs?: readonly string[];\n\t\t\turl?: string;\n\t }\n\t| {\n\t\t\tkind: \"run\";\n\t\t\tmode: OutputMode;\n\t\t\tprompt: string;\n\t\t\tsessionPath?: string;\n\t\t\tcontinueSession?: true;\n\t\t\timagePaths?: readonly string[];\n\t\t\tnoSkills?: true;\n\t\t\tnoContextFiles?: true;\n\t\t\tskillPaths?: readonly string[];\n\t\t\tprojectTrust?: boolean;\n\t };\n\nexport class CliUsageError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"CliUsageError\";\n\t}\n}\n\nexport function parseCliArgs(args: readonly string[]): CliCommand {\n\tif (args[0] === \"plugin\") {\n\t\tconst action = args[1];\n\t\tif (\n\t\t\taction !== \"install\" &&\n\t\t\taction !== \"list\" &&\n\t\t\taction !== \"enable\" &&\n\t\t\taction !== \"disable\" &&\n\t\t\taction !== \"update\" &&\n\t\t\taction !== \"remove\"\n\t\t)\n\t\t\tthrow new CliUsageError(\"Plugin command must be install, list, enable, disable, update, or remove.\");\n\t\tconst argument = args[2];\n\t\tif (\n\t\t\targs.length > 3 ||\n\t\t\t(action !== \"list\" && (argument === undefined || argument.trim() === \"\")) ||\n\t\t\t(action === \"list\" && argument !== undefined)\n\t\t)\n\t\t\tthrow new CliUsageError(\"Plugin command has invalid arguments.\");\n\t\treturn { kind: \"plugin\", action, ...(argument ? { argument } : {}) };\n\t}\n\tif (args[0] === \"mcp\") return parseMcpArgs(args.slice(1));\n\tconst staticOption = args.find((argument) => [\"-h\", \"--help\", \"-v\", \"--version\"].includes(argument));\n\tif (staticOption !== undefined) {\n\t\tconst kind = staticOption === \"-h\" || staticOption === \"--help\" ? \"help\" : \"version\";\n\t\tif (args.length !== 1) {\n\t\t\tthrow new CliUsageError(`--${kind} must be used on its own.`);\n\t\t}\n\t\treturn { kind };\n\t}\n\n\tlet mode: OutputMode = \"print\";\n\tlet printAlias = false;\n\tlet sessionPath: string | undefined;\n\tlet continueSession = false;\n\tlet noSkills = false;\n\tlet noContextFiles = false;\n\tlet projectTrust: boolean | undefined;\n\tconst skillPaths: string[] = [];\n\tconst imagePaths: string[] = [];\n\tconst promptParts: string[] = [];\n\n\tfor (let index = 0; index < args.length; index++) {\n\t\tconst argument = args[index];\n\t\tif (argument === \"-p\" || argument === \"--print\") {\n\t\t\tprintAlias = true;\n\t\t\tcontinue;\n\t\t}\n\t\tif (argument === \"--interactive\") {\n\t\t\tmode = \"interactive\";\n\t\t\tcontinue;\n\t\t}\n\t\tif (argument === \"-c\" || argument === \"--continue\") {\n\t\t\tcontinueSession = true;\n\t\t\tcontinue;\n\t\t}\n\t\tif (argument === \"--no-skills\") {\n\t\t\tnoSkills = true;\n\t\t\tcontinue;\n\t\t}\n\t\tif (argument === \"--no-context-files\") {\n\t\t\tnoContextFiles = true;\n\t\t\tcontinue;\n\t\t}\n\t\tif (argument === \"--trust-project\" || argument === \"--untrust-project\") {\n\t\t\tconst nextTrust = argument === \"--trust-project\";\n\t\t\tif (projectTrust !== undefined && projectTrust !== nextTrust) {\n\t\t\t\tthrow new CliUsageError(\"Cannot combine --trust-project with --untrust-project.\");\n\t\t\t}\n\t\t\tprojectTrust = nextTrust;\n\t\t\tcontinue;\n\t\t}\n\t\tif (argument === \"--skill\") {\n\t\t\tconst value = args[index + 1];\n\t\t\tif (value === undefined || value.trim().length === 0) {\n\t\t\t\tthrow new CliUsageError(\"Option --skill requires a non-empty value.\");\n\t\t\t}\n\t\t\tskillPaths.push(value);\n\t\t\tindex++;\n\t\t\tcontinue;\n\t\t}\n\t\tif (argument === \"--image\") {\n\t\t\tconst value = args[index + 1];\n\t\t\tif (value === undefined || value.trim().length === 0) {\n\t\t\t\tthrow new CliUsageError(\"Option --image requires a non-empty value.\");\n\t\t\t}\n\t\t\timagePaths.push(value);\n\t\t\tindex++;\n\t\t\tcontinue;\n\t\t}\n\t\tif (argument === \"--mode\") {\n\t\t\tconst value = args[index + 1];\n\t\t\tif (value === undefined) {\n\t\t\t\tthrow new CliUsageError(\"Option --mode requires a value.\");\n\t\t\t}\n\t\t\tif (value !== \"print\" && value !== \"json\" && value !== \"interactive\") {\n\t\t\t\tthrow new CliUsageError(`Unsupported mode \"${value}\". Expected print, json, or interactive.`);\n\t\t\t}\n\t\t\tmode = value;\n\t\t\tindex++;\n\t\t\tcontinue;\n\t\t}\n\t\tif (argument === \"--session\") {\n\t\t\tconst value = args[index + 1];\n\t\t\tif (value === undefined) {\n\t\t\t\tthrow new CliUsageError(\"Option --session requires a value.\");\n\t\t\t}\n\t\t\tif (value.trim().length === 0) {\n\t\t\t\tthrow new CliUsageError(\"Option --session requires a non-empty value.\");\n\t\t\t}\n\t\t\tsessionPath = value;\n\t\t\tindex++;\n\t\t\tcontinue;\n\t\t}\n\t\tif (argument?.startsWith(\"-\")) {\n\t\t\tthrow new CliUsageError(`Unknown option \"${argument}\".`);\n\t\t}\n\t\tif (argument !== undefined) {\n\t\t\tpromptParts.push(argument);\n\t\t}\n\t}\n\n\tif (printAlias && mode !== \"print\") {\n\t\tthrow new CliUsageError(`Cannot combine --print with --mode ${mode}.`);\n\t}\n\tif (continueSession && sessionPath !== undefined) {\n\t\tthrow new CliUsageError(\"Cannot combine --continue with --session.\");\n\t}\n\tif (mode === \"interactive\" && imagePaths.length > 0) {\n\t\tthrow new CliUsageError(\"--image is not available in interactive mode.\");\n\t}\n\tif (promptParts.length === 0 && mode !== \"interactive\") {\n\t\tthrow new CliUsageError(\"A prompt is required.\");\n\t}\n\n\treturn {\n\t\tkind: \"run\",\n\t\tmode,\n\t\tprompt: promptParts.join(\" \"),\n\t\t...(sessionPath ? { sessionPath } : {}),\n\t\t...(continueSession ? { continueSession: true as const } : {}),\n\t\t...(noSkills ? { noSkills: true as const } : {}),\n\t\t...(noContextFiles ? { noContextFiles: true as const } : {}),\n\t\t...(skillPaths.length > 0 ? { skillPaths } : {}),\n\t\t...(imagePaths.length > 0 ? { imagePaths } : {}),\n\t\t...(projectTrust === undefined ? {} : { projectTrust }),\n\t};\n}\n\nfunction parseMcpArgs(args: readonly string[]): Extract<CliCommand, { kind: \"mcp\" }> {\n\tconst action = args[0];\n\tif (action !== \"add\" && action !== \"list\" && action !== \"get\" && action !== \"remove\")\n\t\tthrow new CliUsageError(\"MCP command must be add, list, get, or remove.\");\n\tlet scope: \"local\" | \"project\" | \"user\" | undefined;\n\tlet transport: \"stdio\" | \"http\" | undefined;\n\tconst positional: string[] = [];\n\tlet separator = -1;\n\tfor (let index = 1; index < args.length; index++) {\n\t\tconst argument = args[index];\n\t\tif (argument === \"--\") {\n\t\t\tseparator = index;\n\t\t\tbreak;\n\t\t}\n\t\tif (argument === \"--scope\") {\n\t\t\tconst value = args[++index];\n\t\t\tif (value !== \"local\" && value !== \"project\" && value !== \"user\")\n\t\t\t\tthrow new CliUsageError(\"Option --scope expects local, project, or user.\");\n\t\t\tif (scope !== undefined) throw new CliUsageError(\"Option --scope may only be used once.\");\n\t\t\tscope = value;\n\t\t\tcontinue;\n\t\t}\n\t\tif (argument === \"--transport\") {\n\t\t\tconst value = args[++index];\n\t\t\tif (value !== \"stdio\" && value !== \"http\") throw new CliUsageError(\"Option --transport expects stdio or http.\");\n\t\t\tif (transport !== undefined) throw new CliUsageError(\"Option --transport may only be used once.\");\n\t\t\ttransport = value;\n\t\t\tcontinue;\n\t\t}\n\t\tif (argument.startsWith(\"-\")) throw new CliUsageError(`Unknown MCP option \"${argument}\".`);\n\t\tpositional.push(argument);\n\t}\n\tif (separator >= 0) positional.push(...args.slice(separator + 1));\n\tif (action === \"list\") {\n\t\tif (transport !== undefined || positional.length > 0)\n\t\t\tthrow new CliUsageError(\"MCP list accepts only an optional --scope.\");\n\t\treturn { kind: \"mcp\", action, ...(scope ? { scope } : {}) };\n\t}\n\tif (action === \"get\" || action === \"remove\") {\n\t\tif (transport !== undefined || positional.length !== 1 || positional[0].trim() === \"\")\n\t\t\tthrow new CliUsageError(`MCP ${action} requires exactly one server id.`);\n\t\treturn { kind: \"mcp\", action, serverId: positional[0], ...(scope ? { scope } : {}) };\n\t}\n\tconst selectedTransport = transport ?? (separator >= 0 ? \"stdio\" : undefined);\n\tif (selectedTransport === undefined)\n\t\tthrow new CliUsageError(\n\t\t\t\"MCP add requires <server-id> -- <command> [args...] or --transport http <server-id> <url>.\",\n\t\t);\n\tif (selectedTransport === \"stdio\") {\n\t\tif (positional.length < 2 || separator < 0)\n\t\t\tthrow new CliUsageError(\"MCP stdio add requires <server-id> -- <command> [args...].\");\n\t\treturn {\n\t\t\tkind: \"mcp\",\n\t\t\taction,\n\t\t\ttransport: \"stdio\",\n\t\t\tserverId: positional[0],\n\t\t\tcommand: positional[1],\n\t\t\t...(positional.length > 2 ? { args: positional.slice(2) } : {}),\n\t\t\t...(scope ? { scope } : {}),\n\t\t};\n\t}\n\tif (separator >= 0 || positional.length !== 2) throw new CliUsageError(\"MCP HTTP add requires <server-id> <url>.\");\n\treturn { kind: \"mcp\", action, transport, serverId: positional[0], url: positional[1], ...(scope ? { scope } : {}) };\n}\n\nexport function helpText(locale: Locale): string {\n\tconst t = (key: string) => translate(locale, key);\n\treturn `${t(\"usage\")}\n\n${t(\"options\")}\n -p, --print ${t(\"print\")}\n --mode <mode> ${t(\"mode\")}\n --interactive ${t(\"interactive\")}\n --continue, -c ${t(\"continueSession\")}\n --session <path> ${t(\"session\")}\n --image <path> ${t(\"image\")}\n --skill <path> ${t(\"skill\")}\n --no-skills ${t(\"noSkills\")}\n --no-context-files ${t(\"noContextFiles\")}\n --trust-project ${t(\"trustProject\")}\n --untrust-project ${t(\"untrustProject\")}\n plugin <action> ${t(\"plugin\")}\n mcp add|list|get|remove ${t(\"mcp\")}\n -h, --help ${t(\"help\")}\n -v, --version ${t(\"version\")}\n`;\n}\n\nexport interface CliDependencies {\n\tstdout(text: string): void;\n\tstderr(text: string): void;\n\trun(command: Extract<CliCommand, { kind: \"run\" }>): Promise<number>;\n\tplugin?(command: Extract<CliCommand, { kind: \"plugin\" }>): Promise<number>;\n\tmcp?(command: Extract<CliCommand, { kind: \"mcp\" }>): Promise<number>;\n\treadonly version: string;\n\treadonly locale?: Locale;\n}\n\nexport async function runCli(args: readonly string[], dependencies: CliDependencies): Promise<number> {\n\tlet command: CliCommand;\n\ttry {\n\t\tcommand = parseCliArgs(args);\n\t} catch (cause) {\n\t\tif (cause instanceof CliUsageError) {\n\t\t\tdependencies.stderr(`${cause.message}\\n`);\n\t\t\treturn 1;\n\t\t}\n\t\tthrow cause;\n\t}\n\n\tswitch (command.kind) {\n\t\tcase \"help\":\n\t\t\tdependencies.stdout(helpText(dependencies.locale ?? DEFAULT_LOCALE));\n\t\t\treturn 0;\n\t\tcase \"plugin\":\n\t\t\tif (!dependencies.plugin) throw new Error(\"Plugin command handler is unavailable.\");\n\t\t\treturn dependencies.plugin(command);\n\t\tcase \"mcp\":\n\t\t\tif (!dependencies.mcp) throw new Error(\"MCP command handler is unavailable.\");\n\t\t\treturn dependencies.mcp(command);\n\t\tcase \"version\":\n\t\t\tdependencies.stdout(`${dependencies.version}\\n`);\n\t\t\treturn 0;\n\t\tcase \"run\":\n\t\t\treturn dependencies.run(command);\n\t}\n}\n"]}
@@ -1,10 +1,10 @@
1
1
  import type { ImageContent } from "@di-code/ai";
2
2
  /** Reads a native clipboard image when the optional platform package is available. */
3
3
  export declare function readClipboardImage(): Promise<ImageContent | null>;
4
- export declare function clipboardImageDirectory(root: string): string;
4
+ export declare function clipboardImageDirectory(agentDir: string, root: string): string;
5
5
  export declare function isClipboardImagePath(path: string, directory: string): boolean;
6
- /** Removes generated clipboard images that were left by an older process. */
7
- export declare function cleanupStaleClipboardImages(root: string, maxAgeMs?: number): Promise<void>;
6
+ /** Removes generated clipboard images that were left by older processes for this workspace. */
7
+ export declare function cleanupStaleClipboardImages(agentDir: string, root: string, maxAgeMs?: number): Promise<void>;
8
8
  export declare function removeClipboardImage(path: string, directory: string): Promise<void>;
9
9
  /** Writes one clipboard image to a temporary file, matching Pi's editor flow. */
10
10
  export declare function writeImageContentToTempFile(image: ImageContent, directory?: string): Promise<string>;
@@ -1 +1 @@
1
- {"version":3,"file":"clipboard-image.d.ts","sourceRoot":"","sources":["../../src/core/clipboard-image.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAsBhD,sFAAsF;AACtF,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAMvE;AAeD,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE5D;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAG7E;AAED,6EAA6E;AAC7E,wBAAsB,2BAA2B,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,SAAuB,GAAG,OAAO,CAAC,IAAI,CAAC,CAsB9G;AAED,wBAAsB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAOzF;AAED,iFAAiF;AACjF,wBAAsB,2BAA2B,CAAC,KAAK,EAAE,YAAY,EAAE,SAAS,SAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAM5G;AAED,kGAAkG;AAClG,wBAAsB,sBAAsB,CAAC,SAAS,SAAW,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAGzF"}
1
+ {"version":3,"file":"clipboard-image.d.ts","sourceRoot":"","sources":["../../src/core/clipboard-image.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAuBhD,sFAAsF;AACtF,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAMvE;AAeD,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAE9E;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAG7E;AAED,+FAA+F;AAC/F,wBAAsB,2BAA2B,CAChD,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,QAAQ,SAAuB,GAC7B,OAAO,CAAC,IAAI,CAAC,CAkCf;AAED,wBAAsB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAOzF;AAED,iFAAiF;AACjF,wBAAsB,2BAA2B,CAAC,KAAK,EAAE,YAAY,EAAE,SAAS,SAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAM5G;AAED,kGAAkG;AAClG,wBAAsB,sBAAsB,CAAC,SAAS,SAAW,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAGzF"}