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

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 (387) 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 +56 -0
  45. package/dist/context/compaction.js +186 -0
  46. package/dist/context/manager.js +25 -4
  47. package/dist/cost-tracker.js +5 -61
  48. package/dist/credentials/cipher.d.ts +49 -0
  49. package/dist/credentials/cipher.js +45 -0
  50. package/dist/credentials/cookie-jar.d.ts +24 -0
  51. package/dist/credentials/cookie-jar.js +40 -0
  52. package/dist/credentials/index.d.ts +7 -0
  53. package/dist/credentials/index.js +5 -0
  54. package/dist/credentials/inject-credential-tool.d.ts +20 -0
  55. package/dist/credentials/inject-credential-tool.js +130 -0
  56. package/dist/credentials/store.d.ts +72 -0
  57. package/dist/credentials/store.js +184 -0
  58. package/dist/credentials/types.d.ts +56 -0
  59. package/dist/credentials/use-credential-tool.d.ts +29 -0
  60. package/dist/credentials/use-credential-tool.js +205 -0
  61. package/dist/credentials/use-gate.d.ts +56 -0
  62. package/dist/credentials/use-gate.js +52 -0
  63. package/dist/data/model-metadata.d.ts +77 -0
  64. package/dist/data/model-metadata.js +56 -0
  65. package/dist/data/model-metadata.json +216 -0
  66. package/dist/data/openrouter-models.d.ts +18 -7
  67. package/dist/data/openrouter-models.js +35 -8
  68. package/dist/engine/aux-key.d.ts +10 -0
  69. package/dist/engine/aux-key.js +11 -0
  70. package/dist/engine/dynamic-tool-defs.d.ts +19 -0
  71. package/dist/engine/dynamic-tool-defs.js +36 -0
  72. package/dist/engine/engine.d.ts +267 -138
  73. package/dist/engine/engine.js +957 -191
  74. package/dist/engine/friendly-error.d.ts +18 -0
  75. package/dist/engine/friendly-error.js +63 -0
  76. package/dist/engine/goal.d.ts +145 -0
  77. package/dist/engine/goal.js +144 -0
  78. package/dist/engine/image-policy.d.ts +13 -0
  79. package/dist/engine/image-policy.js +24 -0
  80. package/dist/engine/model-connections-pool.d.ts +17 -0
  81. package/dist/engine/model-connections-pool.js +66 -0
  82. package/dist/engine/model-facade.d.ts +10 -0
  83. package/dist/engine/model-facade.js +25 -0
  84. package/dist/engine/patch-orphaned-tools.js +3 -0
  85. package/dist/engine/resolve-llm-config.d.ts +16 -0
  86. package/dist/engine/resolve-llm-config.js +44 -0
  87. package/dist/engine/runtime.js +2 -1
  88. package/dist/engine/sandbox-cache-key.d.ts +10 -0
  89. package/dist/engine/sandbox-cache-key.js +9 -0
  90. package/dist/engine/sandbox-config.d.ts +31 -0
  91. package/dist/engine/sandbox-config.js +38 -0
  92. package/dist/engine/session-usage.d.ts +19 -0
  93. package/dist/engine/session-usage.js +25 -0
  94. package/dist/engine/steer-queue.d.ts +32 -0
  95. package/dist/engine/steer-queue.js +26 -0
  96. package/dist/engine/streaming-tool-queue.d.ts +12 -0
  97. package/dist/engine/streaming-tool-queue.js +50 -10
  98. package/dist/engine/turn-loop.d.ts +67 -3
  99. package/dist/engine/turn-loop.js +292 -41
  100. package/dist/engine/types.d.ts +175 -0
  101. package/dist/engine/types.js +13 -0
  102. package/dist/external-agents/config.d.ts +2 -0
  103. package/dist/external-agents/config.js +15 -0
  104. package/dist/external-agents/types.d.ts +31 -0
  105. package/dist/external-agents/types.js +1 -0
  106. package/dist/git/utils.js +11 -6
  107. package/dist/git/worktree.d.ts +48 -0
  108. package/dist/git/worktree.js +86 -10
  109. package/dist/hooks/goal-stop-hook.d.ts +28 -0
  110. package/dist/hooks/goal-stop-hook.js +186 -9
  111. package/dist/hooks/registry.d.ts +8 -0
  112. package/dist/hooks/registry.js +19 -0
  113. package/dist/hooks/shell-runner.js +10 -21
  114. package/dist/index.d.ts +49 -6
  115. package/dist/index.js +60 -4
  116. package/dist/llm/capabilities/param-specs.d.ts +14 -0
  117. package/dist/llm/capabilities/param-specs.js +62 -0
  118. package/dist/llm/capabilities/rules.js +4 -0
  119. package/dist/llm/capabilities/types.d.ts +10 -0
  120. package/dist/llm/client-base.d.ts +28 -1
  121. package/dist/llm/client-base.js +119 -13
  122. package/dist/llm/model-cache.js +4 -2
  123. package/dist/llm/model-pool.d.ts +14 -0
  124. package/dist/llm/model-pool.js +13 -0
  125. package/dist/llm/provider-auth.d.ts +41 -0
  126. package/dist/llm/provider-auth.js +76 -0
  127. package/dist/llm/provider-catalog.d.ts +4 -0
  128. package/dist/llm/providers/anthropic.js +64 -14
  129. package/dist/llm/providers/openai.d.ts +36 -0
  130. package/dist/llm/providers/openai.js +257 -51
  131. package/dist/llm/reasoning-setting.d.ts +3 -3
  132. package/dist/llm/reasoning-setting.js +9 -1
  133. package/dist/llm/stream-watchdog.js +5 -1
  134. package/dist/llm/token-counter.js +9 -2
  135. package/dist/llm/types.d.ts +4 -0
  136. package/dist/logging/sanitize-messages.js +22 -0
  137. package/dist/lsp/manager.d.ts +1 -1
  138. package/dist/lsp/manager.js +40 -10
  139. package/dist/model-catalog/builtin.d.ts +12 -0
  140. package/dist/model-catalog/builtin.js +407 -0
  141. package/dist/model-catalog/gen-connections.d.ts +20 -0
  142. package/dist/model-catalog/gen-connections.js +28 -0
  143. package/dist/model-catalog/index.d.ts +41 -0
  144. package/dist/model-catalog/index.js +90 -0
  145. package/dist/model-catalog/params.d.ts +20 -0
  146. package/dist/model-catalog/params.js +45 -0
  147. package/dist/model-catalog/resolve.d.ts +48 -0
  148. package/dist/model-catalog/resolve.js +33 -0
  149. package/dist/model-catalog/save-entry.d.ts +32 -0
  150. package/dist/model-catalog/save-entry.js +104 -0
  151. package/dist/model-catalog/types.d.ts +561 -0
  152. package/dist/model-catalog/types.js +93 -0
  153. package/dist/model-catalog/upsert.d.ts +9 -0
  154. package/dist/model-catalog/upsert.js +8 -0
  155. package/dist/onboarding.d.ts +12 -82
  156. package/dist/onboarding.js +61 -326
  157. package/dist/plugins/gitOps.d.ts +19 -0
  158. package/dist/plugins/gitOps.js +73 -4
  159. package/dist/plugins/installer/checkUpdate.d.ts +16 -0
  160. package/dist/plugins/installer/checkUpdate.js +32 -0
  161. package/dist/plugins/installer/codex/convertCommands.d.ts +19 -0
  162. package/dist/plugins/installer/codex/convertCommands.js +46 -0
  163. package/dist/plugins/installer/codex/convertMcp.d.ts +5 -2
  164. package/dist/plugins/installer/codex/convertMcp.js +45 -5
  165. package/dist/plugins/installer/install.js +25 -1
  166. package/dist/plugins/installer/installFromArchive.d.ts +43 -0
  167. package/dist/plugins/installer/installFromArchive.js +134 -0
  168. package/dist/plugins/installer/installFromSource.js +8 -2
  169. package/dist/plugins/installer/loadPluginAgents.js +6 -2
  170. package/dist/plugins/installer/loadPluginMcp.d.ts +9 -2
  171. package/dist/plugins/installer/loadPluginMcp.js +35 -2
  172. package/dist/plugins/installer/pruneDisabled.d.ts +24 -0
  173. package/dist/plugins/installer/pruneDisabled.js +73 -0
  174. package/dist/plugins/installer/types.d.ts +5 -2
  175. package/dist/plugins/installer/types.js +1 -0
  176. package/dist/plugins/installer/uninstall.js +4 -0
  177. package/dist/plugins/installer/unzip.d.ts +14 -0
  178. package/dist/plugins/installer/unzip.js +82 -0
  179. package/dist/plugins/installer/update.d.ts +14 -0
  180. package/dist/plugins/installer/update.js +53 -21
  181. package/dist/plugins/loadPluginHooks.d.ts +47 -1
  182. package/dist/plugins/loadPluginHooks.js +73 -1
  183. package/dist/plugins/marketplaceManager.d.ts +7 -0
  184. package/dist/plugins/marketplaceManager.js +20 -0
  185. package/dist/plugins/pluginCommandHook.js +4 -18
  186. package/dist/plugins/pluginContent.d.ts +30 -0
  187. package/dist/plugins/pluginContent.js +83 -0
  188. package/dist/plugins/pluginInstaller.d.ts +13 -0
  189. package/dist/plugins/pluginInstaller.js +42 -8
  190. package/dist/plugins/schemas.js +1 -0
  191. package/dist/plugins/types.d.ts +6 -0
  192. package/dist/preset/index.d.ts +7 -1
  193. package/dist/preset/index.js +96 -6
  194. package/dist/product/types.d.ts +1 -1
  195. package/dist/prompt/composer.d.ts +27 -0
  196. package/dist/prompt/composer.js +67 -21
  197. package/dist/prompt/instruction-scanner.js +5 -3
  198. package/dist/prompt/section-loader.js +1 -0
  199. package/dist/prompt/sections/base.md +1 -0
  200. package/dist/prompt/sections/browser.md +10 -0
  201. package/dist/prompt/sections/coding.md +4 -0
  202. package/dist/protocol/chat-session-manager.d.ts +8 -2
  203. package/dist/protocol/chat-session-manager.js +36 -0
  204. package/dist/protocol/chat-session.d.ts +65 -0
  205. package/dist/protocol/chat-session.js +94 -2
  206. package/dist/protocol/client.d.ts +27 -0
  207. package/dist/protocol/client.js +38 -0
  208. package/dist/protocol/server.d.ts +112 -0
  209. package/dist/protocol/server.js +586 -16
  210. package/dist/protocol/transport.js +3 -2
  211. package/dist/protocol/types.d.ts +46 -0
  212. package/dist/protocol/types.js +16 -0
  213. package/dist/quota/credentials.d.ts +3 -0
  214. package/dist/quota/credentials.js +80 -0
  215. package/dist/quota/index.d.ts +36 -0
  216. package/dist/quota/index.js +155 -0
  217. package/dist/quota/types.d.ts +48 -0
  218. package/dist/quota/types.js +13 -0
  219. package/dist/review/review-prompt.d.ts +28 -0
  220. package/dist/review/review-prompt.js +81 -0
  221. package/dist/run/FileRunStore.js +8 -3
  222. package/dist/run/RunApprovalBackend.js +25 -5
  223. package/dist/run/RunManager.d.ts +12 -0
  224. package/dist/run/RunManager.js +35 -0
  225. package/dist/run/factory.d.ts +1 -1
  226. package/dist/runtime/background-shell.d.ts +139 -0
  227. package/dist/runtime/background-shell.js +495 -0
  228. package/dist/runtime/output-clean.d.ts +24 -0
  229. package/dist/runtime/output-clean.js +41 -0
  230. package/dist/runtime/ring-file.d.ts +64 -0
  231. package/dist/runtime/ring-file.js +174 -0
  232. package/dist/runtime/safe-spawn.js +15 -34
  233. package/dist/runtime/spawn-common.d.ts +148 -0
  234. package/dist/runtime/spawn-common.js +303 -0
  235. package/dist/runtime/truncate-output.d.ts +22 -0
  236. package/dist/runtime/truncate-output.js +49 -0
  237. package/dist/runtime/utf8-cut.d.ts +11 -0
  238. package/dist/runtime/utf8-cut.js +23 -0
  239. package/dist/services/auto-dream.d.ts +4 -0
  240. package/dist/services/auto-dream.js +26 -26
  241. package/dist/services/diagnostics.d.ts +1 -2
  242. package/dist/services/diagnostics.js +12 -7
  243. package/dist/services/extract-memories.d.ts +14 -1
  244. package/dist/services/extract-memories.js +45 -6
  245. package/dist/services/memory-orchestrator.d.ts +21 -0
  246. package/dist/services/memory-orchestrator.js +125 -50
  247. package/dist/services/session-memory.js +24 -12
  248. package/dist/session/file-history.d.ts +124 -1
  249. package/dist/session/file-history.js +222 -6
  250. package/dist/session/memory.d.ts +116 -2
  251. package/dist/session/memory.js +250 -28
  252. package/dist/session/session-manager.d.ts +40 -0
  253. package/dist/session/session-manager.js +113 -3
  254. package/dist/session/simple-diff.d.ts +23 -0
  255. package/dist/session/simple-diff.js +84 -0
  256. package/dist/session/transcript.d.ts +25 -1
  257. package/dist/session/transcript.js +35 -2
  258. package/dist/session/undo-target.d.ts +67 -0
  259. package/dist/session/undo-target.js +144 -0
  260. package/dist/settings/disk-defaults.d.ts +9 -2
  261. package/dist/settings/disk-defaults.js +11 -2
  262. package/dist/settings/feature-flags.d.ts +64 -0
  263. package/dist/settings/feature-flags.js +61 -0
  264. package/dist/settings/manager.d.ts +68 -1
  265. package/dist/settings/manager.js +266 -29
  266. package/dist/settings/migrate-config.d.ts +45 -0
  267. package/dist/settings/migrate-config.js +125 -0
  268. package/dist/settings/schema-export.d.ts +25 -0
  269. package/dist/settings/schema-export.js +38 -0
  270. package/dist/settings/schema.d.ts +1186 -771
  271. package/dist/settings/schema.js +268 -97
  272. package/dist/skills/scanner.d.ts +9 -0
  273. package/dist/skills/scanner.js +30 -2
  274. package/dist/stt/resolve-transcribe.d.ts +31 -0
  275. package/dist/stt/resolve-transcribe.js +108 -0
  276. package/dist/stt/transcribe.d.ts +51 -0
  277. package/dist/stt/transcribe.js +65 -0
  278. package/dist/tool-system/browser-bridge.d.ts +226 -0
  279. package/dist/tool-system/browser-bridge.js +163 -0
  280. package/dist/tool-system/builtin/agent-heartbeat.d.ts +49 -0
  281. package/dist/tool-system/builtin/agent-heartbeat.js +89 -0
  282. package/dist/tool-system/builtin/agent-notifications.d.ts +12 -3
  283. package/dist/tool-system/builtin/agent-notifications.js +9 -3
  284. package/dist/tool-system/builtin/agent-output-file.d.ts +38 -0
  285. package/dist/tool-system/builtin/agent-output-file.js +72 -0
  286. package/dist/tool-system/builtin/agent-registry.d.ts +12 -0
  287. package/dist/tool-system/builtin/agent-registry.js +8 -0
  288. package/dist/tool-system/builtin/agent.d.ts +21 -1
  289. package/dist/tool-system/builtin/agent.js +489 -42
  290. package/dist/tool-system/builtin/apply-patch/applier.js +66 -8
  291. package/dist/tool-system/builtin/apply-patch/backup-targets.d.ts +10 -0
  292. package/dist/tool-system/builtin/apply-patch/backup-targets.js +30 -0
  293. package/dist/tool-system/builtin/apply-patch/index.js +0 -15
  294. package/dist/tool-system/builtin/background-jobs.d.ts +76 -0
  295. package/dist/tool-system/builtin/background-jobs.js +124 -0
  296. package/dist/tool-system/builtin/background-shell-tools.d.ts +20 -0
  297. package/dist/tool-system/builtin/background-shell-tools.js +108 -0
  298. package/dist/tool-system/builtin/background-work.d.ts +67 -0
  299. package/dist/tool-system/builtin/background-work.js +86 -0
  300. package/dist/tool-system/builtin/bash-output-style.d.ts +32 -0
  301. package/dist/tool-system/builtin/bash-output-style.js +40 -0
  302. package/dist/tool-system/builtin/bash.d.ts +5 -2
  303. package/dist/tool-system/builtin/bash.js +98 -62
  304. package/dist/tool-system/builtin/browser-tools.d.ts +33 -0
  305. package/dist/tool-system/builtin/browser-tools.js +312 -0
  306. package/dist/tool-system/builtin/cancel-goal.d.ts +31 -0
  307. package/dist/tool-system/builtin/cancel-goal.js +64 -0
  308. package/dist/tool-system/builtin/check-quota.d.ts +15 -0
  309. package/dist/tool-system/builtin/check-quota.js +34 -0
  310. package/dist/tool-system/builtin/config.js +7 -0
  311. package/dist/tool-system/builtin/cron.d.ts +7 -0
  312. package/dist/tool-system/builtin/cron.js +55 -3
  313. package/dist/tool-system/builtin/drive-claude-code.d.ts +30 -0
  314. package/dist/tool-system/builtin/drive-claude-code.js +157 -0
  315. package/dist/tool-system/builtin/edit-model-catalog.d.ts +3 -0
  316. package/dist/tool-system/builtin/edit-model-catalog.js +94 -0
  317. package/dist/tool-system/builtin/edit.js +20 -16
  318. package/dist/tool-system/builtin/eol.d.ts +29 -0
  319. package/dist/tool-system/builtin/eol.js +37 -0
  320. package/dist/tool-system/builtin/file-cache.d.ts +6 -0
  321. package/dist/tool-system/builtin/file-cache.js +8 -0
  322. package/dist/tool-system/builtin/generate-image.d.ts +35 -0
  323. package/dist/tool-system/builtin/generate-image.js +278 -50
  324. package/dist/tool-system/builtin/generate-video.d.ts +55 -0
  325. package/dist/tool-system/builtin/generate-video.js +361 -0
  326. package/dist/tool-system/builtin/glob.js +0 -7
  327. package/dist/tool-system/builtin/grep.js +6 -8
  328. package/dist/tool-system/builtin/image-providers.d.ts +86 -0
  329. package/dist/tool-system/builtin/image-providers.js +190 -0
  330. package/dist/tool-system/builtin/image-uploader.d.ts +33 -0
  331. package/dist/tool-system/builtin/image-uploader.js +74 -0
  332. package/dist/tool-system/builtin/index.d.ts +7 -1
  333. package/dist/tool-system/builtin/index.js +249 -25
  334. package/dist/tool-system/builtin/mcp-tools.js +23 -3
  335. package/dist/tool-system/builtin/memory.js +45 -7
  336. package/dist/tool-system/builtin/notebook-edit.js +0 -7
  337. package/dist/tool-system/builtin/powershell.js +4 -1
  338. package/dist/tool-system/builtin/read.js +10 -10
  339. package/dist/tool-system/builtin/repl.js +4 -1
  340. package/dist/tool-system/builtin/skill.js +9 -0
  341. package/dist/tool-system/builtin/sleep.js +3 -2
  342. package/dist/tool-system/builtin/tool-search.js +25 -7
  343. package/dist/tool-system/builtin/video-providers.d.ts +154 -0
  344. package/dist/tool-system/builtin/video-providers.js +235 -0
  345. package/dist/tool-system/builtin/web-fetch.js +12 -2
  346. package/dist/tool-system/builtin/web-search.js +21 -7
  347. package/dist/tool-system/builtin/worktree.d.ts +2 -1
  348. package/dist/tool-system/builtin/worktree.js +31 -4
  349. package/dist/tool-system/builtin/write.js +0 -6
  350. package/dist/tool-system/context.d.ts +154 -6
  351. package/dist/tool-system/executor.d.ts +3 -1
  352. package/dist/tool-system/executor.js +172 -88
  353. package/dist/tool-system/investigation-guard.js +1 -1
  354. package/dist/tool-system/mcp-manager.d.ts +42 -4
  355. package/dist/tool-system/mcp-manager.js +186 -20
  356. package/dist/tool-system/path-policy.d.ts +5 -0
  357. package/dist/tool-system/path-policy.js +307 -8
  358. package/dist/tool-system/permission.d.ts +36 -1
  359. package/dist/tool-system/permission.js +281 -69
  360. package/dist/tool-system/plan-mode-allowlist.d.ts +13 -2
  361. package/dist/tool-system/plan-mode-allowlist.js +24 -2
  362. package/dist/tool-system/registry.d.ts +1 -0
  363. package/dist/tool-system/registry.js +16 -2
  364. package/dist/tool-system/sandbox/index.d.ts +8 -0
  365. package/dist/tool-system/sandbox/index.js +7 -2
  366. package/dist/tool-system/validate-tool-metadata.d.ts +36 -0
  367. package/dist/tool-system/validate-tool-metadata.js +63 -0
  368. package/dist/types.d.ts +217 -6
  369. package/dist/updater.js +20 -9
  370. package/dist/utils/envUtils.d.ts +0 -9
  371. package/dist/utils/envUtils.js +3 -28
  372. package/dist/utils/exec.d.ts +40 -0
  373. package/dist/utils/exec.js +144 -0
  374. package/dist/utils/json.d.ts +12 -0
  375. package/dist/utils/json.js +92 -0
  376. package/dist/utils/theme.d.ts +1 -1
  377. package/dist/utils/theme.js +1 -1
  378. package/dist/utils/toolDisplay.js +0 -1
  379. package/package.json +13 -7
  380. package/dist/agent/coordinator.d.ts +0 -49
  381. package/dist/agent/coordinator.js +0 -77
  382. package/dist/settings/manager.test.js +0 -73
  383. package/dist/tool-system/builtin/remote-trigger.d.ts +0 -6
  384. package/dist/tool-system/builtin/remote-trigger.js +0 -54
  385. package/dist/tool-system/builtin/send-message.d.ts +0 -6
  386. package/dist/tool-system/builtin/send-message.js +0 -47
  387. /package/dist/{settings/manager.test.d.ts → credentials/types.js} +0 -0
@@ -5,6 +5,23 @@
5
5
  * with a predefined prompt on schedule.
6
6
  */
7
7
  import { isCronExpression, parseCronExpression, nextCronTime } from "./cron-expr.js";
8
+ /**
9
+ * How late a cron-expression timer may fire and still be considered "on time".
10
+ * A setTimeout that fires within this window of its scheduled instant runs
11
+ * normally; one that fires later (the host slept through the scheduled time
12
+ * and the timer fired on wake) is treated as a misfire — skipped and re-armed
13
+ * to the next occurrence. 90s comfortably clears cron's 60s granularity plus
14
+ * normal timer jitter, while still catching a multi-minute/hour sleep drift.
15
+ */
16
+ const CRON_MISFIRE_GRACE_MS = 90_000;
17
+ /**
18
+ * True when a cron timer fired too far past its scheduled instant to be a
19
+ * legitimate on-time run — i.e. the host slept through the scheduled time and
20
+ * the timer fired on wake. Exported for unit testing the sleep/wake guard.
21
+ */
22
+ export function isCronMisfire(scheduledFor, now) {
23
+ return now - scheduledFor > CRON_MISFIRE_GRACE_MS;
24
+ }
8
25
  export class CronScheduler {
9
26
  jobs = new Map();
10
27
  timers = new Map();
@@ -168,10 +185,9 @@ export class CronScheduler {
168
185
  }
169
186
  }
170
187
  persistRunStats(job) {
171
- if (!this.store) {
172
- this.persist();
188
+ // No store → nothing to persist. (persist() would also no-op here.)
189
+ if (!this.store)
173
190
  return;
174
- }
175
191
  try {
176
192
  this.store.mutate((jobs) => {
177
193
  const idx = jobs.findIndex((j) => j.id === job.id);
@@ -210,6 +226,8 @@ export class CronScheduler {
210
226
  ...(opts?.cwd !== undefined ? { cwd: opts.cwd } : {}),
211
227
  ...(opts?.timezone !== undefined ? { timezone: opts.timezone } : {}),
212
228
  ...(opts?.permissionLevel !== undefined ? { permissionLevel: opts.permissionLevel } : {}),
229
+ ...(opts?.once === true ? { once: true } : {}),
230
+ ...(opts?.resumeSessionId !== undefined ? { resumeSessionId: opts.resumeSessionId } : {}),
213
231
  };
214
232
  this.refreshNextRunForDisplay(job);
215
233
  return { jobs: [...jobs, job], result: job };
@@ -229,6 +247,8 @@ export class CronScheduler {
229
247
  ...(opts?.cwd !== undefined ? { cwd: opts.cwd } : {}),
230
248
  ...(opts?.timezone !== undefined ? { timezone: opts.timezone } : {}),
231
249
  ...(opts?.permissionLevel !== undefined ? { permissionLevel: opts.permissionLevel } : {}),
250
+ ...(opts?.once === true ? { once: true } : {}),
251
+ ...(opts?.resumeSessionId !== undefined ? { resumeSessionId: opts.resumeSessionId } : {}),
232
252
  };
233
253
  this.jobs.set(id, job);
234
254
  this.arm(job);
@@ -279,6 +299,37 @@ export class CronScheduler {
279
299
  this.persist();
280
300
  return true;
281
301
  }
302
+ /**
303
+ * Auto-disable a job and record WHY (e.g. its resume target session was
304
+ * deleted). Unlike `delete`, the job is retained (enabled=false) so the user
305
+ * can see it stopped and its reason in the UI, then delete or re-point it.
306
+ * Mirrors `pause` but also stamps `disabledReason`. Idempotent-safe: a
307
+ * subsequent `resume()` clears the reason.
308
+ */
309
+ disableWithReason(id, reason) {
310
+ if (this.store) {
311
+ const tx = this.store.mutate((jobs) => {
312
+ let changed = false;
313
+ const next = jobs.map((j) => {
314
+ if (j.id !== id)
315
+ return j;
316
+ changed = true;
317
+ return { ...j, enabled: false, disabledReason: reason };
318
+ });
319
+ return { jobs: next, result: changed };
320
+ });
321
+ this.reconcileJobs(tx.jobs);
322
+ return tx.result;
323
+ }
324
+ const job = this.jobs.get(id);
325
+ if (!job)
326
+ return false;
327
+ job.enabled = false;
328
+ job.disabledReason = reason;
329
+ this.clearTimer(id);
330
+ this.persist();
331
+ return true;
332
+ }
282
333
  resume(id) {
283
334
  if (this.store) {
284
335
  const tx = this.store.mutate((jobs) => {
@@ -287,7 +338,7 @@ export class CronScheduler {
287
338
  if (j.id !== id)
288
339
  return j;
289
340
  changed = true;
290
- const job = { ...j, enabled: true };
341
+ const job = { ...j, enabled: true, disabledReason: undefined };
291
342
  this.refreshNextRunForDisplay(job);
292
343
  return job;
293
344
  });
@@ -300,6 +351,7 @@ export class CronScheduler {
300
351
  if (!job)
301
352
  return false;
302
353
  job.enabled = true;
354
+ job.disabledReason = undefined;
303
355
  this.arm(job);
304
356
  this.persist();
305
357
  return true;
@@ -440,12 +492,27 @@ export class CronScheduler {
440
492
  return;
441
493
  }
442
494
  job.nextRun = next;
495
+ const scheduledFor = next;
443
496
  const delay = Math.max(0, next - Date.now());
444
497
  const timer = setTimeout(() => {
445
- void this.fire(job, () => {
446
- // Re-arm for the following occurrence.
498
+ // Misfire guard for sleep/wake drift. A setTimeout pauses while the host
499
+ // sleeps, then fires the instant the machine wakes — which can be hours
500
+ // off the scheduled wall-clock (observed: a `0 9 * * *` job running at
501
+ // 06:56 because the Mac did a maintenance wake and the timer fired on
502
+ // resume). If we wake too far PAST the scheduled instant, this is a
503
+ // misfire: skip running and re-arm to the next correct occurrence rather
504
+ // than running at the wrong time.
505
+ if (isCronMisfire(scheduledFor, Date.now())) {
447
506
  if (job.enabled)
448
507
  this.armCron(job);
508
+ return;
509
+ }
510
+ void this.fire(job, () => {
511
+ // Re-arm for the following occurrence — but only if the job still
512
+ // exists. A one-shot (once) job deletes itself in fire()'s finally,
513
+ // so this closure must not resurrect it via a stale reference.
514
+ if (job.enabled && this.jobs.has(job.id))
515
+ this.armCron(job);
449
516
  });
450
517
  }, delay);
451
518
  this.timers.set(job.id, timer);
@@ -498,6 +565,11 @@ export class CronScheduler {
498
565
  this.persistRunStats(job);
499
566
  this.running.delete(job.id);
500
567
  this.runningControllers.delete(job.id);
568
+ // One-shot: delete after its first execution so it never fires again.
569
+ // Done after persistRunStats so the final stats write can't race the
570
+ // removal; delete() clears the timer + removes from store/in-memory.
571
+ if (job.once)
572
+ this.delete(job.id);
501
573
  // Unblock any abort() awaiting this run's teardown.
502
574
  resolveDone();
503
575
  }
@@ -523,15 +595,20 @@ function validateSchedule(schedule, timezone) {
523
595
  * a typo like "5mn" should surface as an error, not quietly schedule every
524
596
  * 10 minutes (review-2026-05-30).
525
597
  */
526
- function parseSchedule(schedule) {
598
+ export function parseSchedule(schedule) {
527
599
  const match = schedule.match(/^(\d+)(s|m|h|d)$/);
528
600
  if (match) {
529
601
  const value = parseInt(match[1], 10);
530
- switch (match[2]) {
531
- case "s": return value * 1000;
532
- case "m": return value * 60 * 1000;
533
- case "h": return value * 60 * 60 * 1000;
534
- case "d": return value * 24 * 60 * 60 * 1000;
602
+ // A zero interval ("0s"/"0m"/…) → 0ms → setInterval(fn, 0) spins
603
+ // continuously. Reject it (fall through to throw), matching the raw-ms
604
+ // path's `> 0` guard and the "throw on bad input" contract.
605
+ if (value > 0) {
606
+ switch (match[2]) {
607
+ case "s": return value * 1000;
608
+ case "m": return value * 60 * 1000;
609
+ case "h": return value * 60 * 60 * 1000;
610
+ case "d": return value * 24 * 60 * 60 * 1000;
611
+ }
535
612
  }
536
613
  }
537
614
  // Raw milliseconds — must be all digits and > 0 (parseInt would otherwise
@@ -113,7 +113,10 @@ export class CronStore {
113
113
  throw lastError;
114
114
  }
115
115
  }
116
+ // Reused across calls — Atomics.wait only reads slot 0, which always stays 0,
117
+ // so a single shared buffer is safe and avoids per-call allocation in the
118
+ // lock-retry loop.
119
+ const SLEEP_SIGNAL = new Int32Array(new SharedArrayBuffer(4));
116
120
  function sleepSync(ms) {
117
- const signal = new Int32Array(new SharedArrayBuffer(4));
118
- Atomics.wait(signal, 0, 0, ms);
121
+ Atomics.wait(SLEEP_SIGNAL, 0, 0, ms);
119
122
  }
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Effective disabled-skills/plugins computation — the ONE place that folds a
3
+ * project's capabilityOverrides (tri-state on/off/inherit) over the global
4
+ * baseline, plus the no-repo whitelist inversion.
5
+ *
6
+ * Extracted from Engine.readDisabledLists because the MCP merge consumers
7
+ * (engineFactory in the stdio/tcp servers, diskDefaultsFrom hot-reload) were
8
+ * passing the RAW global `settings.disabledPlugins` to mergePluginMcpServers:
9
+ * a plugin force-enabled at project level (能力总览 "on") stayed excluded from
10
+ * the MCP merge because the global list still named it. Every consumer must
11
+ * fold through here so "project on overrides global off" holds everywhere.
12
+ */
13
+ import { SettingsManager } from "../settings/manager.js";
14
+ export interface EffectiveDisabledLists {
15
+ disabledSkills: string[];
16
+ disabledPlugins: string[];
17
+ /** Folded from capabilityOverrides.pluginHooks "off" keys (see
18
+ * pluginHookKey) — per-hook suppression for plugin-provided hooks. */
19
+ disabledPluginHooks: string[];
20
+ }
21
+ /**
22
+ * Compute the effective disabled lists for `cwd`. Never throws — any read
23
+ * error falls back to empty lists (same contract as Engine.readDisabledLists).
24
+ */
25
+ export declare function computeEffectiveDisabledLists(sm: SettingsManager, cwd: string | undefined): EffectiveDisabledLists;
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Effective disabled-skills/plugins computation — the ONE place that folds a
3
+ * project's capabilityOverrides (tri-state on/off/inherit) over the global
4
+ * baseline, plus the no-repo whitelist inversion.
5
+ *
6
+ * Extracted from Engine.readDisabledLists because the MCP merge consumers
7
+ * (engineFactory in the stdio/tcp servers, diskDefaultsFrom hot-reload) were
8
+ * passing the RAW global `settings.disabledPlugins` to mergePluginMcpServers:
9
+ * a plugin force-enabled at project level (能力总览 "on") stayed excluded from
10
+ * the MCP merge because the global list still named it. Every consumer must
11
+ * fold through here so "project on overrides global off" holds everywhere.
12
+ */
13
+ import { noRepoDir } from "../settings/manager.js";
14
+ import { scanSkills } from "../skills/scanner.js";
15
+ import { readInstalledPlugins } from "../plugins/installedPlugins.js";
16
+ import { effectiveDisabledList, whitelistDisabledList } from "./overlay.js";
17
+ /**
18
+ * Compute the effective disabled lists for `cwd`. Never throws — any read
19
+ * error falls back to empty lists (same contract as Engine.readDisabledLists).
20
+ */
21
+ export function computeEffectiveDisabledLists(sm, cwd) {
22
+ try {
23
+ const settings = sm.get();
24
+ // Read the project overlay UNMERGED (getForScope), not the merged get(),
25
+ // so tri-state inheritance survives. No cwd / no overlay → the baseline
26
+ // is returned unchanged (zero regression).
27
+ const overrides = cwd
28
+ ? sm.getForScope("project", cwd).capabilityOverrides
29
+ : undefined;
30
+ // no-repo "conversation" scope: INVERT skill/plugin filtering to a
31
+ // whitelist (default-all-off, only explicit "on" survives). Only this
32
+ // fixed cwd flips; every real project keeps the denylist below. agent/
33
+ // mcp/builtin are NOT inverted. See conversation-settings spec §3.
34
+ if (cwd && cwd === noRepoDir()) {
35
+ const allSkillNames = scanSkills(cwd).map((s) => s.name);
36
+ const allPluginNames = Object.keys(readInstalledPlugins().plugins).map((key) => {
37
+ const at = key.lastIndexOf("@");
38
+ return at > 0 ? key.slice(0, at) : key;
39
+ });
40
+ return {
41
+ disabledSkills: whitelistDisabledList(allSkillNames, overrides?.skills),
42
+ disabledPlugins: whitelistDisabledList(allPluginNames, overrides?.plugins),
43
+ // pluginHooks is NOT inverted (like agents/mcp/builtin): there is no
44
+ // global per-hook baseline, only project-level "off" keys.
45
+ disabledPluginHooks: effectiveDisabledList([], overrides?.pluginHooks),
46
+ };
47
+ }
48
+ return {
49
+ disabledSkills: effectiveDisabledList(settings.disabledSkills ?? [], overrides?.skills),
50
+ disabledPlugins: effectiveDisabledList(settings.disabledPlugins ?? [], overrides?.plugins),
51
+ disabledPluginHooks: effectiveDisabledList([], overrides?.pluginHooks),
52
+ };
53
+ }
54
+ catch {
55
+ return { disabledSkills: [], disabledPlugins: [], disabledPluginHooks: [] };
56
+ }
57
+ }
@@ -30,6 +30,21 @@ export declare function overrideFor(overrides: CapabilityOverrides | undefined,
30
30
  * leaves the baseline.
31
31
  */
32
32
  export declare function effectiveDisabledList(globalDisabled: string[], bucket: Record<string, CapabilityOverride> | undefined): string[];
33
+ /**
34
+ * Whitelist (opt-in) variant of {@link effectiveDisabledList}, used only for
35
+ * the no-repo "conversation" scope where skill/plugin default-state is INVERTED:
36
+ * everything is disabled UNLESS the project override bucket explicitly marks it
37
+ * `"on"`. This is the opposite of the normal denylist (default-enabled) model.
38
+ *
39
+ * Given the full set of installed names and an override bucket:
40
+ * - a name explicitly `"on"` → kept enabled (NOT in the returned list)
41
+ * - everything else (`"off"`, inherit/absent, garbage) → disabled (in the list)
42
+ *
43
+ * The returned list is the effective disabled list to feed run-time
44
+ * skill/plugin filtering. Order follows `allInstalledNames`; duplicates are
45
+ * collapsed.
46
+ */
47
+ export declare function whitelistDisabledList(allInstalledNames: string[], bucket: Record<string, CapabilityOverride> | undefined): string[];
33
48
  /**
34
49
  * Fold a project builtin override bucket into the global enabled/disabled
35
50
  * builtin-tool lists, producing the lists to feed resolveBuiltinToolNames
@@ -54,6 +54,33 @@ export function effectiveDisabledList(globalDisabled, bucket) {
54
54
  }
55
55
  return [...disabled];
56
56
  }
57
+ /**
58
+ * Whitelist (opt-in) variant of {@link effectiveDisabledList}, used only for
59
+ * the no-repo "conversation" scope where skill/plugin default-state is INVERTED:
60
+ * everything is disabled UNLESS the project override bucket explicitly marks it
61
+ * `"on"`. This is the opposite of the normal denylist (default-enabled) model.
62
+ *
63
+ * Given the full set of installed names and an override bucket:
64
+ * - a name explicitly `"on"` → kept enabled (NOT in the returned list)
65
+ * - everything else (`"off"`, inherit/absent, garbage) → disabled (in the list)
66
+ *
67
+ * The returned list is the effective disabled list to feed run-time
68
+ * skill/plugin filtering. Order follows `allInstalledNames`; duplicates are
69
+ * collapsed.
70
+ */
71
+ export function whitelistDisabledList(allInstalledNames, bucket) {
72
+ const disabled = [];
73
+ const seen = new Set();
74
+ for (const name of allInstalledNames) {
75
+ if (seen.has(name))
76
+ continue;
77
+ seen.add(name);
78
+ if (bucket?.[name] === "on")
79
+ continue; // explicit allow → stays enabled
80
+ disabled.push(name);
81
+ }
82
+ return disabled;
83
+ }
57
84
  /**
58
85
  * Fold a project builtin override bucket into the global enabled/disabled
59
86
  * builtin-tool lists, producing the lists to feed resolveBuiltinToolNames
@@ -0,0 +1,50 @@
1
+ export type PermissionMode = "default" | "acceptEdits" | "bypassPermissions";
2
+ export interface BuildArgsOpts {
3
+ prompt: string;
4
+ resumeSessionId?: string;
5
+ permissionMode: PermissionMode;
6
+ cwd: string;
7
+ }
8
+ export interface ParsedResult {
9
+ sessionId: string;
10
+ finalText: string;
11
+ isError: boolean;
12
+ }
13
+ export interface AgentAdapter {
14
+ /** Display name, e.g. "claude" / "codex". */
15
+ kind: string;
16
+ /** Build the CLI argv (command itself excluded). */
17
+ buildArgs(opts: BuildArgsOpts): string[];
18
+ /** Reduce collected stream-json output lines to {sessionId, finalText, isError}. */
19
+ parseResult(lines: string[]): ParsedResult;
20
+ /**
21
+ * When true, the prompt is fed over stdin instead of being passed in argv.
22
+ * claude takes the prompt as `-p <prompt>` (argv) so leaves this unset; codex
23
+ * `exec` reads the prompt from stdin (its argv ends with a bare `-`).
24
+ */
25
+ promptViaStdin?: boolean;
26
+ }
27
+ /**
28
+ * Soft cost-guard appended to a driven CC's system prompt. Workflow fans out a
29
+ * fleet of agents and is the main token sink; we ask CC to surface intent and
30
+ * get a go-ahead before running one, so a human can intervene (rooms) and the
31
+ * model stays cost-aware even where Workflow isn't hard-disabled. Shared so the
32
+ * room's resident process can reuse the exact same wording.
33
+ */
34
+ export declare const CC_COST_GUARD_PROMPT: string;
35
+ export declare const claudeAdapter: AgentAdapter;
36
+ /**
37
+ * Drives the OpenAI Codex CLI via `codex exec`. Mirrors claudeAdapter but for
38
+ * codex's different surface:
39
+ * - prompt is fed over STDIN (argv ends with a bare `-`), not argv → promptViaStdin
40
+ * - permission is a spawn-time SANDBOX choice, not a per-tool approval loop:
41
+ * default → --sandbox read-only (codex can read, not write)
42
+ * acceptEdits → --sandbox workspace-write (codex can write the workspace)
43
+ * bypassPermissions → --dangerously-bypass-approvals-and-sandbox (full auto)
44
+ * (Matches the only model codex supports — same choice the `wand` tool makes;
45
+ * codex has no `--permission-prompt-tool stdio` equivalent.)
46
+ * - JSONL event shape differs: session id is `thread.started`.thread_id, the
47
+ * final answer is the last `item.completed` of item.type "agent_message", and
48
+ * failure is `turn.failed` / `error` events (no `is_error` flag).
49
+ */
50
+ export declare const codexAdapter: AgentAdapter;
@@ -0,0 +1,133 @@
1
+ /**
2
+ * Soft cost-guard appended to a driven CC's system prompt. Workflow fans out a
3
+ * fleet of agents and is the main token sink; we ask CC to surface intent and
4
+ * get a go-ahead before running one, so a human can intervene (rooms) and the
5
+ * model stays cost-aware even where Workflow isn't hard-disabled. Shared so the
6
+ * room's resident process can reuse the exact same wording.
7
+ */
8
+ export const CC_COST_GUARD_PROMPT = "Cost guard: before invoking the Workflow tool (which fans out many agents and " +
9
+ "burns a lot of tokens), first state in one short message what workflow you intend " +
10
+ "to run and why, and ask for a go-ahead — do NOT launch a Workflow unprompted. A " +
11
+ "single Task sub-agent is fine without asking.";
12
+ export const claudeAdapter = {
13
+ kind: "claude",
14
+ buildArgs(opts) {
15
+ // -p (print/headless) + stream-json REQUIRES --verbose (verified).
16
+ const args = ["-p", opts.prompt, "--output-format", "stream-json", "--verbose"];
17
+ if (opts.resumeSessionId)
18
+ args.push("--resume", opts.resumeSessionId);
19
+ // Hard-disallow Workflow: driving CC unattended (esp. bypassPermissions),
20
+ // CC's Workflow tool fans out a FLEET of agents — the real token-burn culprit
21
+ // (user: "自动了 2 个 workflow token 就烧没了"). A single Task (one sub-agent)
22
+ // is cheap, so it stays ALLOWED. (We earlier disallowed Task by mistake;
23
+ // Workflow is the one that fans out.) Disabling outright is cleaner than an
24
+ // approval round-trip this path doesn't have.
25
+ args.push("--disallowedTools", "Workflow");
26
+ // Soft constraint (belt-and-suspenders + carries to rooms where Workflow is
27
+ // allowed): ask CC to check in before expensive multi-agent work.
28
+ args.push("--append-system-prompt", CC_COST_GUARD_PROMPT);
29
+ args.push("--permission-mode", opts.permissionMode);
30
+ return args;
31
+ },
32
+ parseResult(lines) {
33
+ let sessionId = "";
34
+ let finalText = "";
35
+ let isError = false;
36
+ for (const line of lines) {
37
+ const t = line.trim();
38
+ if (!t)
39
+ continue;
40
+ let d;
41
+ try {
42
+ d = JSON.parse(t);
43
+ }
44
+ catch {
45
+ continue;
46
+ }
47
+ if (typeof d.session_id === "string" && !sessionId)
48
+ sessionId = d.session_id;
49
+ if (d.type === "result") {
50
+ if (typeof d.session_id === "string")
51
+ sessionId = d.session_id;
52
+ if (typeof d.result === "string")
53
+ finalText = d.result;
54
+ isError = Boolean(d.is_error);
55
+ }
56
+ }
57
+ return { sessionId, finalText, isError };
58
+ },
59
+ };
60
+ /**
61
+ * Drives the OpenAI Codex CLI via `codex exec`. Mirrors claudeAdapter but for
62
+ * codex's different surface:
63
+ * - prompt is fed over STDIN (argv ends with a bare `-`), not argv → promptViaStdin
64
+ * - permission is a spawn-time SANDBOX choice, not a per-tool approval loop:
65
+ * default → --sandbox read-only (codex can read, not write)
66
+ * acceptEdits → --sandbox workspace-write (codex can write the workspace)
67
+ * bypassPermissions → --dangerously-bypass-approvals-and-sandbox (full auto)
68
+ * (Matches the only model codex supports — same choice the `wand` tool makes;
69
+ * codex has no `--permission-prompt-tool stdio` equivalent.)
70
+ * - JSONL event shape differs: session id is `thread.started`.thread_id, the
71
+ * final answer is the last `item.completed` of item.type "agent_message", and
72
+ * failure is `turn.failed` / `error` events (no `is_error` flag).
73
+ */
74
+ export const codexAdapter = {
75
+ kind: "codex",
76
+ promptViaStdin: true,
77
+ buildArgs(opts) {
78
+ const args = ["exec", "--json", "--color", "never", "--skip-git-repo-check"];
79
+ if (opts.permissionMode === "bypassPermissions") {
80
+ args.push("--dangerously-bypass-approvals-and-sandbox");
81
+ }
82
+ else {
83
+ args.push("--sandbox", opts.permissionMode === "acceptEdits" ? "workspace-write" : "read-only");
84
+ }
85
+ // `resume <thread_id>` continues a prior codex session; the trailing `-`
86
+ // tells codex exec to read the prompt from stdin (we feed it there).
87
+ if (opts.resumeSessionId)
88
+ args.push("resume", opts.resumeSessionId, "-");
89
+ else
90
+ args.push("-");
91
+ return args;
92
+ },
93
+ parseResult(lines) {
94
+ let sessionId = "";
95
+ let finalText = "";
96
+ let isError = false;
97
+ const errorBits = [];
98
+ for (const line of lines) {
99
+ const t = line.trim();
100
+ if (!t)
101
+ continue;
102
+ let d;
103
+ try {
104
+ d = JSON.parse(t);
105
+ }
106
+ catch {
107
+ continue;
108
+ }
109
+ if (d.type === "thread.started" && typeof d.thread_id === "string")
110
+ sessionId = d.thread_id;
111
+ else if (d.type === "item.completed" && d.item?.type === "agent_message" && typeof d.item.text === "string") {
112
+ finalText = d.item.text; // keep the LAST agent_message
113
+ }
114
+ else if (d.type === "turn.failed") {
115
+ isError = true;
116
+ const msg = d.error?.message ?? d.error ?? "turn failed";
117
+ if (typeof msg === "string")
118
+ errorBits.push(msg);
119
+ }
120
+ else if (d.type === "error") {
121
+ isError = true;
122
+ const msg = d.message ?? d.error?.message ?? d.error ?? "error";
123
+ if (typeof msg === "string")
124
+ errorBits.push(msg);
125
+ }
126
+ }
127
+ // On failure, surface the error text as finalText (so the caller/notification
128
+ // shows *why*), preferring it over any partial agent_message.
129
+ if (isError && errorBits.length)
130
+ finalText = errorBits.join("\n");
131
+ return { sessionId, finalText, isError };
132
+ },
133
+ };
@@ -0,0 +1,19 @@
1
+ export interface CCAvailability {
2
+ available: boolean;
3
+ command: string;
4
+ version?: string;
5
+ reason?: "not-found" | "not-executable";
6
+ }
7
+ /** macOS GUI-launched Electron has a minimal PATH (no Homebrew). Prepend common
8
+ * CLI dirs so `claude` resolves. Mirrors resident-agent.ts's fix. */
9
+ export declare function pathWithCommonBins(env?: NodeJS.ProcessEnv): string;
10
+ export type ProbeRunner = (command: string) => Promise<{
11
+ ok: boolean;
12
+ stdout: string;
13
+ }>;
14
+ /** Probe a CLI's availability. Injectable runner for tests. */
15
+ export declare function probeCli(command: string, runner?: ProbeRunner): Promise<CCAvailability>;
16
+ /** Cached probe; pass force=true to re-detect (user installed CLI mid-session). */
17
+ export declare function probeClaudeCli(force?: boolean): Promise<CCAvailability>;
18
+ /** Cached probe for the OpenAI Codex CLI; force=true re-detects. */
19
+ export declare function probeCodexCli(force?: boolean): Promise<CCAvailability>;
@@ -0,0 +1,53 @@
1
+ import { spawn } from "node:child_process";
2
+ import { delimiter } from "node:path";
3
+ /** macOS GUI-launched Electron has a minimal PATH (no Homebrew). Prepend common
4
+ * CLI dirs so `claude` resolves. Mirrors resident-agent.ts's fix. */
5
+ export function pathWithCommonBins(env = process.env) {
6
+ const extra = ["/opt/homebrew/bin", "/usr/local/bin", "/usr/bin", "/bin"];
7
+ const current = (env.PATH ?? "").split(delimiter).filter(Boolean);
8
+ const merged = [];
9
+ for (const dir of [...extra, ...current])
10
+ if (!merged.includes(dir))
11
+ merged.push(dir);
12
+ return merged.join(delimiter);
13
+ }
14
+ /** Default runner: `<command> --version` with PATH fix. */
15
+ const defaultRunner = (command) => new Promise((resolve, reject) => {
16
+ const child = spawn(command, ["--version"], {
17
+ env: { ...process.env, PATH: pathWithCommonBins() },
18
+ stdio: ["ignore", "pipe", "pipe"],
19
+ });
20
+ let stdout = "";
21
+ child.stdout?.on("data", (c) => (stdout += String(c)));
22
+ child.on("error", reject);
23
+ child.on("exit", (code) => resolve({ ok: code === 0, stdout }));
24
+ });
25
+ /** Probe a CLI's availability. Injectable runner for tests. */
26
+ export async function probeCli(command, runner = defaultRunner) {
27
+ try {
28
+ const { ok, stdout } = await runner(command);
29
+ if (!ok)
30
+ return { available: false, command, reason: "not-executable" };
31
+ return { available: true, command, version: stdout.trim() || undefined };
32
+ }
33
+ catch (err) {
34
+ const code = err.code;
35
+ return { available: false, command, reason: code === "ENOENT" ? "not-found" : "not-executable" };
36
+ }
37
+ }
38
+ let cached;
39
+ /** Cached probe; pass force=true to re-detect (user installed CLI mid-session). */
40
+ export async function probeClaudeCli(force = false) {
41
+ if (cached && !force)
42
+ return cached;
43
+ cached = await probeCli("claude");
44
+ return cached;
45
+ }
46
+ let cachedCodex;
47
+ /** Cached probe for the OpenAI Codex CLI; force=true re-detects. */
48
+ export async function probeCodexCli(force = false) {
49
+ if (cachedCodex && !force)
50
+ return cachedCodex;
51
+ cachedCodex = await probeCli("codex");
52
+ return cachedCodex;
53
+ }
@@ -0,0 +1,24 @@
1
+ import type { DiscoveredSession, DiscoverOptions } from "./session-discovery.js";
2
+ /**
3
+ * Discover codex CLI sessions for a given `cwd`, mirroring the claude-side
4
+ * `discoverSessions` but for codex's storage layout, which is fundamentally
5
+ * different:
6
+ *
7
+ * ~/.codex/sessions/YYYY/MM/DD/rollout-<ts>-<uuid>.jsonl
8
+ *
9
+ * Unlike claude (one dir per project), codex stores rollouts by DATE, not by
10
+ * cwd. The cwd lives INSIDE the file: the first line is a `session_meta` event
11
+ * whose `payload` carries `{ id, cwd, timestamp }` (`id` is the thread id we
12
+ * resume by). So discovery means: walk every rollout file, read just its first
13
+ * line to learn its cwd, and keep the ones matching the requested project.
14
+ *
15
+ * Codex rollout files can be large, so we deliberately AVOID `readFileSync` on
16
+ * the whole file (the claude version reads the whole file because claude
17
+ * sessions are small). We read the first line for the meta, and — only for a
18
+ * matching file — read a bounded prefix to find the first real user message for
19
+ * the title. Returns the same `DiscoveredSession` shape so the UI is CLI-blind.
20
+ */
21
+ export declare function discoverCodexSessions(cwd: string, codexHome?: string, opts?: DiscoverOptions): DiscoveredSession[];
22
+ /** Count codex sessions for `cwd` (reads first-line meta of every rollout; no
23
+ * window). Used so the UI knows whether a bounded list left older ones hidden. */
24
+ export declare function countCodexSessions(cwd: string, codexHome?: string): number;