@cjhyy/code-shell-core 0.5.0-rc.2 → 0.6.0-rc.10

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 (396) hide show
  1. package/README.md +13 -10
  2. package/dist/agent/agent-definition-registry.d.ts +3 -0
  3. package/dist/agent/agent-definition-registry.js +3 -1
  4. package/dist/agent/agent-definition.d.ts +15 -0
  5. package/dist/agent/agent-definition.js +27 -3
  6. package/dist/arena/context/context-tools.js +47 -4
  7. package/dist/arena/ledger.js +9 -1
  8. package/dist/arena/strategies/utils.d.ts +1 -4
  9. package/dist/arena/strategies/utils.js +7 -84
  10. package/dist/automation/cron-expr.d.ts +10 -0
  11. package/dist/automation/cron-expr.js +23 -5
  12. package/dist/automation/runner.d.ts +21 -4
  13. package/dist/automation/runner.js +48 -12
  14. package/dist/automation/scheduler.d.ts +38 -0
  15. package/dist/automation/scheduler.js +89 -12
  16. package/dist/automation/store.js +5 -2
  17. package/dist/capability-control/disabled-lists.d.ts +25 -0
  18. package/dist/capability-control/disabled-lists.js +57 -0
  19. package/dist/capability-control/overlay.d.ts +15 -0
  20. package/dist/capability-control/overlay.js +27 -0
  21. package/dist/cc-orchestrator/agent-adapter.d.ts +50 -0
  22. package/dist/cc-orchestrator/agent-adapter.js +133 -0
  23. package/dist/cc-orchestrator/cc-capability.d.ts +19 -0
  24. package/dist/cc-orchestrator/cc-capability.js +53 -0
  25. package/dist/cc-orchestrator/codex-session-discovery.d.ts +24 -0
  26. package/dist/cc-orchestrator/codex-session-discovery.js +191 -0
  27. package/dist/cc-orchestrator/codex-session-history.d.ts +25 -0
  28. package/dist/cc-orchestrator/codex-session-history.js +187 -0
  29. package/dist/cc-orchestrator/external-agent-changes.d.ts +19 -0
  30. package/dist/cc-orchestrator/external-agent-changes.js +214 -0
  31. package/dist/cc-orchestrator/external-agent-driver.d.ts +18 -0
  32. package/dist/cc-orchestrator/external-agent-driver.js +69 -0
  33. package/dist/cc-orchestrator/index.d.ts +8 -0
  34. package/dist/cc-orchestrator/index.js +8 -0
  35. package/dist/cc-orchestrator/relevance-judge.d.ts +15 -0
  36. package/dist/cc-orchestrator/relevance-judge.js +29 -0
  37. package/dist/cc-orchestrator/session-discovery.d.ts +46 -0
  38. package/dist/cc-orchestrator/session-discovery.js +125 -0
  39. package/dist/cc-orchestrator/session-history.d.ts +19 -0
  40. package/dist/cc-orchestrator/session-history.js +67 -0
  41. package/dist/cli/agent-server-stdio.d.ts +15 -1
  42. package/dist/cli/agent-server-stdio.js +115 -17
  43. package/dist/cli/agent-server-tcp.js +40 -26
  44. package/dist/context/compaction.d.ts +86 -0
  45. package/dist/context/compaction.js +279 -0
  46. package/dist/context/manager.d.ts +18 -0
  47. package/dist/context/manager.js +181 -48
  48. package/dist/context/token-counter.js +13 -0
  49. package/dist/cost-tracker.js +5 -61
  50. package/dist/credentials/cipher.d.ts +49 -0
  51. package/dist/credentials/cipher.js +45 -0
  52. package/dist/credentials/cookie-jar.d.ts +24 -0
  53. package/dist/credentials/cookie-jar.js +40 -0
  54. package/dist/credentials/index.d.ts +7 -0
  55. package/dist/credentials/index.js +5 -0
  56. package/dist/credentials/inject-credential-tool.d.ts +20 -0
  57. package/dist/credentials/inject-credential-tool.js +130 -0
  58. package/dist/credentials/store.d.ts +72 -0
  59. package/dist/credentials/store.js +184 -0
  60. package/dist/credentials/types.d.ts +56 -0
  61. package/dist/credentials/use-credential-tool.d.ts +29 -0
  62. package/dist/credentials/use-credential-tool.js +205 -0
  63. package/dist/credentials/use-gate.d.ts +56 -0
  64. package/dist/credentials/use-gate.js +52 -0
  65. package/dist/data/model-metadata.d.ts +77 -0
  66. package/dist/data/model-metadata.js +56 -0
  67. package/dist/data/model-metadata.json +216 -0
  68. package/dist/data/openrouter-models.d.ts +18 -7
  69. package/dist/data/openrouter-models.js +35 -8
  70. package/dist/engine/aux-key.d.ts +10 -0
  71. package/dist/engine/aux-key.js +11 -0
  72. package/dist/engine/dynamic-tool-defs.d.ts +19 -0
  73. package/dist/engine/dynamic-tool-defs.js +36 -0
  74. package/dist/engine/engine.d.ts +280 -141
  75. package/dist/engine/engine.js +1193 -245
  76. package/dist/engine/friendly-error.d.ts +18 -0
  77. package/dist/engine/friendly-error.js +63 -0
  78. package/dist/engine/goal.d.ts +145 -0
  79. package/dist/engine/goal.js +144 -0
  80. package/dist/engine/image-policy.d.ts +13 -0
  81. package/dist/engine/image-policy.js +24 -0
  82. package/dist/engine/model-connections-pool.d.ts +17 -0
  83. package/dist/engine/model-connections-pool.js +67 -0
  84. package/dist/engine/model-facade.d.ts +10 -0
  85. package/dist/engine/model-facade.js +15 -0
  86. package/dist/engine/patch-orphaned-tools.js +3 -0
  87. package/dist/engine/query.js +2 -0
  88. package/dist/engine/resolve-llm-config.d.ts +16 -0
  89. package/dist/engine/resolve-llm-config.js +44 -0
  90. package/dist/engine/runtime.d.ts +2 -0
  91. package/dist/engine/runtime.js +27 -1
  92. package/dist/engine/sandbox-cache-key.d.ts +10 -0
  93. package/dist/engine/sandbox-cache-key.js +9 -0
  94. package/dist/engine/sandbox-config.d.ts +31 -0
  95. package/dist/engine/sandbox-config.js +38 -0
  96. package/dist/engine/session-usage.d.ts +31 -0
  97. package/dist/engine/session-usage.js +81 -0
  98. package/dist/engine/steer-queue.d.ts +33 -0
  99. package/dist/engine/steer-queue.js +26 -0
  100. package/dist/engine/streaming-tool-queue.d.ts +12 -0
  101. package/dist/engine/streaming-tool-queue.js +50 -10
  102. package/dist/engine/turn-loop.d.ts +94 -4
  103. package/dist/engine/turn-loop.js +432 -54
  104. package/dist/engine/types.d.ts +175 -0
  105. package/dist/engine/types.js +13 -0
  106. package/dist/external-agents/config.d.ts +2 -0
  107. package/dist/external-agents/config.js +15 -0
  108. package/dist/external-agents/types.d.ts +31 -0
  109. package/dist/external-agents/types.js +1 -0
  110. package/dist/git/utils.d.ts +12 -0
  111. package/dist/git/utils.js +38 -6
  112. package/dist/git/worktree.d.ts +48 -0
  113. package/dist/git/worktree.js +86 -10
  114. package/dist/hooks/goal-stop-hook.d.ts +28 -0
  115. package/dist/hooks/goal-stop-hook.js +186 -9
  116. package/dist/hooks/registry.d.ts +8 -0
  117. package/dist/hooks/registry.js +19 -0
  118. package/dist/hooks/shell-runner.js +10 -21
  119. package/dist/index.d.ts +51 -7
  120. package/dist/index.js +62 -5
  121. package/dist/llm/capabilities/param-specs.d.ts +14 -0
  122. package/dist/llm/capabilities/param-specs.js +62 -0
  123. package/dist/llm/capabilities/rules.js +5 -1
  124. package/dist/llm/capabilities/types.d.ts +10 -0
  125. package/dist/llm/client-base.d.ts +28 -1
  126. package/dist/llm/client-base.js +119 -13
  127. package/dist/llm/model-cache.js +4 -2
  128. package/dist/llm/model-pool.d.ts +21 -0
  129. package/dist/llm/model-pool.js +21 -1
  130. package/dist/llm/provider-auth.d.ts +41 -0
  131. package/dist/llm/provider-auth.js +76 -0
  132. package/dist/llm/provider-catalog.d.ts +4 -0
  133. package/dist/llm/providers/anthropic.js +64 -14
  134. package/dist/llm/providers/openai.d.ts +36 -0
  135. package/dist/llm/providers/openai.js +257 -51
  136. package/dist/llm/reasoning-setting.d.ts +3 -3
  137. package/dist/llm/reasoning-setting.js +9 -1
  138. package/dist/llm/stream-watchdog.js +5 -1
  139. package/dist/llm/token-counter.js +9 -2
  140. package/dist/llm/types.d.ts +4 -0
  141. package/dist/logging/sanitize-messages.js +22 -0
  142. package/dist/lsp/manager.d.ts +1 -1
  143. package/dist/lsp/manager.js +40 -10
  144. package/dist/model-catalog/builtin.d.ts +12 -0
  145. package/dist/model-catalog/builtin.js +412 -0
  146. package/dist/model-catalog/gen-connections.d.ts +20 -0
  147. package/dist/model-catalog/gen-connections.js +28 -0
  148. package/dist/model-catalog/index.d.ts +41 -0
  149. package/dist/model-catalog/index.js +90 -0
  150. package/dist/model-catalog/params.d.ts +20 -0
  151. package/dist/model-catalog/params.js +45 -0
  152. package/dist/model-catalog/resolve.d.ts +48 -0
  153. package/dist/model-catalog/resolve.js +33 -0
  154. package/dist/model-catalog/save-entry.d.ts +32 -0
  155. package/dist/model-catalog/save-entry.js +104 -0
  156. package/dist/model-catalog/types.d.ts +561 -0
  157. package/dist/model-catalog/types.js +93 -0
  158. package/dist/model-catalog/upsert.d.ts +9 -0
  159. package/dist/model-catalog/upsert.js +8 -0
  160. package/dist/onboarding.d.ts +12 -82
  161. package/dist/onboarding.js +61 -326
  162. package/dist/plugins/gitOps.d.ts +19 -0
  163. package/dist/plugins/gitOps.js +73 -4
  164. package/dist/plugins/installer/checkUpdate.d.ts +16 -0
  165. package/dist/plugins/installer/checkUpdate.js +32 -0
  166. package/dist/plugins/installer/codex/convertCommands.d.ts +19 -0
  167. package/dist/plugins/installer/codex/convertCommands.js +46 -0
  168. package/dist/plugins/installer/codex/convertMcp.d.ts +5 -2
  169. package/dist/plugins/installer/codex/convertMcp.js +45 -5
  170. package/dist/plugins/installer/install.js +25 -1
  171. package/dist/plugins/installer/installFromArchive.d.ts +43 -0
  172. package/dist/plugins/installer/installFromArchive.js +134 -0
  173. package/dist/plugins/installer/installFromSource.js +8 -2
  174. package/dist/plugins/installer/loadPluginAgents.js +6 -2
  175. package/dist/plugins/installer/loadPluginMcp.d.ts +9 -2
  176. package/dist/plugins/installer/loadPluginMcp.js +35 -2
  177. package/dist/plugins/installer/pruneDisabled.d.ts +24 -0
  178. package/dist/plugins/installer/pruneDisabled.js +73 -0
  179. package/dist/plugins/installer/types.d.ts +5 -2
  180. package/dist/plugins/installer/types.js +1 -0
  181. package/dist/plugins/installer/uninstall.js +4 -0
  182. package/dist/plugins/installer/unzip.d.ts +14 -0
  183. package/dist/plugins/installer/unzip.js +82 -0
  184. package/dist/plugins/installer/update.d.ts +14 -0
  185. package/dist/plugins/installer/update.js +53 -21
  186. package/dist/plugins/loadPluginHooks.d.ts +47 -1
  187. package/dist/plugins/loadPluginHooks.js +73 -1
  188. package/dist/plugins/marketplaceManager.d.ts +7 -0
  189. package/dist/plugins/marketplaceManager.js +20 -0
  190. package/dist/plugins/pluginCommandHook.js +4 -18
  191. package/dist/plugins/pluginContent.d.ts +30 -0
  192. package/dist/plugins/pluginContent.js +83 -0
  193. package/dist/plugins/pluginInstaller.d.ts +13 -0
  194. package/dist/plugins/pluginInstaller.js +42 -8
  195. package/dist/plugins/schemas.js +1 -0
  196. package/dist/plugins/types.d.ts +6 -0
  197. package/dist/preset/index.d.ts +11 -1
  198. package/dist/preset/index.js +115 -6
  199. package/dist/product/types.d.ts +1 -1
  200. package/dist/prompt/composer.d.ts +32 -0
  201. package/dist/prompt/composer.js +75 -21
  202. package/dist/prompt/instruction-scanner.js +5 -3
  203. package/dist/prompt/section-loader.js +1 -0
  204. package/dist/prompt/sections/base.md +2 -0
  205. package/dist/prompt/sections/browser.md +10 -0
  206. package/dist/prompt/sections/coding.md +4 -0
  207. package/dist/protocol/chat-session-manager.d.ts +9 -2
  208. package/dist/protocol/chat-session-manager.js +38 -0
  209. package/dist/protocol/chat-session.d.ts +69 -1
  210. package/dist/protocol/chat-session.js +102 -4
  211. package/dist/protocol/client.d.ts +31 -0
  212. package/dist/protocol/client.js +44 -0
  213. package/dist/protocol/server.d.ts +120 -7
  214. package/dist/protocol/server.js +753 -51
  215. package/dist/protocol/transport.js +3 -2
  216. package/dist/protocol/types.d.ts +60 -0
  217. package/dist/protocol/types.js +16 -0
  218. package/dist/quota/credentials.d.ts +3 -0
  219. package/dist/quota/credentials.js +80 -0
  220. package/dist/quota/index.d.ts +36 -0
  221. package/dist/quota/index.js +155 -0
  222. package/dist/quota/types.d.ts +48 -0
  223. package/dist/quota/types.js +13 -0
  224. package/dist/review/review-prompt.d.ts +28 -0
  225. package/dist/review/review-prompt.js +81 -0
  226. package/dist/run/FileRunStore.js +8 -3
  227. package/dist/run/RunApprovalBackend.js +25 -5
  228. package/dist/run/RunManager.d.ts +12 -0
  229. package/dist/run/RunManager.js +35 -0
  230. package/dist/run/factory.d.ts +1 -1
  231. package/dist/runtime/background-shell.d.ts +139 -0
  232. package/dist/runtime/background-shell.js +509 -0
  233. package/dist/runtime/output-clean.d.ts +24 -0
  234. package/dist/runtime/output-clean.js +41 -0
  235. package/dist/runtime/ring-file.d.ts +64 -0
  236. package/dist/runtime/ring-file.js +174 -0
  237. package/dist/runtime/safe-spawn.js +98 -39
  238. package/dist/runtime/spawn-common.d.ts +159 -0
  239. package/dist/runtime/spawn-common.js +404 -0
  240. package/dist/runtime/truncate-output.d.ts +22 -0
  241. package/dist/runtime/truncate-output.js +49 -0
  242. package/dist/runtime/utf8-cut.d.ts +11 -0
  243. package/dist/runtime/utf8-cut.js +23 -0
  244. package/dist/services/auto-dream.d.ts +4 -0
  245. package/dist/services/auto-dream.js +26 -26
  246. package/dist/services/diagnostics.d.ts +1 -2
  247. package/dist/services/diagnostics.js +12 -7
  248. package/dist/services/extract-memories.d.ts +14 -1
  249. package/dist/services/extract-memories.js +45 -6
  250. package/dist/services/memory-orchestrator.d.ts +21 -0
  251. package/dist/services/memory-orchestrator.js +125 -50
  252. package/dist/services/session-memory.js +24 -12
  253. package/dist/session/file-history.d.ts +124 -1
  254. package/dist/session/file-history.js +222 -6
  255. package/dist/session/memory.d.ts +116 -2
  256. package/dist/session/memory.js +250 -28
  257. package/dist/session/session-manager.d.ts +40 -0
  258. package/dist/session/session-manager.js +119 -3
  259. package/dist/session/simple-diff.d.ts +23 -0
  260. package/dist/session/simple-diff.js +84 -0
  261. package/dist/session/transcript.d.ts +29 -1
  262. package/dist/session/transcript.js +56 -2
  263. package/dist/session/undo-target.d.ts +67 -0
  264. package/dist/session/undo-target.js +144 -0
  265. package/dist/settings/disk-defaults.d.ts +9 -2
  266. package/dist/settings/disk-defaults.js +11 -2
  267. package/dist/settings/feature-flags.d.ts +64 -0
  268. package/dist/settings/feature-flags.js +61 -0
  269. package/dist/settings/manager.d.ts +68 -1
  270. package/dist/settings/manager.js +266 -29
  271. package/dist/settings/migrate-config.d.ts +45 -0
  272. package/dist/settings/migrate-config.js +125 -0
  273. package/dist/settings/schema-export.d.ts +25 -0
  274. package/dist/settings/schema-export.js +38 -0
  275. package/dist/settings/schema.d.ts +1186 -771
  276. package/dist/settings/schema.js +268 -97
  277. package/dist/skills/scanner.d.ts +9 -0
  278. package/dist/skills/scanner.js +30 -2
  279. package/dist/stt/resolve-transcribe.d.ts +31 -0
  280. package/dist/stt/resolve-transcribe.js +108 -0
  281. package/dist/stt/transcribe.d.ts +51 -0
  282. package/dist/stt/transcribe.js +65 -0
  283. package/dist/tool-system/browser-bridge.d.ts +226 -0
  284. package/dist/tool-system/browser-bridge.js +163 -0
  285. package/dist/tool-system/builtin/agent-heartbeat.d.ts +49 -0
  286. package/dist/tool-system/builtin/agent-heartbeat.js +89 -0
  287. package/dist/tool-system/builtin/agent-notifications.d.ts +12 -3
  288. package/dist/tool-system/builtin/agent-notifications.js +9 -3
  289. package/dist/tool-system/builtin/agent-output-file.d.ts +38 -0
  290. package/dist/tool-system/builtin/agent-output-file.js +72 -0
  291. package/dist/tool-system/builtin/agent-registry.d.ts +12 -0
  292. package/dist/tool-system/builtin/agent-registry.js +8 -0
  293. package/dist/tool-system/builtin/agent.d.ts +21 -1
  294. package/dist/tool-system/builtin/agent.js +489 -42
  295. package/dist/tool-system/builtin/apply-patch/applier.js +66 -8
  296. package/dist/tool-system/builtin/apply-patch/backup-targets.d.ts +10 -0
  297. package/dist/tool-system/builtin/apply-patch/backup-targets.js +30 -0
  298. package/dist/tool-system/builtin/apply-patch/index.js +0 -15
  299. package/dist/tool-system/builtin/background-jobs.d.ts +76 -0
  300. package/dist/tool-system/builtin/background-jobs.js +124 -0
  301. package/dist/tool-system/builtin/background-shell-tools.d.ts +20 -0
  302. package/dist/tool-system/builtin/background-shell-tools.js +108 -0
  303. package/dist/tool-system/builtin/background-work.d.ts +67 -0
  304. package/dist/tool-system/builtin/background-work.js +86 -0
  305. package/dist/tool-system/builtin/bash-output-style.d.ts +32 -0
  306. package/dist/tool-system/builtin/bash-output-style.js +40 -0
  307. package/dist/tool-system/builtin/bash.d.ts +5 -2
  308. package/dist/tool-system/builtin/bash.js +101 -64
  309. package/dist/tool-system/builtin/browser-tools.d.ts +33 -0
  310. package/dist/tool-system/builtin/browser-tools.js +312 -0
  311. package/dist/tool-system/builtin/cancel-goal.d.ts +31 -0
  312. package/dist/tool-system/builtin/cancel-goal.js +64 -0
  313. package/dist/tool-system/builtin/check-quota.d.ts +15 -0
  314. package/dist/tool-system/builtin/check-quota.js +34 -0
  315. package/dist/tool-system/builtin/config.js +7 -0
  316. package/dist/tool-system/builtin/cron.d.ts +7 -0
  317. package/dist/tool-system/builtin/cron.js +64 -4
  318. package/dist/tool-system/builtin/drive-claude-code.d.ts +30 -0
  319. package/dist/tool-system/builtin/drive-claude-code.js +157 -0
  320. package/dist/tool-system/builtin/edit-model-catalog.d.ts +3 -0
  321. package/dist/tool-system/builtin/edit-model-catalog.js +104 -0
  322. package/dist/tool-system/builtin/edit.js +20 -16
  323. package/dist/tool-system/builtin/eol.d.ts +29 -0
  324. package/dist/tool-system/builtin/eol.js +37 -0
  325. package/dist/tool-system/builtin/file-cache.d.ts +6 -0
  326. package/dist/tool-system/builtin/file-cache.js +8 -0
  327. package/dist/tool-system/builtin/generate-image.d.ts +35 -0
  328. package/dist/tool-system/builtin/generate-image.js +278 -50
  329. package/dist/tool-system/builtin/generate-video.d.ts +55 -0
  330. package/dist/tool-system/builtin/generate-video.js +364 -0
  331. package/dist/tool-system/builtin/glob.js +0 -7
  332. package/dist/tool-system/builtin/grep.d.ts +9 -0
  333. package/dist/tool-system/builtin/grep.js +106 -11
  334. package/dist/tool-system/builtin/image-providers.d.ts +86 -0
  335. package/dist/tool-system/builtin/image-providers.js +190 -0
  336. package/dist/tool-system/builtin/image-uploader.d.ts +33 -0
  337. package/dist/tool-system/builtin/image-uploader.js +74 -0
  338. package/dist/tool-system/builtin/index.d.ts +10 -2
  339. package/dist/tool-system/builtin/index.js +251 -27
  340. package/dist/tool-system/builtin/mcp-tools.js +23 -3
  341. package/dist/tool-system/builtin/memory.js +45 -7
  342. package/dist/tool-system/builtin/notebook-edit.js +0 -7
  343. package/dist/tool-system/builtin/powershell.js +8 -2
  344. package/dist/tool-system/builtin/read.js +10 -10
  345. package/dist/tool-system/builtin/repl.js +4 -1
  346. package/dist/tool-system/builtin/skill.js +9 -0
  347. package/dist/tool-system/builtin/sleep.js +8 -2
  348. package/dist/tool-system/builtin/tool-search.js +25 -7
  349. package/dist/tool-system/builtin/video-providers.d.ts +154 -0
  350. package/dist/tool-system/builtin/video-providers.js +235 -0
  351. package/dist/tool-system/builtin/web-fetch.js +12 -2
  352. package/dist/tool-system/builtin/web-search.js +21 -7
  353. package/dist/tool-system/builtin/worktree.d.ts +2 -1
  354. package/dist/tool-system/builtin/worktree.js +31 -4
  355. package/dist/tool-system/builtin/write.js +0 -6
  356. package/dist/tool-system/context.d.ts +164 -6
  357. package/dist/tool-system/executor.d.ts +3 -1
  358. package/dist/tool-system/executor.js +197 -90
  359. package/dist/tool-system/investigation-guard.js +1 -1
  360. package/dist/tool-system/mcp-manager.d.ts +42 -4
  361. package/dist/tool-system/mcp-manager.js +203 -20
  362. package/dist/tool-system/mcp-stdio-diagnostics.d.ts +9 -0
  363. package/dist/tool-system/mcp-stdio-diagnostics.js +93 -0
  364. package/dist/tool-system/path-policy.d.ts +5 -0
  365. package/dist/tool-system/path-policy.js +307 -8
  366. package/dist/tool-system/permission.d.ts +39 -2
  367. package/dist/tool-system/permission.js +283 -70
  368. package/dist/tool-system/plan-mode-allowlist.d.ts +13 -2
  369. package/dist/tool-system/plan-mode-allowlist.js +24 -2
  370. package/dist/tool-system/registry.d.ts +1 -0
  371. package/dist/tool-system/registry.js +16 -2
  372. package/dist/tool-system/sandbox/index.d.ts +8 -0
  373. package/dist/tool-system/sandbox/index.js +7 -2
  374. package/dist/tool-system/sandbox/off.js +7 -1
  375. package/dist/tool-system/validate-tool-metadata.d.ts +36 -0
  376. package/dist/tool-system/validate-tool-metadata.js +63 -0
  377. package/dist/types.d.ts +252 -7
  378. package/dist/updater.js +20 -9
  379. package/dist/utils/envUtils.d.ts +0 -9
  380. package/dist/utils/envUtils.js +3 -28
  381. package/dist/utils/exec.d.ts +48 -0
  382. package/dist/utils/exec.js +154 -0
  383. package/dist/utils/json.d.ts +12 -0
  384. package/dist/utils/json.js +92 -0
  385. package/dist/utils/theme.d.ts +1 -1
  386. package/dist/utils/theme.js +1 -1
  387. package/dist/utils/toolDisplay.js +0 -1
  388. package/package.json +13 -7
  389. package/dist/agent/coordinator.d.ts +0 -49
  390. package/dist/agent/coordinator.js +0 -77
  391. package/dist/settings/manager.test.js +0 -73
  392. package/dist/tool-system/builtin/remote-trigger.d.ts +0 -6
  393. package/dist/tool-system/builtin/remote-trigger.js +0 -54
  394. package/dist/tool-system/builtin/send-message.d.ts +0 -6
  395. package/dist/tool-system/builtin/send-message.js +0 -47
  396. /package/dist/{settings/manager.test.d.ts → credentials/types.js} +0 -0
@@ -0,0 +1,31 @@
1
+ /**
2
+ * cancel_goal — user-initiated goal ABANDONMENT (distinct from complete_goal).
3
+ *
4
+ * complete_goal = "the goal is fully achieved, stop." cancel_goal = "the user
5
+ * explicitly asked to STOP pursuing this goal even though it isn't done." Both
6
+ * short-circuit the turn loop to a stop and clear the persisted goal so a later
7
+ * bare send won't re-inherit it — but cancel_goal is a controlled escape hatch,
8
+ * NOT a self-judgment the model may make on its own.
9
+ *
10
+ * "Strong intent" guard (the whole point of this tool): the model must NOT
11
+ * cancel a goal on its own initiative — only when the user has clearly asked to
12
+ * stop/abandon it. To make that hard to do accidentally, the schema REQUIRES:
13
+ * - confirm: true — an explicit boolean gate (a bare call is invalid)
14
+ * - reason: string — the user's own words / paraphrase of the request
15
+ * The turn loop only honors the cancellation when confirm === true; anything
16
+ * else records a refusal string and does NOT stop or clear the goal.
17
+ *
18
+ * Shape note: like complete_goal, this is a ToolDefinition + a separate executor
19
+ * returning a string. The loop-level short-circuit lives in turn-loop.ts and
20
+ * keys off CANCEL_GOAL_TOOL_NAME.
21
+ */
22
+ import type { ToolDefinition } from "../../types.js";
23
+ /** Shared with turn-loop.ts's short-circuit check — the name lives in one place. */
24
+ export declare const CANCEL_GOAL_TOOL_NAME = "cancel_goal";
25
+ export declare const cancelGoalToolDef: ToolDefinition;
26
+ /**
27
+ * Executor. Returns a human-readable acknowledgement. The ACTUAL cancellation
28
+ * (stop + clear persisted goal) is enforced in turn-loop.ts, which re-checks
29
+ * confirm===true — this executor's string is only what lands in the transcript.
30
+ */
31
+ export declare function cancelGoalTool(args: Record<string, unknown>): Promise<string>;
@@ -0,0 +1,64 @@
1
+ /**
2
+ * cancel_goal — user-initiated goal ABANDONMENT (distinct from complete_goal).
3
+ *
4
+ * complete_goal = "the goal is fully achieved, stop." cancel_goal = "the user
5
+ * explicitly asked to STOP pursuing this goal even though it isn't done." Both
6
+ * short-circuit the turn loop to a stop and clear the persisted goal so a later
7
+ * bare send won't re-inherit it — but cancel_goal is a controlled escape hatch,
8
+ * NOT a self-judgment the model may make on its own.
9
+ *
10
+ * "Strong intent" guard (the whole point of this tool): the model must NOT
11
+ * cancel a goal on its own initiative — only when the user has clearly asked to
12
+ * stop/abandon it. To make that hard to do accidentally, the schema REQUIRES:
13
+ * - confirm: true — an explicit boolean gate (a bare call is invalid)
14
+ * - reason: string — the user's own words / paraphrase of the request
15
+ * The turn loop only honors the cancellation when confirm === true; anything
16
+ * else records a refusal string and does NOT stop or clear the goal.
17
+ *
18
+ * Shape note: like complete_goal, this is a ToolDefinition + a separate executor
19
+ * returning a string. The loop-level short-circuit lives in turn-loop.ts and
20
+ * keys off CANCEL_GOAL_TOOL_NAME.
21
+ */
22
+ /** Shared with turn-loop.ts's short-circuit check — the name lives in one place. */
23
+ export const CANCEL_GOAL_TOOL_NAME = "cancel_goal";
24
+ export const cancelGoalToolDef = {
25
+ name: CANCEL_GOAL_TOOL_NAME,
26
+ description: "取消(放弃)当前的持久目标。⚠️ 仅当用户明确要求停止/取消/放弃当前目标时才调用本工具;" +
27
+ "绝不要自行判断放弃目标(“目标太难”“暂时做不完”都不是取消理由——那种情况应继续或用 complete_goal)。" +
28
+ "必须传 confirm=true 并在 reason 里复述用户要求取消的原话/意图。调用后目标会被清除,agent 停止。\n" +
29
+ "Cancel (abandon) the current persistent goal. ⚠️ Call this ONLY when the user has EXPLICITLY asked to " +
30
+ "stop/cancel/abandon the goal. NEVER decide to abandon a goal on your own (a hard or unfinished goal is " +
31
+ "NOT a reason to cancel). You MUST pass confirm=true and put the user's own words/intent in `reason`. " +
32
+ "After calling, the goal is cleared and the agent stops.",
33
+ inputSchema: {
34
+ type: "object",
35
+ properties: {
36
+ confirm: {
37
+ type: "boolean",
38
+ description: "必须为 true 才会真正取消目标。缺省或 false 视为无效调用,不会取消。" +
39
+ "Must be true to actually cancel. Missing/false is treated as an invalid call and cancels nothing.",
40
+ },
41
+ reason: {
42
+ type: "string",
43
+ description: "用户要求取消目标的原话或意图复述(必填)。Required: the user's own words / paraphrased request to cancel.",
44
+ },
45
+ },
46
+ required: ["confirm", "reason"],
47
+ },
48
+ };
49
+ /**
50
+ * Executor. Returns a human-readable acknowledgement. The ACTUAL cancellation
51
+ * (stop + clear persisted goal) is enforced in turn-loop.ts, which re-checks
52
+ * confirm===true — this executor's string is only what lands in the transcript.
53
+ */
54
+ export async function cancelGoalTool(args) {
55
+ const confirmed = args.confirm === true;
56
+ const reason = typeof args.reason === "string" ? args.reason.trim() : "";
57
+ if (!confirmed) {
58
+ return ("cancel_goal 未生效:confirm 必须为 true 且需说明用户要求取消的原因。" +
59
+ "(cancel_goal ignored: confirm must be true and a reason is required.)");
60
+ }
61
+ return reason
62
+ ? `目标已按用户要求取消 (goal cancelled by user). Reason: ${reason}`
63
+ : "目标已按用户要求取消 (goal cancelled by user).";
64
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * CheckQuota builtin — thin shell over the `quota/` module.
3
+ *
4
+ * Lets an orchestrating agent read how much CC/Codex quota is left before/while
5
+ * delegating work (DriveAgent), so it can plan: how many to spawn, whether to
6
+ * wait for a reset, or switch providers. See quota/index.ts for the sources.
7
+ *
8
+ * NOTE the cost asymmetry (surfaced in the description): Codex is a free GET;
9
+ * Claude costs ~1 output token because Anthropic only returns quota via
10
+ * response headers. So restrict with `provider` when you only need one.
11
+ */
12
+ import type { ToolDefinition } from "../../types.js";
13
+ import type { ToolContext } from "../context.js";
14
+ export declare const checkQuotaToolDef: ToolDefinition;
15
+ export declare function checkQuotaTool(args: Record<string, unknown>, ctx?: ToolContext): Promise<string>;
@@ -0,0 +1,34 @@
1
+ import { checkQuota, formatQuota } from "../../quota/index.js";
2
+ import { resolveQuotaCredentials } from "../../quota/credentials.js";
3
+ export const checkQuotaToolDef = {
4
+ name: "CheckQuota",
5
+ description: "Check remaining usage/rate-limit quota for the external coding-agent CLIs (Claude Code and/or " +
6
+ "Codex) — the same 5h/7d subscription windows their status lines show. Use before or during " +
7
+ "orchestration (DriveAgent) to plan how much work to hand off, whether to wait for a reset, or " +
8
+ "which provider to use. Returns each provider's 5h/7d used-% and reset time. " +
9
+ "COST: 'codex' is free (reads a usage endpoint). 'claude' costs ~1 token (Anthropic exposes " +
10
+ "quota only via a response header, so this sends a 1-token probe). Pass `provider` to query " +
11
+ "just one and avoid the other's cost/latency.",
12
+ inputSchema: {
13
+ type: "object",
14
+ properties: {
15
+ provider: {
16
+ type: "string",
17
+ enum: ["claude", "codex", "both"],
18
+ description: "Which to check. 'both' (default) queries Claude Code and Codex. 'claude' sends a 1-token probe; 'codex' is free.",
19
+ },
20
+ },
21
+ required: [],
22
+ },
23
+ };
24
+ export async function checkQuotaTool(args, ctx) {
25
+ const which = args.provider === "claude" ? ["claude"] : args.provider === "codex" ? ["codex"] : ["claude", "codex"];
26
+ const creds = await resolveQuotaCredentials();
27
+ const result = await checkQuota({
28
+ creds,
29
+ providers: which,
30
+ signal: ctx?.signal,
31
+ });
32
+ const nowSec = Math.floor(Date.now() / 1000);
33
+ return formatQuota(result, nowSec);
34
+ }
@@ -59,6 +59,13 @@ export async function configTool(args) {
59
59
  obj = obj[parts[i]];
60
60
  }
61
61
  obj[parts[parts.length - 1]] = value;
62
+ // Never resurrect a deleted project root: a recursive mkdir of
63
+ // <cwd>/.code-shell would recreate `cwd` itself as an empty shell when the
64
+ // directory has been deleted (e.g. a stale session pointing at a removed
65
+ // dir). If the project root is gone, the project is gone — don't write.
66
+ if (!existsSync(cwd)) {
67
+ return `Error: project directory does not exist: ${cwd}`;
68
+ }
62
69
  mkdirSync(join(cwd, ".code-shell"), { recursive: true });
63
70
  writeFileSync(configPath, JSON.stringify(settings, null, 2), "utf-8");
64
71
  return `Updated ${key} = ${JSON.stringify(value)}`;
@@ -2,9 +2,16 @@
2
2
  * Cron tools — CronCreate, CronDelete, CronList.
3
3
  */
4
4
  import type { ToolDefinition } from "../../types.js";
5
+ /** Sink notified after a cron job is created/deleted, so the host (Electron
6
+ * main) can reload+arm the scheduler that actually executes jobs. The worker
7
+ * process only persists cron jobs (executionEnabled=false); without this the
8
+ * host never learns about an AI-created job until the user opens the UI. */
9
+ type CronChangedSink = () => void;
10
+ export declare function setCronChangedSink(sink: CronChangedSink | null): void;
5
11
  export declare const cronCreateToolDef: ToolDefinition;
6
12
  export declare function cronCreateTool(args: Record<string, unknown>): Promise<string>;
7
13
  export declare const cronDeleteToolDef: ToolDefinition;
8
14
  export declare function cronDeleteTool(args: Record<string, unknown>): Promise<string>;
9
15
  export declare const cronListToolDef: ToolDefinition;
10
16
  export declare function cronListTool(_args: Record<string, unknown>): Promise<string>;
17
+ export {};
@@ -2,6 +2,19 @@
2
2
  * Cron tools — CronCreate, CronDelete, CronList.
3
3
  */
4
4
  import { cronScheduler } from "../../automation/scheduler.js";
5
+ import { getCurrentSid } from "../../logging/logger.js";
6
+ let cronChangedSink = null;
7
+ export function setCronChangedSink(sink) {
8
+ cronChangedSink = sink;
9
+ }
10
+ function fireCronChanged() {
11
+ try {
12
+ cronChangedSink?.();
13
+ }
14
+ catch {
15
+ // Notifying the host is best-effort; never break the tool on it.
16
+ }
17
+ }
5
18
  export const cronCreateToolDef = {
6
19
  name: "CronCreate",
7
20
  description: "Create a scheduled automation job that runs a prompt on a recurring schedule. " +
@@ -14,7 +27,14 @@ export const cronCreateToolDef = {
14
27
  "'30 8 * * 1' = 8:30am every Monday. Day-of-week: 0=Sunday..6=Saturday.\n\n" +
15
28
  "For calendar schedules, set `timezone` to the user's IANA zone (e.g. 'Asia/Shanghai', " +
16
29
  "'America/New_York'); ask the user if unknown. Set `cwd` to the project the job operates on. " +
17
- "Leave `permissionLevel` as 'read-only' unless the user explicitly wants the job to modify code.",
30
+ "Leave `permissionLevel` as 'read-only' unless the user explicitly wants the job to modify code.\n\n" +
31
+ "SELF-WAKEUP / background-task safety net: you can also schedule THIS job for yourself, with no user " +
32
+ "request, to re-check on a long-running background task (a download, a build, a background shell/agent) " +
33
+ "that might hang and never signal completion. Use a short interval + `once: true` + `continueInSession: true` " +
34
+ "and a `prompt` that reminds you what to check, e.g. schedule '5m', once true, continueInSession true, " +
35
+ "prompt 'check whether the yt-dlp download finished (BashOutput/ListShells); if still running, wait again'. " +
36
+ "You wake back in THIS conversation with full context, inspect the task, and either finish or reschedule. " +
37
+ "This is the right pattern for a simple poll-until-done loop or a hang safety net — prefer it over looping Sleep.",
18
38
  inputSchema: {
19
39
  type: "object",
20
40
  properties: {
@@ -27,7 +47,7 @@ export const cronCreateToolDef = {
27
47
  prompt: { type: "string", description: "The task prompt the agent runs on each execution" },
28
48
  timezone: {
29
49
  type: "string",
30
- description: "IANA timezone for cron-expression schedules (e.g. 'Asia/Shanghai'). Optional; defaults to UTC.",
50
+ description: "IANA timezone for cron-expression schedules (e.g. 'Asia/Shanghai'). Optional; defaults to the host system's timezone.",
31
51
  },
32
52
  cwd: { type: "string", description: "Working directory / project the job runs in. Optional." },
33
53
  permissionLevel: {
@@ -36,6 +56,23 @@ export const cronCreateToolDef = {
36
56
  description: "What the job may do: 'read-only' (monitoring; default), 'workspace-write' (edit files), " +
37
57
  "'full' (edit + run git/gh to open PRs). Use the least privilege the task needs.",
38
58
  },
59
+ once: {
60
+ type: "boolean",
61
+ description: "true = one-shot: run once at the scheduled time, then auto-delete (for 'in N minutes / " +
62
+ "at <time>, do X once' reminders, tasks, or a self-wakeup to re-check a background task). " +
63
+ "Default false = recurring per `schedule`. " +
64
+ "A one-shot still uses `schedule` for its time: interval '10m' = 10 minutes from now; " +
65
+ "cron '0 7 25 6 *' = once at 07:00 on June 25.",
66
+ },
67
+ continueInSession: {
68
+ type: "boolean",
69
+ description: "true = when the job fires, CONTINUE THE CURRENT conversation: the prompt is appended as " +
70
+ "a new user turn to THIS chat session (restored from disk if needed), carrying its full " +
71
+ "transcript / goal / context. Set this when the user says things like '一小时后接着做 / " +
72
+ "继续 / in this conversation'. Default false = a fresh standalone session per run (right " +
73
+ "for independent recurring tasks like daily reports). The current session id is resolved " +
74
+ "automatically — you do NOT supply it.",
75
+ },
39
76
  },
40
77
  required: ["name", "schedule", "prompt"],
41
78
  },
@@ -46,27 +83,48 @@ export async function cronCreateTool(args) {
46
83
  const prompt = args.prompt;
47
84
  if (!name || !schedule || !prompt)
48
85
  return "Error: name, schedule, and prompt are required";
49
- const timezone = typeof args.timezone === "string" ? args.timezone : undefined;
86
+ const timezone = typeof args.timezone === "string"
87
+ ? args.timezone
88
+ : (() => {
89
+ try {
90
+ return Intl.DateTimeFormat().resolvedOptions().timeZone || undefined;
91
+ }
92
+ catch {
93
+ return undefined;
94
+ }
95
+ })();
50
96
  const cwd = typeof args.cwd === "string" ? args.cwd : undefined;
97
+ const once = args.once === true;
51
98
  const permissionLevel = args.permissionLevel === "read-only" ||
52
99
  args.permissionLevel === "workspace-write" ||
53
100
  args.permissionLevel === "full"
54
101
  ? args.permissionLevel
55
102
  : undefined;
103
+ // Resolve "continue this conversation" to the current session id at create
104
+ // time (the model never supplies it — getCurrentSid() reads the running
105
+ // Engine's ALS context). Empty/unknown sid → treat as standalone.
106
+ const resumeSessionId = args.continueInSession === true && getCurrentSid() ? getCurrentSid() : undefined;
56
107
  let job;
57
108
  try {
58
109
  job = cronScheduler.create(name, schedule, prompt, {
59
110
  ...(timezone !== undefined ? { timezone } : {}),
60
111
  ...(cwd !== undefined ? { cwd } : {}),
61
112
  ...(permissionLevel !== undefined ? { permissionLevel } : {}),
113
+ ...(once ? { once: true } : {}),
114
+ ...(resumeSessionId !== undefined ? { resumeSessionId } : {}),
62
115
  });
63
116
  }
64
117
  catch (err) {
65
118
  return `Error: ${err instanceof Error ? err.message : String(err)}`;
66
119
  }
120
+ fireCronChanged();
67
121
  const tz = job.timezone ? ` (${job.timezone})` : "";
68
122
  const next = job.nextRun ? new Date(job.nextRun).toLocaleString() : "n/a";
69
- return `Cron job #${job.id} "${job.name}" created. Schedule: ${job.schedule}${tz}. Next run: ${next}.`;
123
+ const cont = job.resumeSessionId ? "(到点续接当前对话,带上下文)" : "";
124
+ if (job.once) {
125
+ return `一次性任务 #${job.id} "${job.name}" 已创建${cont}。将于 ${next}${tz} 执行一次后自动删除。`;
126
+ }
127
+ return `Cron job #${job.id} "${job.name}" created${cont}. Schedule: ${job.schedule}${tz}. Next run: ${next}.`;
70
128
  }
71
129
  export const cronDeleteToolDef = {
72
130
  name: "CronDelete",
@@ -84,6 +142,8 @@ export async function cronDeleteTool(args) {
84
142
  if (!id)
85
143
  return "Error: jobId is required";
86
144
  const deleted = cronScheduler.delete(id);
145
+ if (deleted)
146
+ fireCronChanged();
87
147
  return deleted ? `Cron job #${id} deleted.` : `Cron job #${id} not found.`;
88
148
  }
89
149
  export const cronListToolDef = {
@@ -0,0 +1,30 @@
1
+ import type { ToolDefinition } from "../../types.js";
2
+ import type { AgentRunResult } from "../../cc-orchestrator/external-agent-driver.js";
3
+ import type { ToolContext } from "../context.js";
4
+ export type DriveCli = "claude" | "codex";
5
+ export declare const driveAgentToolDef: ToolDefinition;
6
+ type PermMode = "default" | "acceptEdits" | "bypassPermissions";
7
+ type Runner = (opts: {
8
+ cli: DriveCli;
9
+ prompt: string;
10
+ resumeSessionId?: string;
11
+ cwd: string;
12
+ permissionMode?: PermMode;
13
+ }) => Promise<AgentRunResult>;
14
+ /** Factory so tests can inject a fake runner. `fixedCli` (back-compat) forces a
15
+ * cli and hides the `cli` arg — that's how DriveClaudeCode stays a thin alias. */
16
+ export declare function makeDriveAgentTool(runner?: Runner, fixedCli?: DriveCli): (args: Record<string, unknown>, ctx?: ToolContext) => Promise<string>;
17
+ export declare const driveAgentTool: (args: Record<string, unknown>, ctx?: ToolContext) => Promise<string>;
18
+ export declare const driveClaudeCodeToolDef: ToolDefinition;
19
+ /** Back-compat factory: a DriveAgent pinned to cli:"claude" with the `cli` arg
20
+ * hidden. The injected `runner` here keeps the old shape (no `cli` field); we
21
+ * adapt it to the generic Runner so existing tests' fakes still work. */
22
+ type LegacyRunner = (opts: {
23
+ prompt: string;
24
+ resumeSessionId?: string;
25
+ cwd: string;
26
+ permissionMode?: PermMode;
27
+ }) => Promise<AgentRunResult>;
28
+ export declare function makeDriveClaudeCodeTool(runner?: LegacyRunner): (args: Record<string, unknown>, ctx?: ToolContext) => Promise<string>;
29
+ export declare const driveClaudeCodeTool: (args: Record<string, unknown>, ctx?: ToolContext) => Promise<string>;
30
+ export {};
@@ -0,0 +1,157 @@
1
+ import { runAgentOnce } from "../../cc-orchestrator/external-agent-driver.js";
2
+ import { claudeAdapter, codexAdapter } from "../../cc-orchestrator/agent-adapter.js";
3
+ import { backgroundJobRegistry } from "./background-jobs.js";
4
+ import { readExternalChangedFiles } from "../../cc-orchestrator/external-agent-changes.js";
5
+ import { notificationQueue } from "./agent-notifications.js";
6
+ const CLI_ADAPTERS = {
7
+ claude: { adapter: claudeAdapter, command: "claude" },
8
+ codex: { adapter: codexAdapter, command: "codex" },
9
+ };
10
+ export const driveAgentToolDef = {
11
+ name: "DriveAgent",
12
+ description: "Delegate a task to an external coding-agent CLI — drives `claude` (Claude Code) or `codex` " +
13
+ "(OpenAI Codex) for one turn. Pick with `cli` (defaults to claude). Use to hand a coding/" +
14
+ "research task to the agent, or continue an existing session of it. " +
15
+ "Runs in the BACKGROUND by default — these tasks are typically long (minutes to hours), so this " +
16
+ "returns immediately and the result is delivered to you later via a completion notification " +
17
+ "that wakes you. Do NOT sleep-poll for it; just continue or end your turn — you'll be woken " +
18
+ "with the result. For a quick task where you want the answer inline, pass background:false. " +
19
+ "It has NO time concept of its own: for 'in N minutes' / 'every N' / looping, use CronCreate " +
20
+ "instead (never sleep). A scheduled CronCreate job runs one codeshell turn whose prompt can " +
21
+ "instruct it to call DriveAgent; to continue a prior session across runs, have that turn pass " +
22
+ "the sessionId this tool returned as resumeSessionId (same cli). To make the single turn work " +
23
+ "longer/deeper, write that into `prompt` (e.g. 'keep working until done'). " +
24
+ "Pass `resumeSessionId` to continue a prior session of the SAME cli (keeps context); omit to start fresh.\n" +
25
+ "SCOPE & BUDGET (read before fanning out): each driven agent consumes a large, SHARED token budget. " +
26
+ "Do NOT launch many agents at once to 'cover more ground' — that burns the budget and leaves every " +
27
+ "task half-done. Default to ONE agent at a time; only run a few in parallel when the work TRULY splits " +
28
+ "into independent pieces, and even then keep the count small (≈2-3). Prefer finishing one task before " +
29
+ "starting the next. " +
30
+ "Make each `prompt` a COMPLETE, self-contained task that instructs the agent to finish the whole thing " +
31
+ "end-to-end and verify its own work before returning — never a vague 'start looking into X'. " +
32
+ "Give it a concrete definition of done and, for open-ended work, a bound (files/scope/steps) so it " +
33
+ "doesn't sprawl. If a big job must be split, split it into a SEQUENCE you drive one at a time (resume " +
34
+ "the same session), not a swarm launched simultaneously.",
35
+ inputSchema: {
36
+ type: "object",
37
+ properties: {
38
+ prompt: { type: "string", description: "The task for the agent. Make it COMPLETE and self-contained: state the goal, a concrete definition of done, and (for open-ended work) an explicit scope bound so it finishes end-to-end and verifies its own work rather than sprawling or stopping half-way." },
39
+ cli: { type: "string", enum: ["claude", "codex"], description: "Which external CLI to drive. 'claude' = Claude Code (default), 'codex' = OpenAI Codex. resumeSessionId is only valid against the same cli that produced it." },
40
+ resumeSessionId: { type: "string", description: "Existing session id to resume (keeps context). Must come from a prior run of the SAME cli. Omit for a fresh session." },
41
+ cwd: { type: "string", description: "Working directory the run operates in." },
42
+ permissionMode: { type: "string", enum: ["default", "acceptEdits", "bypassPermissions"], description: "Permission/sandbox level. Defaults to 'bypassPermissions' (full auto — needed so the agent's tools run unattended; there is no interactive approval loop here). For codex: default→read-only sandbox, acceptEdits→workspace-write, bypassPermissions→no sandbox. Pass 'default'/'acceptEdits' to gate." },
43
+ background: { type: "boolean", description: "Defaults to TRUE: run in the background and notify you on completion (right for long tasks). Pass false to run in the foreground and get the result inline (only for quick tasks)." },
44
+ },
45
+ required: ["prompt", "cwd"],
46
+ },
47
+ };
48
+ const defaultRunner = (opts) => {
49
+ const { adapter, command } = CLI_ADAPTERS[opts.cli];
50
+ return runAgentOnce(adapter, { command, prompt: opts.prompt, resumeSessionId: opts.resumeSessionId, cwd: opts.cwd, permissionMode: opts.permissionMode ?? "default" });
51
+ };
52
+ /** Factory so tests can inject a fake runner. `fixedCli` (back-compat) forces a
53
+ * cli and hides the `cli` arg — that's how DriveClaudeCode stays a thin alias. */
54
+ export function makeDriveAgentTool(runner = defaultRunner, fixedCli) {
55
+ return async (args, ctx) => {
56
+ const prompt = typeof args.prompt === "string" ? args.prompt : "";
57
+ const cwd = typeof args.cwd === "string" ? args.cwd : process.cwd();
58
+ if (!prompt)
59
+ return "Error: prompt is required";
60
+ const cli = fixedCli ?? (args.cli === "codex" ? "codex" : args.cli === "claude" || args.cli === undefined ? "claude" : "invalid");
61
+ if (cli === "invalid")
62
+ return `Error: unknown cli "${String(args.cli)}" (expected "claude" or "codex")`;
63
+ const resumeSessionId = typeof args.resumeSessionId === "string" ? args.resumeSessionId : undefined;
64
+ // Default to bypassPermissions: this tool is a fire-one-turn delegation to
65
+ // an external CLI with nobody watching for approvals, and there is no
66
+ // interactive approval loop here — so under "default" a tool that needs
67
+ // approval (WebSearch/WebFetch/Write) silently can't run (the
68
+ // "DriveClaudeCode 没有联网能力" report). A caller that wants gating passes
69
+ // an explicit mode, which is honored. (For codex, the mode maps to a sandbox
70
+ // tier inside codexAdapter.)
71
+ const permissionMode = args.permissionMode === "default" ||
72
+ args.permissionMode === "acceptEdits" ||
73
+ args.permissionMode === "bypassPermissions"
74
+ ? args.permissionMode
75
+ : "bypassPermissions";
76
+ const cliName = cli === "codex" ? "Codex" : "Claude Code";
77
+ const label = `DriveAgent(${cli}): ${prompt.slice(0, 40)}`;
78
+ // Background by default (these tasks are typically long). Only an explicit
79
+ // background:false runs in the foreground and returns the result inline.
80
+ const background = args.background !== false;
81
+ if (background) {
82
+ // Fail loud on a missing sessionId: a background job whose completion
83
+ // notification can't be routed (enqueue drops invalid/empty sessionId)
84
+ // would run to completion and then silently vanish — nobody gets woken
85
+ // with the result. Refuse up front instead of launching disappearing work.
86
+ const sessionId = ctx?.sessionId;
87
+ if (typeof sessionId !== "string" || sessionId.length === 0) {
88
+ return `Error: cannot start a background ${cliName} job without a session — its result notification would be dropped. Retry with background:false, or ensure the tool runs inside a session.`;
89
+ }
90
+ const jobId = `cc-${process.hrtime.bigint().toString(36)}`;
91
+ backgroundJobRegistry.start(jobId, sessionId, label);
92
+ void runner({ cli, prompt, resumeSessionId, cwd, permissionMode })
93
+ .then((r) => {
94
+ // Deliver the result back so the woken agent actually sees the answer
95
+ // (not just "a job finished"). Mirrors the video/sub-agent completion
96
+ // path — enqueue lands in the same notificationQueue the wakeup drains.
97
+ notificationQueue.enqueue(r.isError
98
+ ? { agentId: jobId, description: label, status: "failed", workKind: "cc", error: r.finalText || "(no output)", ccSessionId: r.sessionId || undefined, enqueuedAt: Date.now() }
99
+ : { agentId: jobId, description: label, status: "completed", workKind: "cc", finalText: r.finalText, ccSessionId: r.sessionId || undefined, enqueuedAt: Date.now() }, sessionId);
100
+ // Attribute the files the external agent changed by parsing its own
101
+ // transcript (#6) — those Edit/Write calls are invisible to the host's
102
+ // in-session aggregator. Best-effort; [] on any failure.
103
+ const changedFiles = r.sessionId
104
+ ? readExternalChangedFiles(cli, cwd, r.sessionId)
105
+ : [];
106
+ // Retain the job in the panel with its result + the external CLI
107
+ // session id + changed files.
108
+ backgroundJobRegistry.finish(jobId, {
109
+ status: r.isError ? "failed" : "completed",
110
+ finalText: r.finalText || undefined,
111
+ ccSessionId: r.sessionId || undefined,
112
+ ...(changedFiles.length ? { changedFiles } : {}),
113
+ });
114
+ })
115
+ .catch((err) => {
116
+ const msg = err?.message ?? String(err);
117
+ notificationQueue.enqueue({ agentId: jobId, description: label, status: "failed", workKind: "cc", error: msg, enqueuedAt: Date.now() }, sessionId);
118
+ backgroundJobRegistry.finish(jobId, { status: "failed", finalText: msg });
119
+ });
120
+ return `已在后台启动 ${cliName}(jobId ${jobId})。完成后会通知你结果,无需轮询。`;
121
+ }
122
+ const r = await runner({ cli, prompt, resumeSessionId, cwd, permissionMode });
123
+ if (r.isError)
124
+ return `${cliName} 运行出错(session ${r.sessionId}):\n${r.finalText}`;
125
+ return `${cliName} 完成(session ${r.sessionId}):\n${r.finalText}`;
126
+ };
127
+ }
128
+ export const driveAgentTool = makeDriveAgentTool();
129
+ // ── Back-compat: DriveClaudeCode = DriveAgent pinned to cli:"claude" ──────────
130
+ // Kept so old prompts / memories / call sites that reference DriveClaudeCode
131
+ // keep working. It's a thin alias over the same machinery (fixedCli "claude").
132
+ export const driveClaudeCodeToolDef = {
133
+ ...driveAgentToolDef,
134
+ name: "DriveClaudeCode",
135
+ description: "(Alias of DriveAgent with cli:claude.) Delegate a task to the external Claude Code CLI " +
136
+ "(drives `claude` for one turn). Prefer DriveAgent for new calls; this name is kept for " +
137
+ "compatibility. " + driveAgentToolDef.description,
138
+ inputSchema: {
139
+ type: "object",
140
+ properties: {
141
+ // intentionally omit `cli` — this alias is always claude
142
+ prompt: driveAgentToolDef.inputSchema.properties.prompt,
143
+ resumeSessionId: { type: "string", description: "Existing CC session id to resume (keeps context). Omit for a fresh session." },
144
+ cwd: driveAgentToolDef.inputSchema.properties.cwd,
145
+ permissionMode: driveAgentToolDef.inputSchema.properties.permissionMode,
146
+ background: driveAgentToolDef.inputSchema.properties.background,
147
+ },
148
+ required: ["prompt", "cwd"],
149
+ },
150
+ };
151
+ export function makeDriveClaudeCodeTool(runner) {
152
+ const generic = runner
153
+ ? ({ prompt, resumeSessionId, cwd, permissionMode }) => runner({ prompt, resumeSessionId, cwd, permissionMode })
154
+ : undefined;
155
+ return makeDriveAgentTool(generic ?? defaultRunner, "claude");
156
+ }
157
+ export const driveClaudeCodeTool = makeDriveClaudeCodeTool();
@@ -0,0 +1,3 @@
1
+ import type { ToolDefinition } from "../../types.js";
2
+ export declare const editModelCatalogToolDef: ToolDefinition;
3
+ export declare function editModelCatalogTool(args: Record<string, unknown>): Promise<string>;
@@ -0,0 +1,104 @@
1
+ /**
2
+ * EditModelCatalog tool — add or update a provider/model template in the user
3
+ * model catalog (~/.code-shell/model-catalog.user.json). Pairs with the
4
+ * model-fact-finder skill: the skill researches a model's facts (modalities,
5
+ * params, context), then this tool writes them into a CatalogEntry so the
6
+ * connection page picks it up. Backs up before writing; validates against the
7
+ * schema; never touches API keys/credentials (those go through the user's own
8
+ * Edit, by design). See docs/.../2026-06-15-unified-model-catalog-design.md §7.
9
+ */
10
+ import { randomBytes } from "node:crypto";
11
+ import { userCatalogPath } from "../../model-catalog/index.js";
12
+ import { saveCatalogEntry } from "../../model-catalog/save-entry.js";
13
+ import { catalogEntrySchema } from "../../model-catalog/types.js";
14
+ export const editModelCatalogToolDef = {
15
+ name: "EditModelCatalog",
16
+ description: "Add or update a provider/model template in the user model catalog so it " +
17
+ "appears in the connection page (text/image/video). Keyed by `id`: a new id " +
18
+ "adds a provider, an existing id replaces that user-catalog entry. Backs up " +
19
+ "the file before writing and " +
20
+ "validates the entry. Use after researching a model's real facts (id, context " +
21
+ "window, supported params, modalities) — do NOT guess; verify against the " +
22
+ "provider's official docs first (see the model-fact-finder skill). Does NOT set " +
23
+ "API keys: the user enters keys in the connection page (credentials), not here.",
24
+ inputSchema: {
25
+ type: "object",
26
+ properties: {
27
+ entry: {
28
+ type: "object",
29
+ description: "A full CatalogEntry. Required: id, tag (text|image|video), adapterKind " +
30
+ "(an already-wired adapter: openai|anthropic|google|fal), displayName, " +
31
+ "description, defaultBaseUrl. Optional: protocol (openai-compat|anthropic-style), " +
32
+ "defaultModel, needsKey, signupUrl, test, modelPresets[] (each {value, label?, " +
33
+ "maxContextTokens?, maxOutputTokens?, supportsVision?, params?[]}). Each param: " +
34
+ "{name, label?, control (enum|number|toggle|text), options?[], min?, max?, default?, " +
35
+ "doc?, wire?{field}}. Fill maxContextTokens with the model's REAL window; declare " +
36
+ "params per-model (only what that model supports). To keep a custom provider " +
37
+ "beside a built-in one, use a distinct id.",
38
+ },
39
+ },
40
+ required: ["entry"],
41
+ },
42
+ };
43
+ export async function editModelCatalogTool(args) {
44
+ const entry = args.entry;
45
+ if (!entry || typeof entry !== "object") {
46
+ return "Error: `entry` (a CatalogEntry object) is required.";
47
+ }
48
+ const parsed = catalogEntrySchema.safeParse(entry);
49
+ if (!parsed.success) {
50
+ return `Error: invalid catalog entry: ${parsed.error.issues.map((i) => i.message).join("; ")}`;
51
+ }
52
+ const stamp = `${Date.now()}-${randomBytes(3).toString("hex")}`;
53
+ const r = saveCatalogEntry(parsed.data, {
54
+ path: userCatalogPath(),
55
+ stamp,
56
+ });
57
+ if (!r.ok)
58
+ return `Error: ${r.error}`;
59
+ return summarizeWrite(parsed.data, r.action ?? "added", r.backup);
60
+ }
61
+ /**
62
+ * Build a structured completion summary so the user can SEE exactly what was
63
+ * written and catch a wrong value at a glance — every param's options/default
64
+ * is echoed back, because that's where catalog entries go wrong (e.g. listing a
65
+ * gateway's input aliases as if they were the model's native effort levels).
66
+ * The LLM is told to relay this and ask the user to verify against the docs.
67
+ */
68
+ function summarizeWrite(entry, action, backup) {
69
+ const id = entry.id ?? "(unknown)";
70
+ const lines = [];
71
+ lines.push(`✅ ${action === "updated" ? "Updated" : "Added"} catalog entry "${id}".`);
72
+ lines.push(`tag: ${entry.tag ?? "?"} | adapter: ${entry.adapterKind ?? "?"}` +
73
+ (entry.defaultModel ? ` | defaultModel: ${entry.defaultModel}` : "") +
74
+ (entry.defaultBaseUrl ? ` | baseUrl: ${entry.defaultBaseUrl}` : ""));
75
+ const presets = entry.modelPresets ?? [];
76
+ if (presets.length === 0) {
77
+ lines.push("(no modelPresets)");
78
+ }
79
+ for (const p of presets) {
80
+ const ctx = p.maxContextTokens ? `ctx ${p.maxContextTokens}` : "";
81
+ const out = p.maxOutputTokens ? `out ${p.maxOutputTokens}` : "";
82
+ const limits = [ctx, out].filter(Boolean).join(", ");
83
+ lines.push(`\nmodel: ${p.value ?? "?"}${p.label ? ` (${p.label})` : ""}${limits ? ` — ${limits}` : ""}`);
84
+ const params = p.params ?? [];
85
+ if (params.length === 0) {
86
+ lines.push(" (no params declared)");
87
+ }
88
+ for (const pa of params) {
89
+ let detail = "";
90
+ if (pa.control === "enum")
91
+ detail = `options=[${(pa.options ?? []).join(", ")}]`;
92
+ else if (pa.control === "number")
93
+ detail = `range ${pa.min ?? "?"}..${pa.max ?? "?"}`;
94
+ const def = pa.default !== undefined ? ` default=${JSON.stringify(pa.default)}` : "";
95
+ lines.push(` - ${pa.name ?? "?"} (${pa.control ?? "?"}) ${detail}${def}`.trimEnd());
96
+ }
97
+ }
98
+ lines.push(`\nWritten to ${userCatalogPath()}.` + (backup ? ` Backup: ${backup}.` : ""));
99
+ lines.push("Hot-reloads — the connection page refreshes once this turn completes.");
100
+ lines.push("⚠️ Relay this summary to the user and ask them to verify each param's options/default " +
101
+ "match the provider's OFFICIAL docs — especially enum levels (a gateway's input aliases " +
102
+ "are NOT the model's native values). To fix: edit this file directly, or ask me to.");
103
+ return lines.join("\n");
104
+ }