@jingyi0605/codingns 0.3.5 → 0.4.0

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 (255) hide show
  1. package/README.md +16 -0
  2. package/bin/codingns.mjs +1369 -10
  3. package/dist/public/assets/{TerminalPage-CgrfstRm.js → TerminalPage-6jHZV9Mh.js} +17 -17
  4. package/dist/public/assets/index-CSVhg7I8.js +123 -0
  5. package/dist/public/assets/index-Ce1VX19m.css +1 -0
  6. package/dist/public/index.html +2 -2
  7. package/dist/server/config/opencode-base-url-resolver.d.ts +7 -0
  8. package/dist/server/config/opencode-base-url-resolver.js +48 -11
  9. package/dist/server/config/opencode-base-url-resolver.js.map +1 -1
  10. package/dist/server/config/opencode-system-probe-helper-client.d.ts +4 -0
  11. package/dist/server/config/opencode-system-probe-helper-client.js +29 -0
  12. package/dist/server/config/opencode-system-probe-helper-client.js.map +1 -1
  13. package/dist/server/config/opencode-system-probe-helper-process.d.ts +12 -0
  14. package/dist/server/config/opencode-system-probe-helper-process.js +34 -7
  15. package/dist/server/config/opencode-system-probe-helper-process.js.map +1 -1
  16. package/dist/server/modules/assistant-capability/assistant-capability-controller.d.ts +317 -0
  17. package/dist/server/modules/assistant-capability/assistant-capability-controller.js +549 -1
  18. package/dist/server/modules/assistant-capability/assistant-capability-controller.js.map +1 -1
  19. package/dist/server/modules/assistant-capability/assistant-capability-service.d.ts +330 -2
  20. package/dist/server/modules/assistant-capability/assistant-capability-service.js +958 -3
  21. package/dist/server/modules/assistant-capability/assistant-capability-service.js.map +1 -1
  22. package/dist/server/modules/butler/assistant-automation-service.d.ts +110 -0
  23. package/dist/server/modules/butler/assistant-automation-service.js +786 -0
  24. package/dist/server/modules/butler/assistant-automation-service.js.map +1 -0
  25. package/dist/server/modules/butler/assistant-automation-trigger.d.ts +94 -0
  26. package/dist/server/modules/butler/assistant-automation-trigger.js +400 -0
  27. package/dist/server/modules/butler/assistant-automation-trigger.js.map +1 -0
  28. package/dist/server/modules/butler/assistant-sandbox-service.d.ts +55 -0
  29. package/dist/server/modules/butler/assistant-sandbox-service.js +266 -0
  30. package/dist/server/modules/butler/assistant-sandbox-service.js.map +1 -0
  31. package/dist/server/modules/butler/butler-action-context-service.d.ts +4 -1
  32. package/dist/server/modules/butler/butler-action-context-service.js +8 -2
  33. package/dist/server/modules/butler/butler-action-context-service.js.map +1 -1
  34. package/dist/server/modules/butler/butler-control-session-service.d.ts +8 -1
  35. package/dist/server/modules/butler/butler-control-session-service.js +154 -40
  36. package/dist/server/modules/butler/butler-control-session-service.js.map +1 -1
  37. package/dist/server/modules/butler/butler-control-timer-scheduler.d.ts +32 -0
  38. package/dist/server/modules/butler/butler-control-timer-scheduler.js +93 -0
  39. package/dist/server/modules/butler/butler-control-timer-scheduler.js.map +1 -0
  40. package/dist/server/modules/butler/butler-control-timer-service.d.ts +42 -0
  41. package/dist/server/modules/butler/butler-control-timer-service.js +132 -0
  42. package/dist/server/modules/butler/butler-control-timer-service.js.map +1 -0
  43. package/dist/server/modules/butler/butler-controller.d.ts +42 -2
  44. package/dist/server/modules/butler/butler-controller.js +79 -12
  45. package/dist/server/modules/butler/butler-controller.js.map +1 -1
  46. package/dist/server/modules/butler/butler-follow-up-service.d.ts +9 -1
  47. package/dist/server/modules/butler/butler-follow-up-service.js +273 -181
  48. package/dist/server/modules/butler/butler-follow-up-service.js.map +1 -1
  49. package/dist/server/modules/butler/butler-inbox-analysis-service.d.ts +4 -1
  50. package/dist/server/modules/butler/butler-inbox-analysis-service.js +18 -4
  51. package/dist/server/modules/butler/butler-inbox-analysis-service.js.map +1 -1
  52. package/dist/server/modules/butler/butler-inbox-instruction-adapter.js +7 -6
  53. package/dist/server/modules/butler/butler-inbox-instruction-adapter.js.map +1 -1
  54. package/dist/server/modules/butler/butler-profile-service.js +2 -5
  55. package/dist/server/modules/butler/butler-profile-service.js.map +1 -1
  56. package/dist/server/modules/butler/butler-project-service.d.ts +3 -1
  57. package/dist/server/modules/butler/butler-project-service.js +7 -1
  58. package/dist/server/modules/butler/butler-project-service.js.map +1 -1
  59. package/dist/server/modules/butler/butler-session-service.d.ts +3 -1
  60. package/dist/server/modules/butler/butler-session-service.js +12 -1
  61. package/dist/server/modules/butler/butler-session-service.js.map +1 -1
  62. package/dist/server/modules/butler/butler-session-summary-service.js +2 -1
  63. package/dist/server/modules/butler/butler-session-summary-service.js.map +1 -1
  64. package/dist/server/modules/butler/butler-workspace-context.d.ts +3 -0
  65. package/dist/server/modules/butler/butler-workspace-context.js +182 -51
  66. package/dist/server/modules/butler/butler-workspace-context.js.map +1 -1
  67. package/dist/server/modules/butler/patrol-execution-service.js +2 -1
  68. package/dist/server/modules/butler/patrol-execution-service.js.map +1 -1
  69. package/dist/server/modules/butler/provider-adapter-registry.d.ts +3 -0
  70. package/dist/server/modules/butler/provider-adapter-registry.js +18 -1
  71. package/dist/server/modules/butler/provider-adapter-registry.js.map +1 -1
  72. package/dist/server/modules/butler/verification-run-service.d.ts +9 -2
  73. package/dist/server/modules/butler/verification-run-service.js +188 -34
  74. package/dist/server/modules/butler/verification-run-service.js.map +1 -1
  75. package/dist/server/modules/debug-target/debug-target-controller.d.ts +13 -0
  76. package/dist/server/modules/debug-target/debug-target-controller.js +77 -2
  77. package/dist/server/modules/debug-target/debug-target-controller.js.map +1 -1
  78. package/dist/server/modules/debug-target/debug-target-service.d.ts +17 -3
  79. package/dist/server/modules/debug-target/debug-target-service.js +696 -98
  80. package/dist/server/modules/debug-target/debug-target-service.js.map +1 -1
  81. package/dist/server/modules/git/git-command-helper-client.d.ts +3 -0
  82. package/dist/server/modules/git/git-command-helper-client.js +71 -29
  83. package/dist/server/modules/git/git-command-helper-client.js.map +1 -1
  84. package/dist/server/modules/git/git-command-helper-process.js +62 -9
  85. package/dist/server/modules/git/git-command-helper-process.js.map +1 -1
  86. package/dist/server/modules/git/git-command-runner.d.ts +1 -0
  87. package/dist/server/modules/git/git-command-runner.js +44 -1
  88. package/dist/server/modules/git/git-command-runner.js.map +1 -1
  89. package/dist/server/modules/git/git-controller.js +8 -7
  90. package/dist/server/modules/git/git-controller.js.map +1 -1
  91. package/dist/server/modules/git/git-read-service.d.ts +7 -7
  92. package/dist/server/modules/git/git-read-service.js +41 -24
  93. package/dist/server/modules/git/git-read-service.js.map +1 -1
  94. package/dist/server/modules/model-switch/cc-switch-adapter.js +6 -2
  95. package/dist/server/modules/model-switch/cc-switch-adapter.js.map +1 -1
  96. package/dist/server/modules/preferences/profile-service.d.ts +3 -1
  97. package/dist/server/modules/preferences/profile-service.js +74 -3
  98. package/dist/server/modules/preferences/profile-service.js.map +1 -1
  99. package/dist/server/modules/provider/codex-model-options.js +2 -3
  100. package/dist/server/modules/provider/codex-model-options.js.map +1 -1
  101. package/dist/server/modules/provider/opencode-model-options.js +2 -3
  102. package/dist/server/modules/provider/opencode-model-options.js.map +1 -1
  103. package/dist/server/modules/provider/provider-discovery-helper-client.d.ts +14 -7
  104. package/dist/server/modules/provider/provider-discovery-helper-client.js +208 -46
  105. package/dist/server/modules/provider/provider-discovery-helper-client.js.map +1 -1
  106. package/dist/server/modules/provider/provider-discovery-helper-process.js +96 -47
  107. package/dist/server/modules/provider/provider-discovery-helper-process.js.map +1 -1
  108. package/dist/server/modules/provider/provider-discovery-runtime.d.ts +4 -0
  109. package/dist/server/modules/provider/provider-discovery-runtime.js +145 -0
  110. package/dist/server/modules/provider/provider-discovery-runtime.js.map +1 -0
  111. package/dist/server/modules/sessions/claude-runtime-helper-client.js +23 -1
  112. package/dist/server/modules/sessions/claude-runtime-helper-client.js.map +1 -1
  113. package/dist/server/modules/sessions/session-history-service.d.ts +12 -3
  114. package/dist/server/modules/sessions/session-history-service.js +465 -67
  115. package/dist/server/modules/sessions/session-history-service.js.map +1 -1
  116. package/dist/server/modules/sessions/session-live-runtime-service.d.ts +8 -0
  117. package/dist/server/modules/sessions/session-live-runtime-service.js +164 -34
  118. package/dist/server/modules/sessions/session-live-runtime-service.js.map +1 -1
  119. package/dist/server/modules/sessions/session-message-origin-utils.d.ts +12 -0
  120. package/dist/server/modules/sessions/session-message-origin-utils.js +45 -0
  121. package/dist/server/modules/sessions/session-message-origin-utils.js.map +1 -0
  122. package/dist/server/modules/sessions/session-permission-request-service.js +167 -0
  123. package/dist/server/modules/sessions/session-permission-request-service.js.map +1 -1
  124. package/dist/server/modules/skills/builtin-skill-service.d.ts +12 -0
  125. package/dist/server/modules/skills/builtin-skill-service.js +49 -0
  126. package/dist/server/modules/skills/builtin-skill-service.js.map +1 -0
  127. package/dist/server/modules/skills/builtin-skills/codingns-assistant/SKILL.md +82 -0
  128. package/dist/server/modules/skills/builtin-skills/codingns-assistant/agents/openai.yaml +4 -0
  129. package/dist/server/modules/skills/builtin-skills/codingns-assistant/references/cli-workflow.md +136 -0
  130. package/dist/server/modules/skills/skill-manager-service.d.ts +7 -0
  131. package/dist/server/modules/skills/skill-manager-service.js +98 -0
  132. package/dist/server/modules/skills/skill-manager-service.js.map +1 -1
  133. package/dist/server/modules/tailscale/tailscale-helper-client.d.ts +1 -0
  134. package/dist/server/modules/tailscale/tailscale-helper-client.js +12 -0
  135. package/dist/server/modules/tailscale/tailscale-helper-client.js.map +1 -1
  136. package/dist/server/modules/tasks/task-helper-client.d.ts +10 -2
  137. package/dist/server/modules/tasks/task-helper-client.js +152 -27
  138. package/dist/server/modules/tasks/task-helper-client.js.map +1 -1
  139. package/dist/server/modules/tasks/task-helper-process-handlers.d.ts +10 -3
  140. package/dist/server/modules/tasks/task-helper-process-handlers.js +7 -5
  141. package/dist/server/modules/tasks/task-helper-process-handlers.js.map +1 -1
  142. package/dist/server/modules/tasks/task-helper-process.js +104 -3
  143. package/dist/server/modules/tasks/task-helper-process.js.map +1 -1
  144. package/dist/server/modules/tasks/task-lane-executors.js +2 -2
  145. package/dist/server/modules/tasks/task-lane-executors.js.map +1 -1
  146. package/dist/server/modules/tasks/task-types.d.ts +4 -0
  147. package/dist/server/modules/tasks/task-types.js +5 -1
  148. package/dist/server/modules/tasks/task-types.js.map +1 -1
  149. package/dist/server/modules/terminal/command-template-service.d.ts +11 -2
  150. package/dist/server/modules/terminal/command-template-service.js +91 -9
  151. package/dist/server/modules/terminal/command-template-service.js.map +1 -1
  152. package/dist/server/modules/terminal/runtime/terminal-log-writer-client.js +1 -1
  153. package/dist/server/modules/terminal/runtime/terminal-log-writer-client.js.map +1 -1
  154. package/dist/server/modules/terminal/runtime/terminal-log-writer-process.js +160 -11
  155. package/dist/server/modules/terminal/runtime/terminal-log-writer-process.js.map +1 -1
  156. package/dist/server/modules/terminal/template-port-runtime.d.ts +1 -1
  157. package/dist/server/modules/terminal/template-port-runtime.js +87 -37
  158. package/dist/server/modules/terminal/template-port-runtime.js.map +1 -1
  159. package/dist/server/modules/terminal/terminal-controller.d.ts +3 -0
  160. package/dist/server/modules/terminal/terminal-controller.js +41 -0
  161. package/dist/server/modules/terminal/terminal-controller.js.map +1 -1
  162. package/dist/server/modules/terminal/terminal-service.d.ts +4 -0
  163. package/dist/server/modules/terminal/terminal-service.js +35 -1
  164. package/dist/server/modules/terminal/terminal-service.js.map +1 -1
  165. package/dist/server/modules/workbench/workbench-service.d.ts +3 -0
  166. package/dist/server/modules/workbench/workbench-service.js +7 -6
  167. package/dist/server/modules/workbench/workbench-service.js.map +1 -1
  168. package/dist/server/modules/workbench/workspace-file-watcher.d.ts +14 -6
  169. package/dist/server/modules/workbench/workspace-file-watcher.js +267 -57
  170. package/dist/server/modules/workbench/workspace-file-watcher.js.map +1 -1
  171. package/dist/server/modules/workbench/workspace-panel-snapshot-service.d.ts +3 -0
  172. package/dist/server/modules/workbench/workspace-panel-snapshot-service.js +149 -41
  173. package/dist/server/modules/workbench/workspace-panel-snapshot-service.js.map +1 -1
  174. package/dist/server/modules/workspace/workspace-code-composition.d.ts +1 -0
  175. package/dist/server/modules/workspace/workspace-code-composition.js +183 -1
  176. package/dist/server/modules/workspace/workspace-code-composition.js.map +1 -1
  177. package/dist/server/modules/workspace/workspace-service.js +54 -17
  178. package/dist/server/modules/workspace/workspace-service.js.map +1 -1
  179. package/dist/server/modules/worktree/worktree-cleanup-service.d.ts +1 -1
  180. package/dist/server/modules/worktree/worktree-cleanup-service.js +22 -17
  181. package/dist/server/modules/worktree/worktree-cleanup-service.js.map +1 -1
  182. package/dist/server/modules/worktree/worktree-controller.js +6 -5
  183. package/dist/server/modules/worktree/worktree-controller.js.map +1 -1
  184. package/dist/server/modules/worktree/worktree-manager.d.ts +10 -2
  185. package/dist/server/modules/worktree/worktree-manager.js +35 -20
  186. package/dist/server/modules/worktree/worktree-manager.js.map +1 -1
  187. package/dist/server/modules/worktree/worktree-merge-service.d.ts +2 -2
  188. package/dist/server/modules/worktree/worktree-merge-service.js +34 -27
  189. package/dist/server/modules/worktree/worktree-merge-service.js.map +1 -1
  190. package/dist/server/modules/worktree/worktree-sync-service.d.ts +1 -1
  191. package/dist/server/modules/worktree/worktree-sync-service.js +5 -3
  192. package/dist/server/modules/worktree/worktree-sync-service.js.map +1 -1
  193. package/dist/server/routes/assistant.js +43 -0
  194. package/dist/server/routes/assistant.js.map +1 -1
  195. package/dist/server/routes/butler.js +5 -0
  196. package/dist/server/routes/butler.js.map +1 -1
  197. package/dist/server/server/create-server.d.ts +8 -0
  198. package/dist/server/server/create-server.js +51 -13
  199. package/dist/server/server/create-server.js.map +1 -1
  200. package/dist/server/shared/http/request-abort.d.ts +2 -0
  201. package/dist/server/shared/http/request-abort.js +38 -0
  202. package/dist/server/shared/http/request-abort.js.map +1 -0
  203. package/dist/server/storage/repositories/assistant-automation-run-repository.d.ts +12 -0
  204. package/dist/server/storage/repositories/assistant-automation-run-repository.js +139 -0
  205. package/dist/server/storage/repositories/assistant-automation-run-repository.js.map +1 -0
  206. package/dist/server/storage/repositories/assistant-automation-task-repository.d.ts +15 -0
  207. package/dist/server/storage/repositories/assistant-automation-task-repository.js +173 -0
  208. package/dist/server/storage/repositories/assistant-automation-task-repository.js.map +1 -0
  209. package/dist/server/storage/repositories/assistant-sandbox-workspace-repository.d.ts +17 -0
  210. package/dist/server/storage/repositories/assistant-sandbox-workspace-repository.js +164 -0
  211. package/dist/server/storage/repositories/assistant-sandbox-workspace-repository.js.map +1 -0
  212. package/dist/server/storage/repositories/butler-control-session-repository.js +27 -3
  213. package/dist/server/storage/repositories/butler-control-session-repository.js.map +1 -1
  214. package/dist/server/storage/repositories/butler-control-timer-repository.d.ts +15 -0
  215. package/dist/server/storage/repositories/butler-control-timer-repository.js +157 -0
  216. package/dist/server/storage/repositories/butler-control-timer-repository.js.map +1 -0
  217. package/dist/server/storage/repositories/user-preference-profile-repository.js +6 -3
  218. package/dist/server/storage/repositories/user-preference-profile-repository.js.map +1 -1
  219. package/dist/server/storage/sqlite/client.js +239 -2
  220. package/dist/server/storage/sqlite/client.js.map +1 -1
  221. package/dist/server/storage/sqlite/schema.sql +107 -1
  222. package/dist/server/types/domain.d.ts +89 -2
  223. package/dist/server/ws/workbench-ws-hub.d.ts +14 -7
  224. package/dist/server/ws/workbench-ws-hub.js +316 -158
  225. package/dist/server/ws/workbench-ws-hub.js.map +1 -1
  226. package/node_modules/@codingns/session-sync-core/dist/providers/claude-code.d.ts +4 -1
  227. package/node_modules/@codingns/session-sync-core/dist/providers/claude-code.js +111 -3
  228. package/node_modules/@codingns/session-sync-core/dist/providers/claude-code.js.map +1 -1
  229. package/node_modules/@codingns/session-sync-core/dist/providers/codex.d.ts +6 -1
  230. package/node_modules/@codingns/session-sync-core/dist/providers/codex.js +306 -31
  231. package/node_modules/@codingns/session-sync-core/dist/providers/codex.js.map +1 -1
  232. package/node_modules/@codingns/session-sync-core/dist/providers/gemini.d.ts +5 -1
  233. package/node_modules/@codingns/session-sync-core/dist/providers/gemini.js +187 -26
  234. package/node_modules/@codingns/session-sync-core/dist/providers/gemini.js.map +1 -1
  235. package/node_modules/@codingns/session-sync-core/dist/providers/kimi.d.ts +4 -1
  236. package/node_modules/@codingns/session-sync-core/dist/providers/kimi.js +98 -1
  237. package/node_modules/@codingns/session-sync-core/dist/providers/kimi.js.map +1 -1
  238. package/node_modules/@codingns/session-sync-core/dist/providers/opencode.d.ts +2 -0
  239. package/node_modules/@codingns/session-sync-core/dist/providers/opencode.js +71 -8
  240. package/node_modules/@codingns/session-sync-core/dist/providers/opencode.js.map +1 -1
  241. package/node_modules/@codingns/session-sync-core/dist/providers/utils.d.ts +1 -0
  242. package/node_modules/@codingns/session-sync-core/dist/providers/utils.js +4 -1
  243. package/node_modules/@codingns/session-sync-core/dist/providers/utils.js.map +1 -1
  244. package/node_modules/@codingns/session-sync-core/dist/runtime/claude-runtime.js +44 -0
  245. package/node_modules/@codingns/session-sync-core/dist/runtime/claude-runtime.js.map +1 -1
  246. package/node_modules/@codingns/session-sync-core/dist/runtime/codex-runtime.js +9 -3
  247. package/node_modules/@codingns/session-sync-core/dist/runtime/codex-runtime.js.map +1 -1
  248. package/node_modules/@codingns/session-sync-core/dist/runtime/types.d.ts +1 -0
  249. package/node_modules/@codingns/session-sync-core/dist/services.js +17 -8
  250. package/node_modules/@codingns/session-sync-core/dist/services.js.map +1 -1
  251. package/node_modules/@codingns/session-sync-core/dist/types.d.ts +4 -0
  252. package/package.json +1 -1
  253. package/scripts/postinstall.mjs +33 -0
  254. package/dist/public/assets/index-Cek6u0b9.css +0 -1
  255. package/dist/public/assets/index-THHY79si.js +0 -122
package/bin/codingns.mjs CHANGED
@@ -139,6 +139,32 @@ async function runAssistantCommand(argv) {
139
139
  }));
140
140
  return;
141
141
  }
142
+ case "sessions:start": {
143
+ await printAssistantResponse(await requestAssistant({
144
+ method: "POST",
145
+ path: "/api/assistant/sessions/start",
146
+ argv: rest,
147
+ supportedOptions: [
148
+ "project",
149
+ "workspace",
150
+ "sandbox",
151
+ "message",
152
+ "provider",
153
+ "model",
154
+ "reasoning-level",
155
+ "permission-mode"
156
+ ],
157
+ helpTopic: "sessions.start"
158
+ }, (options) => ({
159
+ ...resolveAssistantSessionStartTarget(options.values),
160
+ content: requireOptionValue(options.values.message, "message"),
161
+ providerId: readOptionalTrimmedValue(options.values.provider),
162
+ model: readOptionalTrimmedValue(options.values.model),
163
+ reasoningLevel: readOptionalTrimmedValue(options.values["reasoning-level"]),
164
+ permissionMode: readOptionalTrimmedValue(options.values["permission-mode"])
165
+ })));
166
+ return;
167
+ }
142
168
  case "sessions:get": {
143
169
  const [sessionId, ...tail] = rest;
144
170
  await printAssistantResponse(await requestAssistant({
@@ -207,6 +233,237 @@ async function runAssistantCommand(argv) {
207
233
  })));
208
234
  return;
209
235
  }
236
+ case "automations:list":
237
+ await printAssistantResponse(await requestAssistant({
238
+ method: "GET",
239
+ path: "/api/assistant/automations",
240
+ argv: rest,
241
+ supportedOptions: ["status", "control-session-id"],
242
+ helpTopic: "automations.list"
243
+ }, (options) => ({
244
+ status: readOptionalTrimmedValue(options.values.status),
245
+ controlSessionId: readOptionalTrimmedValue(options.values["control-session-id"])
246
+ })));
247
+ return;
248
+ case "automations:get": {
249
+ const [automationId, ...tail] = rest;
250
+ await printAssistantResponse(await requestAssistant({
251
+ method: "GET",
252
+ path: `/api/assistant/automations/${requirePositional(automationId, "automationId")}`,
253
+ argv: tail,
254
+ helpTopic: "automations.get"
255
+ }));
256
+ return;
257
+ }
258
+ case "automations:create":
259
+ await printAssistantResponse(await requestAssistant({
260
+ method: "POST",
261
+ path: "/api/assistant/automations",
262
+ argv: rest,
263
+ supportedOptions: [
264
+ "message",
265
+ "trigger",
266
+ "title",
267
+ "due-at",
268
+ "after-seconds",
269
+ "every-seconds",
270
+ "every-minutes",
271
+ "every-hours",
272
+ "stop-at",
273
+ "cron-minute",
274
+ "cron-hour",
275
+ "cron-day-of-week",
276
+ "condition-kind",
277
+ "repository-url",
278
+ "poll-interval-seconds",
279
+ "expires-at",
280
+ "max-checks",
281
+ "condition-session-id",
282
+ "control-session-id",
283
+ "project-id",
284
+ "session-id"
285
+ ],
286
+ supportedFlags: ["include-trigger-context"],
287
+ repeatableOptions: ["cron-day-of-week"],
288
+ helpTopic: "automations.create"
289
+ }, (options) => ({
290
+ content: requireOptionValue(options.values.message, "message"),
291
+ triggerType: readOptionalTrimmedValue(options.values.trigger),
292
+ title: readOptionalTrimmedValue(options.values.title),
293
+ dueAt: readOptionalTrimmedValue(options.values["due-at"]),
294
+ afterSeconds: readOptionalTrimmedValue(options.values["after-seconds"]),
295
+ everySeconds: readOptionalTrimmedValue(options.values["every-seconds"]),
296
+ everyMinutes: readOptionalTrimmedValue(options.values["every-minutes"]),
297
+ everyHours: readOptionalTrimmedValue(options.values["every-hours"]),
298
+ stopAt: readOptionalTrimmedValue(options.values["stop-at"]),
299
+ cronMinute: readOptionalTrimmedValue(options.values["cron-minute"]),
300
+ cronHour: readOptionalTrimmedValue(options.values["cron-hour"]),
301
+ cronDaysOfWeek: readMultiOptionValues(options.values["cron-day-of-week"]),
302
+ conditionKind: readOptionalTrimmedValue(options.values["condition-kind"]),
303
+ repositoryUrl: readOptionalTrimmedValue(options.values["repository-url"]),
304
+ pollIntervalSeconds: readOptionalTrimmedValue(options.values["poll-interval-seconds"]),
305
+ expiresAt: readOptionalTrimmedValue(options.values["expires-at"]),
306
+ maxChecks: readOptionalTrimmedValue(options.values["max-checks"]),
307
+ conditionSessionId: readOptionalTrimmedValue(options.values["condition-session-id"]),
308
+ includeTriggerContext: options.flags["include-trigger-context"] === true,
309
+ controlSessionId: readOptionalTrimmedValue(options.values["control-session-id"]),
310
+ projectId: readOptionalTrimmedValue(options.values["project-id"]),
311
+ targetSessionId: readOptionalTrimmedValue(options.values["session-id"])
312
+ })));
313
+ return;
314
+ case "automations:cancel": {
315
+ const [automationId, ...tail] = rest;
316
+ await printAssistantResponse(await requestAssistant({
317
+ method: "POST",
318
+ path: `/api/assistant/automations/${requirePositional(automationId, "automationId")}/cancel`,
319
+ argv: tail,
320
+ helpTopic: "automations.cancel"
321
+ }));
322
+ return;
323
+ }
324
+ case "automations:runs": {
325
+ const [automationId, ...tail] = rest;
326
+ await printAssistantResponse(await requestAssistant({
327
+ method: "GET",
328
+ path: `/api/assistant/automations/${requirePositional(automationId, "automationId")}/runs`,
329
+ argv: tail,
330
+ helpTopic: "automations.runs"
331
+ }));
332
+ return;
333
+ }
334
+ case "sandboxes:list":
335
+ await printAssistantResponse(await requestAssistant({
336
+ method: "GET",
337
+ path: "/api/assistant/sandboxes",
338
+ argv: rest,
339
+ supportedOptions: ["status"],
340
+ helpTopic: "sandboxes.list"
341
+ }, (options) => ({
342
+ status: readOptionalTrimmedValue(options.values.status)
343
+ })));
344
+ return;
345
+ case "sandboxes:create":
346
+ await printAssistantResponse(await requestAssistant({
347
+ method: "POST",
348
+ path: "/api/assistant/sandboxes",
349
+ argv: rest,
350
+ supportedOptions: [
351
+ "title",
352
+ "description",
353
+ "purpose",
354
+ "expires-at",
355
+ "source-kind",
356
+ "repository-url",
357
+ "directory-name",
358
+ "auth-mode",
359
+ "username",
360
+ "password",
361
+ "auth-token"
362
+ ],
363
+ helpTopic: "sandboxes.create"
364
+ }, (options) => ({
365
+ title: readOptionalTrimmedValue(options.values.title),
366
+ description: readOptionalTrimmedValue(options.values.description),
367
+ purpose: readOptionalTrimmedValue(options.values.purpose),
368
+ expiresAt: readOptionalTrimmedValue(options.values["expires-at"]),
369
+ sourceKind: readOptionalTrimmedValue(options.values["source-kind"]),
370
+ repositoryUrl: readOptionalTrimmedValue(options.values["repository-url"]),
371
+ directoryName: readOptionalTrimmedValue(options.values["directory-name"]),
372
+ auth: buildWorkspaceCloneAuth(options.values)
373
+ })));
374
+ return;
375
+ case "sandboxes:promote": {
376
+ const [sandboxId, ...tail] = rest;
377
+ await printAssistantResponse(await requestAssistant({
378
+ method: "POST",
379
+ path: `/api/assistant/sandboxes/${requirePositional(sandboxId, "sandboxId")}/promote`,
380
+ argv: tail,
381
+ supportedOptions: ["mode", "project-name", "provider"],
382
+ helpTopic: "sandboxes.promote"
383
+ }, (options) => ({
384
+ mode: readOptionalTrimmedValue(options.values.mode),
385
+ projectName: readOptionalTrimmedValue(options.values["project-name"]),
386
+ defaultProvider: readOptionalTrimmedValue(options.values.provider)
387
+ })));
388
+ return;
389
+ }
390
+ case "sandboxes:expire": {
391
+ const [sandboxId, ...tail] = rest;
392
+ await printAssistantResponse(await requestAssistant({
393
+ method: "POST",
394
+ path: `/api/assistant/sandboxes/${requirePositional(sandboxId, "sandboxId")}/expire`,
395
+ argv: tail,
396
+ helpTopic: "sandboxes.expire"
397
+ }));
398
+ return;
399
+ }
400
+ case "sandboxes:remove": {
401
+ const [sandboxId, ...tail] = rest;
402
+ await printAssistantResponse(await requestAssistant({
403
+ method: "DELETE",
404
+ path: `/api/assistant/sandboxes/${requirePositional(sandboxId, "sandboxId")}`,
405
+ argv: tail,
406
+ helpTopic: "sandboxes.remove"
407
+ }));
408
+ return;
409
+ }
410
+ case "timers:list":
411
+ await printAssistantResponse(await requestAssistant({
412
+ method: "GET",
413
+ path: "/api/assistant/timers",
414
+ argv: rest,
415
+ supportedOptions: ["status", "control-session-id"],
416
+ helpTopic: "timers.list"
417
+ }, (options) => ({
418
+ status: readOptionalTrimmedValue(options.values.status),
419
+ controlSessionId: readOptionalTrimmedValue(options.values["control-session-id"])
420
+ })));
421
+ return;
422
+ case "timers:get": {
423
+ const [timerId, ...tail] = rest;
424
+ await printAssistantResponse(await requestAssistant({
425
+ method: "GET",
426
+ path: `/api/assistant/timers/${requirePositional(timerId, "timerId")}`,
427
+ argv: tail,
428
+ helpTopic: "timers.get"
429
+ }));
430
+ return;
431
+ }
432
+ case "timers:create":
433
+ await printAssistantResponse(await requestAssistant({
434
+ method: "POST",
435
+ path: "/api/assistant/timers",
436
+ argv: rest,
437
+ supportedOptions: [
438
+ "message",
439
+ "title",
440
+ "due-at",
441
+ "after-seconds",
442
+ "control-session-id",
443
+ "project-id",
444
+ "session-id"
445
+ ],
446
+ helpTopic: "timers.create"
447
+ }, (options) => ({
448
+ content: requireOptionValue(options.values.message, "message"),
449
+ title: readOptionalTrimmedValue(options.values.title),
450
+ dueAt: readOptionalTrimmedValue(options.values["due-at"]),
451
+ afterSeconds: readOptionalTrimmedValue(options.values["after-seconds"]),
452
+ controlSessionId: readOptionalTrimmedValue(options.values["control-session-id"]),
453
+ projectId: readOptionalTrimmedValue(options.values["project-id"]),
454
+ targetSessionId: readOptionalTrimmedValue(options.values["session-id"])
455
+ })));
456
+ return;
457
+ case "timers:cancel": {
458
+ const [timerId, ...tail] = rest;
459
+ await printAssistantResponse(await requestAssistant({
460
+ method: "POST",
461
+ path: `/api/assistant/timers/${requirePositional(timerId, "timerId")}/cancel`,
462
+ argv: tail,
463
+ helpTopic: "timers.cancel"
464
+ }));
465
+ return;
466
+ }
210
467
  case "terminals:list":
211
468
  await printAssistantResponse(await requestAssistant({
212
469
  method: "GET",
@@ -229,7 +486,7 @@ async function runAssistantCommand(argv) {
229
486
  helpTopic: "terminals.history"
230
487
  }, (options) => ({
231
488
  beforeSeq: readOptionalTrimmedValue(options.values["before-seq"]),
232
- limit: readOptionalTrimmedValue(options.values.limit)
489
+ limit: readAssistantTerminalHistoryLimitOption(options.values.limit)
233
490
  })));
234
491
  return;
235
492
  }
@@ -246,6 +503,303 @@ async function runAssistantCommand(argv) {
246
503
  })));
247
504
  return;
248
505
  }
506
+ case "terminals:close": {
507
+ const [terminalId, ...tail] = rest;
508
+ await printAssistantResponse(await requestAssistant({
509
+ method: "DELETE",
510
+ path: `/api/assistant/terminals/${requirePositional(terminalId, "terminalId")}`,
511
+ argv: tail,
512
+ helpTopic: "terminals.close"
513
+ }));
514
+ return;
515
+ }
516
+ case "debug-targets:compatibility-matrix":
517
+ await printAssistantResponse(await requestAssistant({
518
+ method: "GET",
519
+ path: "/api/assistant/debug-targets/compatibility-matrix",
520
+ argv: rest,
521
+ helpTopic: "debug-targets.compatibility-matrix"
522
+ }));
523
+ return;
524
+ case "debug-targets:analyze":
525
+ await printAssistantResponse(await requestAssistant({
526
+ method: "POST",
527
+ path: "/api/assistant/debug-targets/analyze",
528
+ argv: rest,
529
+ supportedOptions: ["workspace-id", "root-path", "command-hint"],
530
+ repeatableOptions: ["command-hint"],
531
+ helpTopic: "debug-targets.analyze"
532
+ }, (options) => ({
533
+ workspaceId: requireOptionValue(options.values["workspace-id"], "workspace-id"),
534
+ rootPath: requireOptionValue(options.values["root-path"], "root-path"),
535
+ commandHints: readMultiOptionValues(options.values["command-hint"])
536
+ })));
537
+ return;
538
+ case "debug-targets:framework-analysis": {
539
+ const [targetId, ...tail] = rest;
540
+ await printAssistantResponse(await requestAssistant({
541
+ method: "GET",
542
+ path: `/api/assistant/debug-targets/${requirePositional(targetId, "targetId")}/framework-analysis`,
543
+ argv: tail,
544
+ helpTopic: "debug-targets.framework-analysis"
545
+ }));
546
+ return;
547
+ }
548
+ case "debug-targets:refresh-framework-analysis": {
549
+ const [targetId, ...tail] = rest;
550
+ await printAssistantResponse(await requestAssistant({
551
+ method: "POST",
552
+ path: `/api/assistant/debug-targets/${requirePositional(targetId, "targetId")}/framework-analysis/refresh`,
553
+ argv: tail,
554
+ helpTopic: "debug-targets.refresh-framework-analysis"
555
+ }));
556
+ return;
557
+ }
558
+ case "debug-targets:launch-plan": {
559
+ const [targetId, ...tail] = rest;
560
+ await printAssistantResponse(await requestAssistant({
561
+ method: "POST",
562
+ path: `/api/assistant/debug-targets/${requirePositional(targetId, "targetId")}/launch-plan`,
563
+ argv: tail,
564
+ supportedOptions: ["port-request"],
565
+ repeatableOptions: ["port-request"],
566
+ helpTopic: "debug-targets.launch-plan"
567
+ }, (options) => ({
568
+ portRequests: parseDebugPortRequests(options.values["port-request"])
569
+ })));
570
+ return;
571
+ }
572
+ case "debug-targets:run": {
573
+ const [targetId, ...tail] = rest;
574
+ await printAssistantResponse(await requestAssistant({
575
+ method: "POST",
576
+ path: `/api/assistant/debug-targets/${requirePositional(targetId, "targetId")}/run`,
577
+ argv: tail,
578
+ supportedOptions: ["shell", "runtime-type", "port-request"],
579
+ repeatableOptions: ["port-request"],
580
+ helpTopic: "debug-targets.run"
581
+ }, (options) => ({
582
+ shell: readOptionalTrimmedValue(options.values.shell),
583
+ runtimeType: readOptionalTrimmedValue(options.values["runtime-type"]),
584
+ portRequests: parseDebugPortRequests(options.values["port-request"])
585
+ })));
586
+ return;
587
+ }
588
+ case "debug-targets:runtime-latest": {
589
+ const [targetId, ...tail] = rest;
590
+ await printAssistantResponse(await requestAssistant({
591
+ method: "GET",
592
+ path: `/api/assistant/debug-targets/${requirePositional(targetId, "targetId")}/runtime-latest`,
593
+ argv: tail,
594
+ helpTopic: "debug-targets.runtime-latest"
595
+ }));
596
+ return;
597
+ }
598
+ case "debug-targets:runtimes": {
599
+ const [targetId, ...tail] = rest;
600
+ await printAssistantResponse(await requestAssistant({
601
+ method: "GET",
602
+ path: `/api/assistant/debug-targets/${requirePositional(targetId, "targetId")}/runtimes`,
603
+ argv: tail,
604
+ supportedOptions: ["limit"],
605
+ helpTopic: "debug-targets.runtimes"
606
+ }, (options) => ({
607
+ limit: readOptionalTrimmedValue(options.values.limit)
608
+ })));
609
+ return;
610
+ }
611
+ case "debug-runtimes:get": {
612
+ const [runtimeId, ...tail] = rest;
613
+ await printAssistantResponse(await requestAssistant({
614
+ method: "GET",
615
+ path: `/api/assistant/debug-runtimes/${requirePositional(runtimeId, "runtimeId")}`,
616
+ argv: tail,
617
+ helpTopic: "debug-runtimes.get"
618
+ }));
619
+ return;
620
+ }
621
+ case "workspaces:list":
622
+ await printAssistantResponse(await requestAssistant({
623
+ method: "GET",
624
+ path: "/api/assistant/workspaces",
625
+ argv: rest,
626
+ helpTopic: "workspaces.list"
627
+ }));
628
+ return;
629
+ case "workspaces:browse":
630
+ await printAssistantResponse(await requestAssistant({
631
+ method: "GET",
632
+ path: "/api/assistant/workspaces/browse",
633
+ argv: rest,
634
+ supportedOptions: ["path"],
635
+ helpTopic: "workspaces.browse"
636
+ }, (options) => ({
637
+ path: readOptionalTrimmedValue(options.values.path)
638
+ })));
639
+ return;
640
+ case "workspaces:mkdir":
641
+ await printAssistantResponse(await requestAssistant({
642
+ method: "POST",
643
+ path: "/api/assistant/workspaces/directories",
644
+ argv: rest,
645
+ supportedOptions: ["parent-path", "directory-name"],
646
+ helpTopic: "workspaces.mkdir"
647
+ }, (options) => ({
648
+ parentPath: requireOptionValue(options.values["parent-path"], "parent-path"),
649
+ directoryName: requireOptionValue(options.values["directory-name"], "directory-name")
650
+ })));
651
+ return;
652
+ case "workspaces:import":
653
+ await printAssistantResponse(await requestAssistant({
654
+ method: "POST",
655
+ path: "/api/assistant/workspaces/import",
656
+ argv: rest,
657
+ supportedOptions: ["path", "name"],
658
+ helpTopic: "workspaces.import"
659
+ }, (options) => ({
660
+ path: requireOptionValue(options.values.path, "path"),
661
+ name: readOptionalTrimmedValue(options.values.name)
662
+ })));
663
+ return;
664
+ case "workspaces:clone":
665
+ await printAssistantResponse(await requestAssistant({
666
+ method: "POST",
667
+ path: "/api/assistant/workspaces/clone",
668
+ argv: rest,
669
+ supportedOptions: [
670
+ "repository-url",
671
+ "parent-path",
672
+ "directory-name",
673
+ "name",
674
+ "auth-mode",
675
+ "username",
676
+ "password",
677
+ "auth-token"
678
+ ],
679
+ helpTopic: "workspaces.clone"
680
+ }, (options) => ({
681
+ repositoryUrl: requireOptionValue(options.values["repository-url"], "repository-url"),
682
+ parentPath: requireOptionValue(options.values["parent-path"], "parent-path"),
683
+ directoryName: readOptionalTrimmedValue(options.values["directory-name"]),
684
+ name: readOptionalTrimmedValue(options.values.name),
685
+ auth: buildWorkspaceCloneAuth(options.values)
686
+ })));
687
+ return;
688
+ case "workspaces:reorder":
689
+ await printAssistantResponse(await requestAssistant({
690
+ method: "PUT",
691
+ path: "/api/assistant/workspaces/reorder",
692
+ argv: rest,
693
+ supportedOptions: ["workspace-id"],
694
+ repeatableOptions: ["workspace-id"],
695
+ helpTopic: "workspaces.reorder"
696
+ }, (options) => ({
697
+ workspaceIds: requireMultiOptionValues(options.values["workspace-id"], "workspace-id")
698
+ })));
699
+ return;
700
+ case "workspaces:management": {
701
+ const [workspaceId, ...tail] = rest;
702
+ await printAssistantResponse(await requestAssistant({
703
+ method: "GET",
704
+ path: `/api/assistant/workspaces/${requirePositional(workspaceId, "workspaceId")}/management`,
705
+ argv: tail,
706
+ helpTopic: "workspaces.management"
707
+ }));
708
+ return;
709
+ }
710
+ case "workspaces:nav-state": {
711
+ const [workspaceId, ...tail] = rest;
712
+ await printAssistantResponse(await requestAssistant({
713
+ method: "PUT",
714
+ path: `/api/assistant/workspaces/${requirePositional(workspaceId, "workspaceId")}/navigation-state`,
715
+ argv: tail,
716
+ supportedOptions: ["collapsed", "background-color"],
717
+ helpTopic: "workspaces.nav-state"
718
+ }, (options) => {
719
+ const payload = {};
720
+ const collapsed = readOptionalTrimmedValue(options.values.collapsed);
721
+ const backgroundColor = readOptionalTrimmedValue(options.values["background-color"]);
722
+
723
+ if (collapsed !== null) {
724
+ payload.collapsed = parseBooleanOption(collapsed, "collapsed");
725
+ }
726
+
727
+ if (backgroundColor !== null) {
728
+ payload.backgroundColor = normalizeBackgroundColorOption(backgroundColor);
729
+ }
730
+
731
+ return payload;
732
+ }));
733
+ return;
734
+ }
735
+ case "workspaces:remove": {
736
+ const [workspaceId, ...tail] = rest;
737
+ await printAssistantResponse(await requestAssistant({
738
+ method: "DELETE",
739
+ path: `/api/assistant/workspaces/${requirePositional(workspaceId, "workspaceId")}`,
740
+ argv: tail,
741
+ helpTopic: "workspaces.remove"
742
+ }));
743
+ return;
744
+ }
745
+ case "worktrees:tree":
746
+ await printAssistantResponse(await requestAssistant({
747
+ method: "GET",
748
+ path: "/api/assistant/worktrees/tree",
749
+ argv: rest,
750
+ supportedOptions: ["root-workspace-id"],
751
+ helpTopic: "worktrees.tree"
752
+ }, (options) => ({
753
+ rootWorkspaceId: requireOptionValue(options.values["root-workspace-id"], "root-workspace-id")
754
+ })));
755
+ return;
756
+ case "worktrees:create":
757
+ await printAssistantResponse(await requestAssistant({
758
+ method: "POST",
759
+ path: "/api/assistant/worktrees",
760
+ argv: rest,
761
+ supportedOptions: ["source-workspace-id", "branch-name", "display-name", "base-ref"],
762
+ helpTopic: "worktrees.create"
763
+ }, (options) => ({
764
+ sourceWorkspaceId: requireOptionValue(options.values["source-workspace-id"], "source-workspace-id"),
765
+ branchName: requireOptionValue(options.values["branch-name"], "branch-name"),
766
+ displayName: readOptionalTrimmedValue(options.values["display-name"]),
767
+ baseRef: readOptionalTrimmedValue(options.values["base-ref"])
768
+ })));
769
+ return;
770
+ case "worktrees:merge-preview": {
771
+ const [workspaceId, ...tail] = rest;
772
+ await printAssistantResponse(await requestAssistant({
773
+ method: "POST",
774
+ path: `/api/assistant/worktrees/${requirePositional(workspaceId, "workspaceId")}/merge-preview`,
775
+ argv: tail,
776
+ helpTopic: "worktrees.merge-preview"
777
+ }));
778
+ return;
779
+ }
780
+ case "worktrees:merge": {
781
+ const [workspaceId, ...tail] = rest;
782
+ await printAssistantResponse(await requestAssistant({
783
+ method: "POST",
784
+ path: `/api/assistant/worktrees/${requirePositional(workspaceId, "workspaceId")}/merge-into-parent`,
785
+ argv: tail,
786
+ helpTopic: "worktrees.merge"
787
+ }));
788
+ return;
789
+ }
790
+ case "worktrees:cleanup": {
791
+ const [workspaceId, ...tail] = rest;
792
+ await printAssistantResponse(await requestAssistant({
793
+ method: "POST",
794
+ path: `/api/assistant/worktrees/${requirePositional(workspaceId, "workspaceId")}/cleanup`,
795
+ argv: tail,
796
+ supportedFlags: ["delete-branch"],
797
+ helpTopic: "worktrees.cleanup"
798
+ }, (options) => ({
799
+ deleteBranch: options.flags["delete-branch"] === true
800
+ })));
801
+ return;
802
+ }
249
803
  default:
250
804
  console.error(`[codingns] 不支持的 assistant 子命令:${group}${action ? ` ${action}` : ""}`);
251
805
  printAssistantHelpTopic("assistant", 1);
@@ -336,7 +890,9 @@ async function requestAssistant(command, buildPayload) {
336
890
  "base-url",
337
891
  "token",
338
892
  ...(command.supportedOptions ?? [])
339
- ]
893
+ ],
894
+ repeatableOptions: command.repeatableOptions ?? [],
895
+ supportedFlags: command.supportedFlags ?? []
340
896
  });
341
897
 
342
898
  if (options.help) {
@@ -366,13 +922,14 @@ async function requestAssistant(command, buildPayload) {
366
922
  let response;
367
923
 
368
924
  try {
925
+ const usesJsonBody = command.method === "POST" || command.method === "PUT";
369
926
  response = await fetch(url, {
370
927
  method: command.method,
371
928
  headers: {
372
929
  Authorization: `Bearer ${accessToken}`,
373
- ...(command.method === "POST" ? { "Content-Type": "application/json" } : {})
930
+ ...(usesJsonBody ? { "Content-Type": "application/json" } : {})
374
931
  },
375
- body: command.method === "POST" ? JSON.stringify(payload ?? {}) : undefined
932
+ body: usesJsonBody ? JSON.stringify(payload ?? {}) : undefined
376
933
  });
377
934
  } catch (error) {
378
935
  const message = error instanceof Error ? error.message : "未知网络错误";
@@ -571,10 +1128,14 @@ function parseArgs(argv, input = {}) {
571
1128
  }
572
1129
 
573
1130
  function resolveAssistantBaseUrl(input) {
574
- const baseUrl = readStringOption(
1131
+ const configuredBaseUrl = readStringOption(
575
1132
  input,
576
1133
  process.env.CODINGNS_BASE_URL,
577
- process.env.CODINGNS_SERVER_BASE_URL,
1134
+ process.env.CODINGNS_SERVER_BASE_URL
1135
+ );
1136
+ const baseUrl = readStringOption(
1137
+ configuredBaseUrl,
1138
+ configuredBaseUrl ? "" : readAssistantCredentialField("apiBaseUrl"),
578
1139
  "http://127.0.0.1:3002"
579
1140
  );
580
1141
 
@@ -586,19 +1147,109 @@ function resolveAssistantBaseUrl(input) {
586
1147
  }
587
1148
 
588
1149
  function resolveAssistantAccessToken(input) {
589
- const accessToken = readStringOption(
1150
+ const configuredAccessToken = readStringOption(
590
1151
  input,
591
1152
  process.env.CODINGNS_ACCESS_TOKEN,
592
1153
  process.env.CODINGNS_TOKEN
593
1154
  );
594
-
1155
+ const accessToken = readStringOption(
1156
+ configuredAccessToken,
1157
+ configuredAccessToken ? "" : readAssistantCredentialField("accessToken")
1158
+ );
1159
+
595
1160
  if (!accessToken) {
596
- fail("缺少助手调用 access token,请传 --token 或设置 CODINGNS_ACCESS_TOKEN");
1161
+ fail(
1162
+ "缺少助手调用 access token,请传 --token、设置 CODINGNS_ACCESS_TOKEN,或在当前目录/上级目录提供 BUTLER_AUTH.json(也可用 CODINGNS_AUTH_FILE 指定)"
1163
+ );
597
1164
  }
598
1165
 
599
1166
  return accessToken;
600
1167
  }
601
1168
 
1169
+ var cachedAssistantCredential;
1170
+
1171
+ function readAssistantCredentialField(field) {
1172
+ const credential = readAssistantCredential();
1173
+
1174
+ if (!credential) {
1175
+ return "";
1176
+ }
1177
+
1178
+ const value = credential[field];
1179
+ return typeof value === "string" ? value : "";
1180
+ }
1181
+
1182
+ function readAssistantCredential() {
1183
+ if (cachedAssistantCredential !== undefined) {
1184
+ return cachedAssistantCredential;
1185
+ }
1186
+
1187
+ const credentialFilePath = resolveAssistantCredentialFilePath();
1188
+
1189
+ if (!credentialFilePath) {
1190
+ cachedAssistantCredential = null;
1191
+ return cachedAssistantCredential;
1192
+ }
1193
+
1194
+ let rawContent;
1195
+
1196
+ try {
1197
+ rawContent = fs.readFileSync(credentialFilePath, "utf8");
1198
+ } catch (error) {
1199
+ const message = error instanceof Error ? error.message : "未知错误";
1200
+ fail(`读取助手认证文件失败:${credentialFilePath}(${message})`);
1201
+ }
1202
+
1203
+ let parsed;
1204
+
1205
+ try {
1206
+ parsed = JSON.parse(rawContent);
1207
+ } catch (error) {
1208
+ const message = error instanceof Error ? error.message : "未知错误";
1209
+ fail(`助手认证文件不是合法 JSON:${credentialFilePath}(${message})`);
1210
+ }
1211
+
1212
+ cachedAssistantCredential = {
1213
+ filePath: credentialFilePath,
1214
+ accessToken: typeof parsed?.accessToken === "string" ? parsed.accessToken.trim() : "",
1215
+ apiBaseUrl: typeof parsed?.apiBaseUrl === "string" ? parsed.apiBaseUrl.trim() : ""
1216
+ };
1217
+ return cachedAssistantCredential;
1218
+ }
1219
+
1220
+ function resolveAssistantCredentialFilePath() {
1221
+ const configuredPath = readStringOption(
1222
+ process.env.CODINGNS_AUTH_FILE,
1223
+ process.env.BUTLER_AUTH_FILE
1224
+ );
1225
+
1226
+ if (configuredPath) {
1227
+ return path.resolve(configuredPath);
1228
+ }
1229
+
1230
+ return findFileUpward(process.cwd(), "BUTLER_AUTH.json");
1231
+ }
1232
+
1233
+ function findFileUpward(startPath, fileName) {
1234
+ let currentPath = path.resolve(startPath);
1235
+
1236
+ while (true) {
1237
+ const candidatePath = path.join(currentPath, fileName);
1238
+
1239
+ if (fs.existsSync(candidatePath) && fs.statSync(candidatePath).isFile()) {
1240
+ return candidatePath;
1241
+ }
1242
+
1243
+ const parentPath = path.dirname(currentPath);
1244
+
1245
+ if (parentPath === currentPath) {
1246
+ return null;
1247
+ }
1248
+
1249
+ currentPath = parentPath;
1250
+ }
1251
+ }
1252
+
602
1253
  function readStringOption(...values) {
603
1254
  for (const value of values) {
604
1255
  if (typeof value === "string" && value.trim().length > 0) {
@@ -614,6 +1265,27 @@ function readOptionalTrimmedValue(value) {
614
1265
  return normalized.length > 0 ? normalized : null;
615
1266
  }
616
1267
 
1268
+ function readAssistantTerminalHistoryLimitOption(value) {
1269
+ const normalized = readOptionalTrimmedValue(value);
1270
+
1271
+ if (!normalized) {
1272
+ return null;
1273
+ }
1274
+
1275
+ const parsed = Number.parseInt(normalized, 10);
1276
+
1277
+ if (!Number.isInteger(parsed) || parsed < 1) {
1278
+ return normalized;
1279
+ }
1280
+
1281
+ if (parsed <= 100) {
1282
+ return normalized;
1283
+ }
1284
+
1285
+ console.warn("[codingns] assistant terminals history 的 --limit 最大为 100,已自动收敛到 100。");
1286
+ return "100";
1287
+ }
1288
+
617
1289
  function readMultiOptionValues(value) {
618
1290
  const values = Array.isArray(value)
619
1291
  ? value
@@ -753,8 +1425,13 @@ assistant 例子:
753
1425
 
754
1426
  codingns assistant capabilities list --token <token>
755
1427
  codingns assistant projects list --status active --token <token>
1428
+ codingns assistant workspaces list --token <token>
1429
+ codingns assistant debug-targets analyze --workspace-id <id> --root-path <path> --token <token>
1430
+ codingns assistant debug-targets launch-plan <targetId> --port-request role=backend,cwd=apps/api,port=44001 --token <token>
1431
+ codingns assistant worktrees tree --root-workspace-id <id> --token <token>
756
1432
  codingns assistant sessions send <sessionId> --message "继续修复类型错误" --token <token>
757
1433
  codingns assistant terminals send <terminalId> --input "npm test\\n" --token <token>
1434
+ codingns assistant terminals close <terminalId> --token <token>
758
1435
 
759
1436
  skills 例子:
760
1437
 
@@ -840,6 +1517,115 @@ codingns assistant projects get
840
1517
 
841
1518
  用法:
842
1519
  codingns assistant projects get <projectId> --token <token>
1520
+ `.trim();
1521
+ case "workspaces":
1522
+ return `
1523
+ codingns assistant workspaces
1524
+
1525
+ 可用动作:
1526
+ list 列出当前工作区
1527
+ browse 浏览可导入目录
1528
+ mkdir 创建目录
1529
+ import 导入工作区
1530
+ clone 克隆并导入工作区
1531
+ reorder 调整工作区顺序
1532
+ management 读取工作区管理摘要
1533
+ nav-state 更新导航状态
1534
+ remove 移除工作区
1535
+
1536
+ 示例:
1537
+ codingns assistant workspaces list --token <token>
1538
+ codingns assistant workspaces import --path /repo/demo --token <token>
1539
+ `.trim();
1540
+ case "workspaces.list":
1541
+ return `
1542
+ codingns assistant workspaces list
1543
+
1544
+ 用途:
1545
+ 列出当前可见工作区。
1546
+
1547
+ 用法:
1548
+ codingns assistant workspaces list --token <token>
1549
+ `.trim();
1550
+ case "workspaces.browse":
1551
+ return `
1552
+ codingns assistant workspaces browse
1553
+
1554
+ 用途:
1555
+ 浏览本地目录,给导入或 clone 选目标位置。
1556
+
1557
+ 用法:
1558
+ codingns assistant workspaces browse [--path <path>] --token <token>
1559
+ `.trim();
1560
+ case "workspaces.mkdir":
1561
+ return `
1562
+ codingns assistant workspaces mkdir
1563
+
1564
+ 用途:
1565
+ 在指定父目录下创建新目录。
1566
+
1567
+ 用法:
1568
+ codingns assistant workspaces mkdir --parent-path <path> --directory-name <name> --token <token>
1569
+ `.trim();
1570
+ case "workspaces.import":
1571
+ return `
1572
+ codingns assistant workspaces import
1573
+
1574
+ 用途:
1575
+ 把已有目录导入成工作区。
1576
+
1577
+ 用法:
1578
+ codingns assistant workspaces import --path <path> [--name <name>] --token <token>
1579
+ `.trim();
1580
+ case "workspaces.clone":
1581
+ return `
1582
+ codingns assistant workspaces clone
1583
+
1584
+ 用途:
1585
+ 克隆 Git 仓库并导入成工作区。
1586
+
1587
+ 用法:
1588
+ codingns assistant workspaces clone --repository-url <url> --parent-path <path> [--directory-name <name>] [--name <name>] [--auth-mode none|basic|token] [--username <name>] [--password <password>] [--auth-token <token>] --token <token>
1589
+ `.trim();
1590
+ case "workspaces.reorder":
1591
+ return `
1592
+ codingns assistant workspaces reorder
1593
+
1594
+ 用途:
1595
+ 调整工作区显示顺序,必须提交当前全部可见工作区。
1596
+
1597
+ 用法:
1598
+ codingns assistant workspaces reorder --workspace-id <id> [--workspace-id <id>] --token <token>
1599
+ `.trim();
1600
+ case "workspaces.management":
1601
+ return `
1602
+ codingns assistant workspaces management
1603
+
1604
+ 用途:
1605
+ 读取工作区 Git 和代码构成摘要。
1606
+
1607
+ 用法:
1608
+ codingns assistant workspaces management <workspaceId> --token <token>
1609
+ `.trim();
1610
+ case "workspaces.nav-state":
1611
+ return `
1612
+ codingns assistant workspaces nav-state
1613
+
1614
+ 用途:
1615
+ 更新工作区导航状态,比如折叠状态和背景色。
1616
+
1617
+ 用法:
1618
+ codingns assistant workspaces nav-state <workspaceId> [--collapsed true|false] [--background-color #RRGGBB|none] --token <token>
1619
+ `.trim();
1620
+ case "workspaces.remove":
1621
+ return `
1622
+ codingns assistant workspaces remove
1623
+
1624
+ 用途:
1625
+ 移除工作区入口,不直接删除磁盘目录。
1626
+
1627
+ 用法:
1628
+ codingns assistant workspaces remove <workspaceId> --token <token>
843
1629
  `.trim();
844
1630
  case "sessions":
845
1631
  return `
@@ -847,6 +1633,7 @@ codingns assistant sessions
847
1633
 
848
1634
  可用动作:
849
1635
  list 列出指定项目下的会话
1636
+ start 按 project/workspace/sandbox 目标新建真实会话
850
1637
  get 读取会话详情
851
1638
  messages 读取消息窗口
852
1639
  runtime 读取运行态
@@ -855,6 +1642,7 @@ codingns assistant sessions
855
1642
 
856
1643
  示例:
857
1644
  codingns assistant sessions list --project <projectId> --token <token>
1645
+ codingns assistant sessions start --project <projectId> --message "继续处理这个问题" --token <token>
858
1646
  codingns assistant sessions send <sessionId> --message "继续修复" --token <token>
859
1647
  `.trim();
860
1648
  case "sessions.list":
@@ -866,6 +1654,16 @@ codingns assistant sessions list
866
1654
 
867
1655
  用法:
868
1656
  codingns assistant sessions list --project <projectId> --token <token>
1657
+ `.trim();
1658
+ case "sessions.start":
1659
+ return `
1660
+ codingns assistant sessions start
1661
+
1662
+ 用途:
1663
+ 在指定 project/workspace/sandbox 目标下新建真实会话;如果不显式传 provider/model,会默认继承当前助手控制会话的配置。
1664
+
1665
+ 用法:
1666
+ codingns assistant sessions start (--project <projectId> | --workspace <workspaceId> | --sandbox <sandboxId>) --message "..." [--provider <provider>] [--model <model>] [--reasoning-level <level>] [--permission-mode <mode>] --token <token>
869
1667
  `.trim();
870
1668
  case "sessions.get":
871
1669
  return `
@@ -916,6 +1714,193 @@ codingns assistant sessions fork
916
1714
 
917
1715
  用法:
918
1716
  codingns assistant sessions fork <sessionId> [--source-type session|message] [--message-id <id>] [--strategy auto|native-only|reconstruct-only] [--target-provider <provider>] --token <token>
1717
+ `.trim();
1718
+ case "sandboxes":
1719
+ return `
1720
+ codingns assistant sandboxes
1721
+
1722
+ 可用动作:
1723
+ list 列出当前助手沙箱
1724
+ create 创建新的临时沙箱工作区
1725
+ promote 把沙箱保留为 pinned,或晋升成正式项目
1726
+ expire 标记沙箱过期
1727
+ remove 清理沙箱
1728
+
1729
+ 示例:
1730
+ codingns assistant sandboxes list --status active --token <token>
1731
+ codingns assistant sandboxes create --title "CodingNS 临时沙箱" --source-kind clone --repository-url <url> --token <token>
1732
+ `.trim();
1733
+ case "sandboxes.list":
1734
+ return `
1735
+ codingns assistant sandboxes list
1736
+
1737
+ 用途:
1738
+ 列出当前用户可见的助手沙箱。
1739
+
1740
+ 用法:
1741
+ codingns assistant sandboxes list [--status active|archived|expired|deleted] --token <token>
1742
+ `.trim();
1743
+ case "sandboxes.create":
1744
+ return `
1745
+ codingns assistant sandboxes create
1746
+
1747
+ 用途:
1748
+ 创建新的临时沙箱工作区;默认空白沙箱,也可以直接 clone 仓库。
1749
+
1750
+ 用法:
1751
+ codingns assistant sandboxes create [--title <title>] [--description <text>] [--purpose <text>] [--expires-at <isoTime>] [--source-kind blank|clone] [--repository-url <url>] [--directory-name <name>] [--auth-mode none|basic|token] [--username <name>] [--password <password>] [--auth-token <token>] --token <token>
1752
+ `.trim();
1753
+ case "sandboxes.promote":
1754
+ return `
1755
+ codingns assistant sandboxes promote
1756
+
1757
+ 用途:
1758
+ 把沙箱保留为 pinned,或者直接晋升成正式项目。
1759
+
1760
+ 用法:
1761
+ codingns assistant sandboxes promote <sandboxId> [--mode pin|project] [--project-name <name>] [--provider <provider>] --token <token>
1762
+ `.trim();
1763
+ case "sandboxes.expire":
1764
+ return `
1765
+ codingns assistant sandboxes expire
1766
+
1767
+ 用途:
1768
+ 把指定沙箱标记为过期,后续不能再拿它启动会话。
1769
+
1770
+ 用法:
1771
+ codingns assistant sandboxes expire <sandboxId> --token <token>
1772
+ `.trim();
1773
+ case "sandboxes.remove":
1774
+ return `
1775
+ codingns assistant sandboxes remove
1776
+
1777
+ 用途:
1778
+ 删除指定沙箱并尝试清理对应工作区入口。
1779
+
1780
+ 用法:
1781
+ codingns assistant sandboxes remove <sandboxId> --token <token>
1782
+ `.trim();
1783
+ case "automations":
1784
+ return `
1785
+ codingns assistant automations
1786
+
1787
+ 可用动作:
1788
+ list 列出正式自动化任务
1789
+ get 读取单个自动化详情
1790
+ create 创建正式自动化任务
1791
+ cancel 取消自动化任务
1792
+ runs 查看自动化执行记录
1793
+
1794
+ 示例:
1795
+ codingns assistant automations create --after-seconds 3600 --message "1 小时后检查 codingns 新 tag" --session-id <sessionId> --project-id <projectId> --token <token>
1796
+ codingns assistant automations create --trigger interval --every-hours 1 --message "每小时检查一次" --token <token>
1797
+ codingns assistant automations create --trigger cron --cron-minute 30 --cron-hour 9 --cron-day-of-week 1 --cron-day-of-week 2 --message "工作日早上检查" --token <token>
1798
+ codingns assistant automations create --trigger condition --condition-kind git.remote_tag_changed --repository-url <url> --poll-interval-seconds 3600 --message "发现新 tag 后通知我" --include-trigger-context --token <token>
1799
+ codingns assistant automations list --status active --token <token>
1800
+ `.trim();
1801
+ case "automations.list":
1802
+ return `
1803
+ codingns assistant automations list
1804
+
1805
+ 用途:
1806
+ 查看当前助手控制会话下的正式自动化任务。
1807
+
1808
+ 用法:
1809
+ codingns assistant automations list [--status active|completed|cancelled|failed] [--control-session-id <id>] --token <token>
1810
+ `.trim();
1811
+ case "automations.get":
1812
+ return `
1813
+ codingns assistant automations get
1814
+
1815
+ 用途:
1816
+ 读取单个自动化任务详情。
1817
+
1818
+ 用法:
1819
+ codingns assistant automations get <automationId> --token <token>
1820
+ `.trim();
1821
+ case "automations.create":
1822
+ return `
1823
+ codingns assistant automations create
1824
+
1825
+ 用途:
1826
+ 创建正式自动化;支持 once / interval / cron / condition 四种触发器。
1827
+
1828
+ 用法:
1829
+ codingns assistant automations create --message "..." [--trigger once|interval|cron|condition] [--title <title>] [--due-at <isoTime> | --after-seconds <seconds>] [--every-seconds <n> | --every-minutes <n> | --every-hours <n>] [--stop-at <isoTime>] [--cron-minute <0-59>] [--cron-hour <0-23>] [--cron-day-of-week <0-6>] [--condition-kind git.remote_tag_changed|session.runtime_idle] [--repository-url <url>] [--condition-session-id <sessionId>] [--poll-interval-seconds <n>] [--expires-at <isoTime>] [--max-checks <n>] [--include-trigger-context] [--control-session-id <id>] [--project-id <projectId>] [--session-id <sessionId>] --token <token>
1830
+ `.trim();
1831
+ case "automations.cancel":
1832
+ return `
1833
+ codingns assistant automations cancel
1834
+
1835
+ 用途:
1836
+ 取消一个尚未执行的自动化任务。
1837
+
1838
+ 用法:
1839
+ codingns assistant automations cancel <automationId> --token <token>
1840
+ `.trim();
1841
+ case "automations.runs":
1842
+ return `
1843
+ codingns assistant automations runs
1844
+
1845
+ 用途:
1846
+ 查看某个自动化任务的执行记录。
1847
+
1848
+ 用法:
1849
+ codingns assistant automations runs <automationId> --token <token>
1850
+ `.trim();
1851
+ case "timers":
1852
+ return `
1853
+ codingns assistant timers
1854
+
1855
+ 可用动作:
1856
+ list 列出当前助手会话相关的计时器
1857
+ get 读取单个计时器详情
1858
+ create 创建到点后继续助手会话的计时器
1859
+ cancel 取消计时器
1860
+
1861
+ 示例:
1862
+ codingns assistant timers create --after-seconds 300 --message "5 分钟后检查真实会话最新回复" --session-id <sessionId> --project-id <projectId> --token <token>
1863
+ codingns assistant timers list --status active --token <token>
1864
+ `.trim();
1865
+ case "timers.list":
1866
+ return `
1867
+ codingns assistant timers list
1868
+
1869
+ 用途:
1870
+ 查看当前助手会话下仍在等待、已完成或已失败的计时器。
1871
+
1872
+ 用法:
1873
+ codingns assistant timers list [--status active|completed|cancelled|failed] [--control-session-id <id>] --token <token>
1874
+ `.trim();
1875
+ case "timers.get":
1876
+ return `
1877
+ codingns assistant timers get
1878
+
1879
+ 用途:
1880
+ 读取单个计时器详情,包括计划触发时间和最后错误。
1881
+
1882
+ 用法:
1883
+ codingns assistant timers get <timerId> --token <token>
1884
+ `.trim();
1885
+ case "timers.create":
1886
+ return `
1887
+ codingns assistant timers create
1888
+
1889
+ 用途:
1890
+ 创建一个一次性计时器;到期后系统会自动向同一个助手控制会话发送消息,继续工作。
1891
+
1892
+ 用法:
1893
+ codingns assistant timers create --message "..." [--title <title>] [--due-at <isoTime> | --after-seconds <seconds>] [--control-session-id <id>] [--project-id <projectId>] [--session-id <sessionId>] --token <token>
1894
+ `.trim();
1895
+ case "timers.cancel":
1896
+ return `
1897
+ codingns assistant timers cancel
1898
+
1899
+ 用途:
1900
+ 取消一个尚未触发的计时器。
1901
+
1902
+ 用法:
1903
+ codingns assistant timers cancel <timerId> --token <token>
919
1904
  `.trim();
920
1905
  case "terminals":
921
1906
  return `
@@ -925,6 +1910,7 @@ codingns assistant terminals
925
1910
  list 列出项目或工作区下的终端
926
1911
  history 读取终端历史输出
927
1912
  send 向受控终端发送输入
1913
+ close 关闭受控终端
928
1914
 
929
1915
  示例:
930
1916
  codingns assistant terminals list --project-id <projectId> --token <token>
@@ -959,29 +1945,262 @@ codingns assistant terminals send
959
1945
 
960
1946
  用法:
961
1947
  codingns assistant terminals send <terminalId> --input "npm test\\n" --token <token>
1948
+ `.trim();
1949
+ case "terminals.close":
1950
+ return `
1951
+ codingns assistant terminals close
1952
+
1953
+ 用途:
1954
+ 关闭指定受控终端,常用于停止调试进程或回收运行资源。
1955
+
1956
+ 用法:
1957
+ codingns assistant terminals close <terminalId> --token <token>
1958
+ `.trim();
1959
+ case "debug-targets":
1960
+ return `
1961
+ codingns assistant debug-targets
1962
+
1963
+ 可用动作:
1964
+ compatibility-matrix 读取框架兼容矩阵
1965
+ analyze 分析工作区调试目标
1966
+ framework-analysis 读取框架分析结果
1967
+ refresh-framework-analysis 刷新框架分析结果
1968
+ launch-plan 生成启动计划,可显式请求端口
1969
+ run 启动调试目标,可显式请求端口
1970
+ runtime-latest 读取最近一次运行态
1971
+ runtimes 读取运行历史
1972
+
1973
+ 示例:
1974
+ codingns assistant debug-targets analyze --workspace-id <id> --root-path /repo/demo --token <token>
1975
+ codingns assistant debug-targets launch-plan <targetId> --port-request role=backend,cwd=apps/api,port=44001 --token <token>
1976
+ `.trim();
1977
+ case "debug-targets.compatibility-matrix":
1978
+ return `
1979
+ codingns assistant debug-targets compatibility-matrix
1980
+
1981
+ 用途:
1982
+ 读取平台当前支持的框架兼容矩阵和建议注入方式。
1983
+
1984
+ 用法:
1985
+ codingns assistant debug-targets compatibility-matrix --token <token>
1986
+ `.trim();
1987
+ case "debug-targets.analyze":
1988
+ return `
1989
+ codingns assistant debug-targets analyze
1990
+
1991
+ 用途:
1992
+ 分析指定工作区下的调试目标、服务和框架兼容性。
1993
+
1994
+ 用法:
1995
+ codingns assistant debug-targets analyze --workspace-id <id> --root-path <path> [--command-hint "pnpm dev"] [--command-hint "node server.js"] --token <token>
1996
+ `.trim();
1997
+ case "debug-targets.framework-analysis":
1998
+ return `
1999
+ codingns assistant debug-targets framework-analysis
2000
+
2001
+ 用途:
2002
+ 读取指定调试目标当前的框架分析结果。
2003
+
2004
+ 用法:
2005
+ codingns assistant debug-targets framework-analysis <targetId> --token <token>
2006
+ `.trim();
2007
+ case "debug-targets.refresh-framework-analysis":
2008
+ return `
2009
+ codingns assistant debug-targets refresh-framework-analysis
2010
+
2011
+ 用途:
2012
+ 刷新指定调试目标的框架分析结果。
2013
+
2014
+ 用法:
2015
+ codingns assistant debug-targets refresh-framework-analysis <targetId> --token <token>
2016
+ `.trim();
2017
+ case "debug-targets.launch-plan":
2018
+ return `
2019
+ codingns assistant debug-targets launch-plan
2020
+
2021
+ 用途:
2022
+ 生成调试目标启动计划,可通过重复的 --port-request 显式请求服务端口。
2023
+
2024
+ 用法:
2025
+ codingns assistant debug-targets launch-plan <targetId> [--port-request role=frontend,cwd=apps/web,port=43001] [--port-request role=backend,cwd=apps/api,port=44001] --token <token>
2026
+ `.trim();
2027
+ case "debug-targets.run":
2028
+ return `
2029
+ codingns assistant debug-targets run
2030
+
2031
+ 用途:
2032
+ 启动调试目标,可选指定 shell、runtimeType 和显式端口请求。
2033
+
2034
+ 用法:
2035
+ codingns assistant debug-targets run <targetId> [--shell zsh] [--runtime-type tmux|embedded-pty|conpty-powershell|conpty-cmd|conpty-git-bash] [--port-request role=backend,cwd=apps/api,port=44001] --token <token>
2036
+ `.trim();
2037
+ case "debug-targets.runtime-latest":
2038
+ return `
2039
+ codingns assistant debug-targets runtime-latest
2040
+
2041
+ 用途:
2042
+ 读取指定调试目标最近一次运行态,没有运行记录时返回 null。
2043
+
2044
+ 用法:
2045
+ codingns assistant debug-targets runtime-latest <targetId> --token <token>
2046
+ `.trim();
2047
+ case "debug-targets.runtimes":
2048
+ return `
2049
+ codingns assistant debug-targets runtimes
2050
+
2051
+ 用途:
2052
+ 读取指定调试目标最近几次运行历史。
2053
+
2054
+ 用法:
2055
+ codingns assistant debug-targets runtimes <targetId> [--limit 5] --token <token>
2056
+ `.trim();
2057
+ case "debug-runtimes":
2058
+ return `
2059
+ codingns assistant debug-runtimes
2060
+
2061
+ 可用动作:
2062
+ get 读取单个调试运行时详情
2063
+
2064
+ 示例:
2065
+ codingns assistant debug-runtimes get <runtimeId> --token <token>
2066
+ `.trim();
2067
+ case "debug-runtimes.get":
2068
+ return `
2069
+ codingns assistant debug-runtimes get
2070
+
2071
+ 用途:
2072
+ 读取指定调试运行时详情,包括服务、绑定、租约和终端实例。
2073
+
2074
+ 用法:
2075
+ codingns assistant debug-runtimes get <runtimeId> --token <token>
2076
+ `.trim();
2077
+ case "worktrees":
2078
+ return `
2079
+ codingns assistant worktrees
2080
+
2081
+ 可用动作:
2082
+ tree 读取工作树结构
2083
+ create 创建子工作树
2084
+ merge-preview 读取合并预览
2085
+ merge 合并回父工作区
2086
+ cleanup 清理子工作树
2087
+
2088
+ 示例:
2089
+ codingns assistant worktrees tree --root-workspace-id <id> --token <token>
2090
+ codingns assistant worktrees create --source-workspace-id <id> --branch-name feature/demo --token <token>
2091
+ `.trim();
2092
+ case "worktrees.tree":
2093
+ return `
2094
+ codingns assistant worktrees tree
2095
+
2096
+ 用途:
2097
+ 读取某个根工作区下面的工作树结构。
2098
+
2099
+ 用法:
2100
+ codingns assistant worktrees tree --root-workspace-id <id> --token <token>
2101
+ `.trim();
2102
+ case "worktrees.create":
2103
+ return `
2104
+ codingns assistant worktrees create
2105
+
2106
+ 用途:
2107
+ 从指定工作区创建新的子工作树。
2108
+
2109
+ 用法:
2110
+ codingns assistant worktrees create --source-workspace-id <id> --branch-name <name> [--display-name <name>] [--base-ref <ref>] --token <token>
2111
+ `.trim();
2112
+ case "worktrees.merge-preview":
2113
+ return `
2114
+ codingns assistant worktrees merge-preview
2115
+
2116
+ 用途:
2117
+ 查看子工作树合并回父工作区前的阻塞项和预览。
2118
+
2119
+ 用法:
2120
+ codingns assistant worktrees merge-preview <workspaceId> --token <token>
2121
+ `.trim();
2122
+ case "worktrees.merge":
2123
+ return `
2124
+ codingns assistant worktrees merge
2125
+
2126
+ 用途:
2127
+ 把子工作树合并回父工作区。
2128
+
2129
+ 用法:
2130
+ codingns assistant worktrees merge <workspaceId> --token <token>
2131
+ `.trim();
2132
+ case "worktrees.cleanup":
2133
+ return `
2134
+ codingns assistant worktrees cleanup
2135
+
2136
+ 用途:
2137
+ 清理已经完成的子工作树,可选同时删除分支。
2138
+
2139
+ 用法:
2140
+ codingns assistant worktrees cleanup <workspaceId> [--delete-branch] --token <token>
962
2141
  `.trim();
963
2142
  default:
964
2143
  return `
965
2144
  codingns assistant 用法:
966
2145
 
967
- codingns assistant help [capabilities|projects|sessions|terminals] [action]
2146
+ codingns assistant help [capabilities|projects|sessions|sandboxes|automations|timers|terminals|debug-targets|debug-runtimes|workspaces|worktrees] [action]
968
2147
  codingns assistant capabilities list [--base-url http://127.0.0.1:3002] --token <token>
969
2148
  codingns assistant projects list [--workspace-id <id>] [--status active|paused|archived] [--risk-level low|medium|high] --token <token>
970
2149
  codingns assistant projects get <projectId> [--base-url ...] --token <token>
2150
+ codingns assistant debug-targets compatibility-matrix [--base-url ...] --token <token>
2151
+ codingns assistant debug-targets analyze --workspace-id <id> --root-path <path> [--command-hint <command>] [--command-hint <command>] [--base-url ...] --token <token>
2152
+ codingns assistant debug-targets framework-analysis <targetId> [--base-url ...] --token <token>
2153
+ codingns assistant debug-targets refresh-framework-analysis <targetId> [--base-url ...] --token <token>
2154
+ codingns assistant debug-targets launch-plan <targetId> [--port-request role=backend,cwd=apps/api,port=44001] [--base-url ...] --token <token>
2155
+ codingns assistant debug-targets run <targetId> [--shell zsh] [--runtime-type tmux|embedded-pty|conpty-powershell|conpty-cmd|conpty-git-bash] [--port-request role=backend,cwd=apps/api,port=44001] [--base-url ...] --token <token>
2156
+ codingns assistant debug-targets runtime-latest <targetId> [--base-url ...] --token <token>
2157
+ codingns assistant debug-targets runtimes <targetId> [--limit 5] [--base-url ...] --token <token>
2158
+ codingns assistant debug-runtimes get <runtimeId> [--base-url ...] --token <token>
2159
+ codingns assistant workspaces list [--base-url ...] --token <token>
2160
+ codingns assistant workspaces browse [--path <path>] [--base-url ...] --token <token>
2161
+ codingns assistant workspaces mkdir --parent-path <path> --directory-name <name> [--base-url ...] --token <token>
2162
+ codingns assistant workspaces import --path <path> [--name <name>] [--base-url ...] --token <token>
2163
+ codingns assistant workspaces clone --repository-url <url> --parent-path <path> [--directory-name <name>] [--name <name>] [--auth-mode none|basic|token] [--username <name>] [--password <password>] [--auth-token <token>] [--base-url ...] --token <token>
2164
+ codingns assistant workspaces reorder --workspace-id <id> [--workspace-id <id>] [--base-url ...] --token <token>
2165
+ codingns assistant workspaces management <workspaceId> [--base-url ...] --token <token>
2166
+ codingns assistant workspaces nav-state <workspaceId> [--collapsed true|false] [--background-color #RRGGBB|none] [--base-url ...] --token <token>
2167
+ codingns assistant workspaces remove <workspaceId> [--base-url ...] --token <token>
971
2168
  codingns assistant sessions list --project <projectId> [--base-url ...] --token <token>
2169
+ codingns assistant sessions start (--project <projectId> | --workspace <workspaceId> | --sandbox <sandboxId>) --message "..." [--provider <provider>] [--model <model>] [--reasoning-level <level>] [--permission-mode <mode>] --token <token>
972
2170
  codingns assistant sessions get <sessionId> [--base-url ...] --token <token>
973
2171
  codingns assistant sessions messages <sessionId> [--cursor <cursor>] [--limit 40] [--direction forward|backward] --token <token>
974
2172
  codingns assistant sessions runtime <sessionId> [--base-url ...] --token <token>
975
2173
  codingns assistant sessions send <sessionId> --message "..." [--client-request-id <id>] [--model <model>] [--reasoning-level <level>] [--permission-mode <mode>] --token <token>
976
2174
  codingns assistant sessions fork <sessionId> [--source-type session|message] [--message-id <id>] [--strategy auto|native-only|reconstruct-only] [--target-provider <provider>] --token <token>
2175
+ codingns assistant sandboxes list [--status active|archived|expired|deleted] [--base-url ...] --token <token>
2176
+ codingns assistant sandboxes create [--title <title>] [--description <text>] [--purpose <text>] [--expires-at <isoTime>] [--source-kind blank|clone] [--repository-url <url>] [--directory-name <name>] [--auth-mode none|basic|token] [--username <name>] [--password <password>] [--auth-token <token>] [--base-url ...] --token <token>
2177
+ codingns assistant sandboxes promote <sandboxId> [--mode pin|project] [--project-name <name>] [--provider <provider>] [--base-url ...] --token <token>
2178
+ codingns assistant sandboxes expire <sandboxId> [--base-url ...] --token <token>
2179
+ codingns assistant sandboxes remove <sandboxId> [--base-url ...] --token <token>
2180
+ codingns assistant automations list [--status active|completed|cancelled|failed] [--control-session-id <id>] --token <token>
2181
+ codingns assistant automations get <automationId> [--base-url ...] --token <token>
2182
+ codingns assistant automations create --message "..." [--trigger once|interval|cron|condition] [--title <title>] [--due-at <isoTime> | --after-seconds <seconds>] [--every-seconds <n> | --every-minutes <n> | --every-hours <n>] [--stop-at <isoTime>] [--cron-minute <0-59>] [--cron-hour <0-23>] [--cron-day-of-week <0-6>] [--condition-kind git.remote_tag_changed|session.runtime_idle] [--repository-url <url>] [--condition-session-id <sessionId>] [--poll-interval-seconds <n>] [--expires-at <isoTime>] [--max-checks <n>] [--include-trigger-context] [--control-session-id <id>] [--project-id <projectId>] [--session-id <sessionId>] --token <token>
2183
+ codingns assistant automations cancel <automationId> [--base-url ...] --token <token>
2184
+ codingns assistant automations runs <automationId> [--base-url ...] --token <token>
2185
+ codingns assistant timers list [--status active|completed|cancelled|failed] [--control-session-id <id>] --token <token>
2186
+ codingns assistant timers get <timerId> [--base-url ...] --token <token>
2187
+ codingns assistant timers create --message "..." [--title <title>] [--due-at <isoTime> | --after-seconds <seconds>] [--control-session-id <id>] [--project-id <projectId>] [--session-id <sessionId>] --token <token>
2188
+ codingns assistant timers cancel <timerId> [--base-url ...] --token <token>
977
2189
  codingns assistant terminals list [--workspace-id <id> | --project-id <id>] --token <token>
978
2190
  codingns assistant terminals history <terminalId> [--before-seq <n>] [--limit 20] --token <token>
979
2191
  codingns assistant terminals send <terminalId> --input "npm test\\n" --token <token>
2192
+ codingns assistant terminals close <terminalId> [--base-url ...] --token <token>
2193
+ codingns assistant worktrees tree --root-workspace-id <id> [--base-url ...] --token <token>
2194
+ codingns assistant worktrees create --source-workspace-id <id> --branch-name <name> [--display-name <name>] [--base-ref <ref>] [--base-url ...] --token <token>
2195
+ codingns assistant worktrees merge-preview <workspaceId> [--base-url ...] --token <token>
2196
+ codingns assistant worktrees merge <workspaceId> [--base-url ...] --token <token>
2197
+ codingns assistant worktrees cleanup <workspaceId> [--delete-branch] [--base-url ...] --token <token>
980
2198
 
981
2199
  环境变量:
982
2200
 
983
2201
  CODINGNS_BASE_URL 默认 Host 地址,未传时默认 http://127.0.0.1:3002
984
2202
  CODINGNS_ACCESS_TOKEN 默认 Bearer token
2203
+ CODINGNS_AUTH_FILE 可选认证文件,支持读取 apiBaseUrl/accessToken
985
2204
  `.trim();
986
2205
  }
987
2206
  }
@@ -1041,6 +2260,7 @@ codingns skills 用法:
1041
2260
 
1042
2261
  CODINGNS_BASE_URL 默认 Host 地址,未传时默认 http://127.0.0.1:3002
1043
2262
  CODINGNS_ACCESS_TOKEN 默认 Bearer token
2263
+ CODINGNS_AUTH_FILE 可选认证文件,支持读取 apiBaseUrl/accessToken
1044
2264
  `.trim();
1045
2265
  }
1046
2266
  }
@@ -1057,6 +2277,145 @@ function buildAssistantHelpTopic(action, rest) {
1057
2277
  return `${action}.${rest[0]}`;
1058
2278
  }
1059
2279
 
2280
+ function resolveAssistantSessionStartTarget(values) {
2281
+ const projectId = readOptionalTrimmedValue(values.project);
2282
+ const workspaceId = readOptionalTrimmedValue(values.workspace);
2283
+ const sandboxId = readOptionalTrimmedValue(values.sandbox);
2284
+ const targets = [
2285
+ projectId ? { projectId } : null,
2286
+ workspaceId ? { workspaceId } : null,
2287
+ sandboxId ? { sandboxId } : null
2288
+ ].filter((item) => item !== null);
2289
+
2290
+ if (targets.length !== 1) {
2291
+ fail("sessions start 必须且只能提供 --project、--workspace、--sandbox 其中一个");
2292
+ }
2293
+
2294
+ return targets[0];
2295
+ }
2296
+
2297
+ function buildWorkspaceCloneAuth(values) {
2298
+ const authMode = readOptionalTrimmedValue(values["auth-mode"]);
2299
+
2300
+ if (!authMode || authMode === "none") {
2301
+ return authMode === "none" ? { mode: "none" } : undefined;
2302
+ }
2303
+
2304
+ if (authMode === "basic") {
2305
+ return {
2306
+ mode: "basic",
2307
+ username: readOptionalTrimmedValue(values.username),
2308
+ password: readOptionalTrimmedValue(values.password)
2309
+ };
2310
+ }
2311
+
2312
+ if (authMode === "token") {
2313
+ return {
2314
+ mode: "token",
2315
+ username: readOptionalTrimmedValue(values.username),
2316
+ token: readOptionalTrimmedValue(values["auth-token"])
2317
+ };
2318
+ }
2319
+
2320
+ fail(`不支持的 --auth-mode:${authMode}`);
2321
+ }
2322
+
2323
+ function parseDebugPortRequests(value) {
2324
+ const values = Array.isArray(value)
2325
+ ? value
2326
+ : typeof value === "string"
2327
+ ? [value]
2328
+ : [];
2329
+
2330
+ return values
2331
+ .map((item) => item.trim())
2332
+ .filter((item) => item.length > 0)
2333
+ .map((item) => parseDebugPortRequest(item));
2334
+ }
2335
+
2336
+ function parseDebugPortRequest(value) {
2337
+ const segments = value
2338
+ .split(",")
2339
+ .map((item) => item.trim())
2340
+ .filter((item) => item.length > 0);
2341
+ const request = {
2342
+ serviceId: null,
2343
+ role: null,
2344
+ cwd: null,
2345
+ name: null,
2346
+ command: null,
2347
+ port: null
2348
+ };
2349
+
2350
+ for (const segment of segments) {
2351
+ const [rawKey, ...rest] = segment.split("=");
2352
+ const key = rawKey?.trim().toLowerCase() ?? "";
2353
+ const parsedValue = rest.join("=").trim();
2354
+
2355
+ if (!key || !parsedValue) {
2356
+ fail(`无效的 --port-request:${value}`);
2357
+ }
2358
+
2359
+ switch (key) {
2360
+ case "service-id":
2361
+ request.serviceId = parsedValue;
2362
+ break;
2363
+ case "role":
2364
+ request.role = parsedValue;
2365
+ break;
2366
+ case "cwd":
2367
+ request.cwd = parsedValue;
2368
+ break;
2369
+ case "name":
2370
+ request.name = parsedValue;
2371
+ break;
2372
+ case "command":
2373
+ request.command = parsedValue;
2374
+ break;
2375
+ case "port": {
2376
+ const port = Number.parseInt(parsedValue, 10);
2377
+
2378
+ if (!Number.isInteger(port)) {
2379
+ fail(`--port-request 中的 port 非法:${parsedValue}`);
2380
+ }
2381
+
2382
+ request.port = port;
2383
+ break;
2384
+ }
2385
+ default:
2386
+ fail(`--port-request 不支持的键:${rawKey}`);
2387
+ }
2388
+ }
2389
+
2390
+ if (!Number.isInteger(request.port)) {
2391
+ fail(`--port-request 缺少 port:${value}`);
2392
+ }
2393
+
2394
+ if (!request.serviceId && !request.role && !request.cwd && !request.name && !request.command) {
2395
+ fail(`--port-request 至少要提供 service-id、role、cwd、name、command 之一:${value}`);
2396
+ }
2397
+
2398
+ return request;
2399
+ }
2400
+
2401
+ function parseBooleanOption(value, field) {
2402
+ const normalized = value.toLowerCase();
2403
+
2404
+ if (normalized === "true") {
2405
+ return true;
2406
+ }
2407
+
2408
+ if (normalized === "false") {
2409
+ return false;
2410
+ }
2411
+
2412
+ fail(`参数 --${field} 只接受 true 或 false`);
2413
+ }
2414
+
2415
+ function normalizeBackgroundColorOption(value) {
2416
+ return value.toLowerCase() === "none" ? null : value;
2417
+ }
2418
+
1060
2419
  function buildSkillsHelpTopic(action) {
1061
2420
  if (!action || action === "--help" || action === "-h") {
1062
2421
  return "skills";