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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (528) hide show
  1. package/README.md +13 -10
  2. package/dist/agent/agent-definition-registry.d.ts +21 -3
  3. package/dist/agent/agent-definition-registry.js +49 -18
  4. package/dist/agent/agent-definition.d.ts +32 -0
  5. package/dist/agent/agent-definition.js +49 -4
  6. package/dist/arena/arena.js +11 -12
  7. package/dist/arena/context/context-tools.js +47 -6
  8. package/dist/arena/context/within-root.d.ts +7 -0
  9. package/dist/arena/context/within-root.js +15 -0
  10. package/dist/arena/iterate/phases/argue.js +8 -2
  11. package/dist/arena/iterate/phases/revise.js +1 -1
  12. package/dist/arena/iterate/phases/tournament.js +3 -3
  13. package/dist/arena/ledger.js +9 -1
  14. package/dist/arena/phases/adjudication.js +1 -4
  15. package/dist/arena/phases/build-consensus.js +1 -4
  16. package/dist/arena/phases/cross-review.js +2 -8
  17. package/dist/arena/phases/debate-rounds.js +1 -4
  18. package/dist/arena/phases/participant-research.js +1 -4
  19. package/dist/arena/phases/planning-detail-expansion.js +8 -10
  20. package/dist/arena/planner.js +0 -1
  21. package/dist/arena/providers/docs.d.ts +1 -0
  22. package/dist/arena/providers/docs.js +5 -2
  23. package/dist/arena/providers/repo.d.ts +1 -0
  24. package/dist/arena/providers/repo.js +5 -2
  25. package/dist/arena/strategies/utils.d.ts +1 -4
  26. package/dist/arena/strategies/utils.js +7 -51
  27. package/dist/arena/transitions.d.ts +7 -2
  28. package/dist/arena/transitions.js +9 -4
  29. package/dist/arena/types.d.ts +8 -2
  30. package/dist/automation/cron-expr.d.ts +41 -0
  31. package/dist/automation/cron-expr.js +169 -0
  32. package/dist/automation/index.d.ts +41 -0
  33. package/dist/automation/index.js +39 -0
  34. package/dist/automation/runner.d.ts +84 -0
  35. package/dist/automation/runner.js +92 -0
  36. package/dist/automation/scheduler.d.ts +194 -0
  37. package/dist/automation/scheduler.js +623 -0
  38. package/dist/automation/store.d.ts +39 -0
  39. package/dist/automation/store.js +122 -0
  40. package/dist/automation/write-policy.d.ts +34 -0
  41. package/dist/automation/write-policy.js +113 -0
  42. package/dist/automation/write-run.d.ts +51 -0
  43. package/dist/automation/write-run.js +38 -0
  44. package/dist/capability-control/disabled-lists.d.ts +25 -0
  45. package/dist/capability-control/disabled-lists.js +57 -0
  46. package/dist/capability-control/index.d.ts +5 -0
  47. package/dist/capability-control/index.js +3 -0
  48. package/dist/capability-control/overlay.d.ts +64 -0
  49. package/dist/capability-control/overlay.js +116 -0
  50. package/dist/capability-control/project.d.ts +65 -0
  51. package/dist/capability-control/project.js +147 -0
  52. package/dist/capability-control/service.d.ts +70 -0
  53. package/dist/capability-control/service.js +147 -0
  54. package/dist/capability-control/types.d.ts +62 -0
  55. package/dist/capability-control/types.js +17 -0
  56. package/dist/cc-orchestrator/agent-adapter.d.ts +50 -0
  57. package/dist/cc-orchestrator/agent-adapter.js +133 -0
  58. package/dist/cc-orchestrator/cc-capability.d.ts +19 -0
  59. package/dist/cc-orchestrator/cc-capability.js +53 -0
  60. package/dist/cc-orchestrator/codex-session-discovery.d.ts +24 -0
  61. package/dist/cc-orchestrator/codex-session-discovery.js +191 -0
  62. package/dist/cc-orchestrator/codex-session-history.d.ts +25 -0
  63. package/dist/cc-orchestrator/codex-session-history.js +187 -0
  64. package/dist/cc-orchestrator/external-agent-changes.d.ts +19 -0
  65. package/dist/cc-orchestrator/external-agent-changes.js +214 -0
  66. package/dist/cc-orchestrator/external-agent-driver.d.ts +18 -0
  67. package/dist/cc-orchestrator/external-agent-driver.js +69 -0
  68. package/dist/cc-orchestrator/index.d.ts +8 -0
  69. package/dist/cc-orchestrator/index.js +8 -0
  70. package/dist/cc-orchestrator/relevance-judge.d.ts +15 -0
  71. package/dist/cc-orchestrator/relevance-judge.js +29 -0
  72. package/dist/cc-orchestrator/session-discovery.d.ts +46 -0
  73. package/dist/cc-orchestrator/session-discovery.js +125 -0
  74. package/dist/cc-orchestrator/session-history.d.ts +19 -0
  75. package/dist/cc-orchestrator/session-history.js +67 -0
  76. package/dist/cli/agent-server-stdio.d.ts +26 -1
  77. package/dist/cli/agent-server-stdio.js +221 -28
  78. package/dist/cli/agent-server-tcp.d.ts +20 -0
  79. package/dist/cli/agent-server-tcp.js +134 -0
  80. package/dist/cli/graceful-shutdown.d.ts +27 -0
  81. package/dist/cli/graceful-shutdown.js +30 -0
  82. package/dist/context/compaction.d.ts +56 -0
  83. package/dist/context/compaction.js +209 -15
  84. package/dist/context/manager.d.ts +0 -20
  85. package/dist/context/manager.js +25 -41
  86. package/dist/cost-tracker.js +5 -61
  87. package/dist/credentials/cipher.d.ts +49 -0
  88. package/dist/credentials/cipher.js +45 -0
  89. package/dist/credentials/cookie-jar.d.ts +24 -0
  90. package/dist/credentials/cookie-jar.js +40 -0
  91. package/dist/credentials/index.d.ts +7 -0
  92. package/dist/credentials/index.js +5 -0
  93. package/dist/credentials/inject-credential-tool.d.ts +20 -0
  94. package/dist/credentials/inject-credential-tool.js +130 -0
  95. package/dist/credentials/store.d.ts +72 -0
  96. package/dist/credentials/store.js +184 -0
  97. package/dist/credentials/types.d.ts +56 -0
  98. package/dist/credentials/use-credential-tool.d.ts +29 -0
  99. package/dist/credentials/use-credential-tool.js +205 -0
  100. package/dist/credentials/use-gate.d.ts +56 -0
  101. package/dist/credentials/use-gate.js +52 -0
  102. package/dist/cron/cron-runtime.d.ts +2 -0
  103. package/dist/cron/cron-runtime.js +2 -0
  104. package/dist/cron/cron-store.d.ts +2 -0
  105. package/dist/cron/cron-store.js +2 -0
  106. package/dist/cron/scheduler.d.ts +5 -32
  107. package/dist/cron/scheduler.js +5 -113
  108. package/dist/data/model-metadata.d.ts +77 -0
  109. package/dist/data/model-metadata.js +56 -0
  110. package/dist/data/model-metadata.json +216 -0
  111. package/dist/data/openrouter-models.d.ts +18 -7
  112. package/dist/data/openrouter-models.js +35 -8
  113. package/dist/data/openrouter-sync.js +1 -1
  114. package/dist/engine/aux-key.d.ts +10 -0
  115. package/dist/engine/aux-key.js +11 -0
  116. package/dist/engine/dynamic-tool-defs.d.ts +19 -0
  117. package/dist/engine/dynamic-tool-defs.js +36 -0
  118. package/dist/engine/engine.d.ts +431 -108
  119. package/dist/engine/engine.js +1630 -279
  120. package/dist/engine/friendly-error.d.ts +18 -0
  121. package/dist/engine/friendly-error.js +63 -0
  122. package/dist/engine/goal.d.ts +187 -0
  123. package/dist/engine/goal.js +196 -0
  124. package/dist/engine/image-compression.d.ts +81 -0
  125. package/dist/engine/image-compression.js +186 -0
  126. package/dist/engine/image-policy.d.ts +165 -0
  127. package/dist/engine/image-policy.js +189 -0
  128. package/dist/engine/model-connections-pool.d.ts +17 -0
  129. package/dist/engine/model-connections-pool.js +66 -0
  130. package/dist/engine/model-facade.d.ts +10 -0
  131. package/dist/engine/model-facade.js +25 -0
  132. package/dist/engine/patch-orphaned-tools.js +3 -0
  133. package/dist/engine/reactive-threshold.d.ts +13 -0
  134. package/dist/engine/reactive-threshold.js +17 -0
  135. package/dist/engine/resolve-llm-config.d.ts +16 -0
  136. package/dist/engine/resolve-llm-config.js +44 -0
  137. package/dist/engine/runtime.js +9 -1
  138. package/dist/engine/sandbox-cache-key.d.ts +10 -0
  139. package/dist/engine/sandbox-cache-key.js +9 -0
  140. package/dist/engine/sandbox-config.d.ts +31 -0
  141. package/dist/engine/sandbox-config.js +38 -0
  142. package/dist/engine/session-title.d.ts +13 -0
  143. package/dist/engine/session-title.js +34 -0
  144. package/dist/engine/session-usage.d.ts +19 -0
  145. package/dist/engine/session-usage.js +25 -0
  146. package/dist/engine/steer-queue.d.ts +32 -0
  147. package/dist/engine/steer-queue.js +26 -0
  148. package/dist/engine/streaming-tool-queue.d.ts +12 -0
  149. package/dist/engine/streaming-tool-queue.js +50 -10
  150. package/dist/engine/turn-loop.d.ts +94 -9
  151. package/dist/engine/turn-loop.js +775 -342
  152. package/dist/engine/types.d.ts +175 -0
  153. package/dist/engine/types.js +13 -0
  154. package/dist/external-agents/config.d.ts +2 -0
  155. package/dist/external-agents/config.js +15 -0
  156. package/dist/external-agents/types.d.ts +31 -0
  157. package/dist/external-agents/types.js +1 -0
  158. package/dist/git/parse-log.d.ts +13 -0
  159. package/dist/git/parse-log.js +21 -0
  160. package/dist/git/utils.d.ts +8 -6
  161. package/dist/git/utils.js +62 -26
  162. package/dist/git/worktree.d.ts +48 -0
  163. package/dist/git/worktree.js +111 -20
  164. package/dist/hooks/events.d.ts +23 -1
  165. package/dist/hooks/goal-stop-hook.d.ts +58 -0
  166. package/dist/hooks/goal-stop-hook.js +279 -0
  167. package/dist/hooks/hook-output.d.ts +33 -0
  168. package/dist/hooks/hook-output.js +79 -0
  169. package/dist/hooks/registry.d.ts +15 -0
  170. package/dist/hooks/registry.js +57 -1
  171. package/dist/hooks/shell-runner.d.ts +2 -0
  172. package/dist/hooks/shell-runner.js +48 -18
  173. package/dist/index.d.ts +79 -11
  174. package/dist/index.js +89 -6
  175. package/dist/llm/capabilities/param-specs.d.ts +14 -0
  176. package/dist/llm/capabilities/param-specs.js +62 -0
  177. package/dist/llm/capabilities/reasoning-control.d.ts +24 -0
  178. package/dist/llm/capabilities/reasoning-control.js +38 -0
  179. package/dist/llm/capabilities/rules.js +37 -3
  180. package/dist/llm/capabilities/types.d.ts +32 -2
  181. package/dist/llm/clamp-max-tokens.d.ts +11 -0
  182. package/dist/llm/clamp-max-tokens.js +17 -0
  183. package/dist/llm/client-base.d.ts +69 -5
  184. package/dist/llm/client-base.js +185 -25
  185. package/dist/llm/client-factory.d.ts +3 -3
  186. package/dist/llm/client-factory.js +2 -2
  187. package/dist/llm/model-cache.js +4 -2
  188. package/dist/llm/model-pool.d.ts +29 -11
  189. package/dist/llm/model-pool.js +36 -20
  190. package/dist/llm/provider-auth.d.ts +41 -0
  191. package/dist/llm/provider-auth.js +76 -0
  192. package/dist/llm/provider-catalog.d.ts +6 -2
  193. package/dist/llm/providers/anthropic.d.ts +32 -2
  194. package/dist/llm/providers/anthropic.js +207 -18
  195. package/dist/llm/providers/openai.d.ts +47 -2
  196. package/dist/llm/providers/openai.js +478 -71
  197. package/dist/llm/reasoning-setting.d.ts +51 -0
  198. package/dist/llm/reasoning-setting.js +40 -0
  199. package/dist/llm/stop-reason.d.ts +13 -0
  200. package/dist/llm/stop-reason.js +21 -0
  201. package/dist/llm/stream-watchdog.js +5 -1
  202. package/dist/llm/strip-vision.d.ts +32 -0
  203. package/dist/llm/strip-vision.js +94 -0
  204. package/dist/llm/token-counter.js +9 -2
  205. package/dist/llm/types.d.ts +9 -6
  206. package/dist/logging/logger.js +18 -4
  207. package/dist/logging/sanitize-messages.d.ts +10 -0
  208. package/dist/logging/sanitize-messages.js +112 -0
  209. package/dist/lsp/client.js +28 -8
  210. package/dist/lsp/manager.d.ts +1 -1
  211. package/dist/lsp/manager.js +42 -11
  212. package/dist/lsp/root-path.d.ts +9 -0
  213. package/dist/lsp/root-path.js +12 -0
  214. package/dist/model-catalog/builtin.d.ts +12 -0
  215. package/dist/model-catalog/builtin.js +407 -0
  216. package/dist/model-catalog/gen-connections.d.ts +20 -0
  217. package/dist/model-catalog/gen-connections.js +28 -0
  218. package/dist/model-catalog/index.d.ts +41 -0
  219. package/dist/model-catalog/index.js +90 -0
  220. package/dist/model-catalog/params.d.ts +20 -0
  221. package/dist/model-catalog/params.js +45 -0
  222. package/dist/model-catalog/resolve.d.ts +48 -0
  223. package/dist/model-catalog/resolve.js +33 -0
  224. package/dist/model-catalog/save-entry.d.ts +32 -0
  225. package/dist/model-catalog/save-entry.js +104 -0
  226. package/dist/model-catalog/types.d.ts +561 -0
  227. package/dist/model-catalog/types.js +93 -0
  228. package/dist/model-catalog/upsert.d.ts +9 -0
  229. package/dist/model-catalog/upsert.js +8 -0
  230. package/dist/onboarding.d.ts +12 -82
  231. package/dist/onboarding.js +75 -333
  232. package/dist/plugins/gitOps.d.ts +53 -0
  233. package/dist/plugins/gitOps.js +130 -5
  234. package/dist/plugins/installer/checkUpdate.d.ts +16 -0
  235. package/dist/plugins/installer/checkUpdate.js +32 -0
  236. package/dist/plugins/installer/codex/convertAgents.d.ts +7 -0
  237. package/dist/plugins/installer/codex/convertAgents.js +55 -0
  238. package/dist/plugins/installer/codex/convertCommands.d.ts +19 -0
  239. package/dist/plugins/installer/codex/convertCommands.js +46 -0
  240. package/dist/plugins/installer/codex/convertMcp.d.ts +11 -0
  241. package/dist/plugins/installer/codex/convertMcp.js +85 -0
  242. package/dist/plugins/installer/codex/convertSkills.d.ts +12 -0
  243. package/dist/plugins/installer/codex/convertSkills.js +33 -0
  244. package/dist/plugins/installer/detectFormat.d.ts +2 -0
  245. package/dist/plugins/installer/detectFormat.js +6 -0
  246. package/dist/plugins/installer/install.d.ts +7 -0
  247. package/dist/plugins/installer/install.js +123 -0
  248. package/dist/plugins/installer/installFromArchive.d.ts +43 -0
  249. package/dist/plugins/installer/installFromArchive.js +134 -0
  250. package/dist/plugins/installer/installFromSource.d.ts +13 -0
  251. package/dist/plugins/installer/installFromSource.js +51 -0
  252. package/dist/plugins/installer/list.d.ts +9 -0
  253. package/dist/plugins/installer/list.js +30 -0
  254. package/dist/plugins/installer/loadPluginAgents.d.ts +3 -0
  255. package/dist/plugins/installer/loadPluginAgents.js +27 -0
  256. package/dist/plugins/installer/loadPluginMcp.d.ts +14 -0
  257. package/dist/plugins/installer/loadPluginMcp.js +107 -0
  258. package/dist/plugins/installer/parseSource.d.ts +20 -0
  259. package/dist/plugins/installer/parseSource.js +74 -0
  260. package/dist/plugins/installer/paths.d.ts +5 -0
  261. package/dist/plugins/installer/paths.js +25 -0
  262. package/dist/plugins/installer/pruneDisabled.d.ts +24 -0
  263. package/dist/plugins/installer/pruneDisabled.js +73 -0
  264. package/dist/plugins/installer/types.d.ts +52 -0
  265. package/dist/plugins/installer/types.js +28 -0
  266. package/dist/plugins/installer/uninstall.d.ts +2 -0
  267. package/dist/plugins/installer/uninstall.js +18 -0
  268. package/dist/plugins/installer/unzip.d.ts +14 -0
  269. package/dist/plugins/installer/unzip.js +82 -0
  270. package/dist/plugins/installer/update.d.ts +28 -0
  271. package/dist/plugins/installer/update.js +97 -0
  272. package/dist/plugins/loadPluginHooks.d.ts +54 -1
  273. package/dist/plugins/loadPluginHooks.js +83 -1
  274. package/dist/plugins/marketplaceManager.d.ts +15 -1
  275. package/dist/plugins/marketplaceManager.js +58 -4
  276. package/dist/plugins/pluginCommandHook.js +34 -14
  277. package/dist/plugins/pluginContent.d.ts +30 -0
  278. package/dist/plugins/pluginContent.js +83 -0
  279. package/dist/plugins/pluginInstaller.d.ts +34 -0
  280. package/dist/plugins/pluginInstaller.js +168 -35
  281. package/dist/plugins/schemas.js +41 -6
  282. package/dist/plugins/types.d.ts +10 -0
  283. package/dist/preset/index.d.ts +7 -1
  284. package/dist/preset/index.js +112 -6
  285. package/dist/product/types.d.ts +1 -1
  286. package/dist/prompt/composer.d.ts +31 -0
  287. package/dist/prompt/composer.js +95 -25
  288. package/dist/prompt/instruction-scanner.js +5 -3
  289. package/dist/prompt/section-loader.js +1 -0
  290. package/dist/prompt/sections/base.md +1 -0
  291. package/dist/prompt/sections/browser.md +10 -0
  292. package/dist/prompt/sections/coding.md +4 -0
  293. package/dist/prompt/sections/orchestration.md +8 -0
  294. package/dist/protocol/chat-session-manager.d.ts +15 -2
  295. package/dist/protocol/chat-session-manager.js +46 -0
  296. package/dist/protocol/chat-session.d.ts +82 -0
  297. package/dist/protocol/chat-session.js +121 -1
  298. package/dist/protocol/client.d.ts +27 -0
  299. package/dist/protocol/client.js +38 -0
  300. package/dist/protocol/redact.d.ts +50 -0
  301. package/dist/protocol/redact.js +71 -0
  302. package/dist/protocol/server.d.ts +153 -2
  303. package/dist/protocol/server.js +807 -39
  304. package/dist/protocol/tcp-transport.d.ts +45 -0
  305. package/dist/protocol/tcp-transport.js +74 -0
  306. package/dist/protocol/transport.js +3 -2
  307. package/dist/protocol/types.d.ts +69 -0
  308. package/dist/protocol/types.js +22 -0
  309. package/dist/quota/credentials.d.ts +3 -0
  310. package/dist/quota/credentials.js +80 -0
  311. package/dist/quota/index.d.ts +36 -0
  312. package/dist/quota/index.js +155 -0
  313. package/dist/quota/types.d.ts +48 -0
  314. package/dist/quota/types.js +13 -0
  315. package/dist/remote/bridge.d.ts +11 -2
  316. package/dist/remote/bridge.js +61 -33
  317. package/dist/review/review-prompt.d.ts +28 -0
  318. package/dist/review/review-prompt.js +81 -0
  319. package/dist/run/ArtifactTracker.js +5 -4
  320. package/dist/run/EngineRunner.d.ts +27 -1
  321. package/dist/run/EngineRunner.js +46 -8
  322. package/dist/run/FileRunStore.js +40 -11
  323. package/dist/run/RunApprovalBackend.js +25 -5
  324. package/dist/run/RunLock.d.ts +28 -2
  325. package/dist/run/RunLock.js +49 -7
  326. package/dist/run/RunManager.d.ts +12 -0
  327. package/dist/run/RunManager.js +86 -3
  328. package/dist/run/RunQueue.d.ts +1 -0
  329. package/dist/run/RunQueue.js +8 -2
  330. package/dist/run/factory.d.ts +8 -1
  331. package/dist/run/factory.js +1 -0
  332. package/dist/run/index.d.ts +2 -2
  333. package/dist/run/index.js +1 -1
  334. package/dist/run/redirect-target.d.ts +7 -0
  335. package/dist/run/redirect-target.js +13 -0
  336. package/dist/run/types.js +1 -1
  337. package/dist/runtime/background-shell.d.ts +139 -0
  338. package/dist/runtime/background-shell.js +495 -0
  339. package/dist/runtime/output-clean.d.ts +24 -0
  340. package/dist/runtime/output-clean.js +41 -0
  341. package/dist/runtime/ring-file.d.ts +64 -0
  342. package/dist/runtime/ring-file.js +174 -0
  343. package/dist/runtime/safe-spawn.js +15 -34
  344. package/dist/runtime/spawn-common.d.ts +148 -0
  345. package/dist/runtime/spawn-common.js +303 -0
  346. package/dist/runtime/truncate-output.d.ts +22 -0
  347. package/dist/runtime/truncate-output.js +49 -0
  348. package/dist/runtime/utf8-cut.d.ts +11 -0
  349. package/dist/runtime/utf8-cut.js +23 -0
  350. package/dist/services/auto-dream.d.ts +4 -0
  351. package/dist/services/auto-dream.js +26 -26
  352. package/dist/services/browser-open.d.ts +13 -0
  353. package/dist/services/browser-open.js +16 -0
  354. package/dist/services/diagnostics.d.ts +1 -2
  355. package/dist/services/diagnostics.js +12 -7
  356. package/dist/services/dream-consolidation.d.ts +57 -0
  357. package/dist/services/dream-consolidation.js +151 -0
  358. package/dist/services/extract-memories.d.ts +14 -1
  359. package/dist/services/extract-memories.js +45 -6
  360. package/dist/services/memory-orchestrator.d.ts +21 -0
  361. package/dist/services/memory-orchestrator.js +125 -32
  362. package/dist/services/notifier.d.ts +8 -0
  363. package/dist/services/notifier.js +39 -25
  364. package/dist/services/oauth.js +5 -7
  365. package/dist/services/session-memory-sort.d.ts +8 -0
  366. package/dist/services/session-memory-sort.js +9 -0
  367. package/dist/services/session-memory.js +30 -19
  368. package/dist/session/file-history.d.ts +124 -1
  369. package/dist/session/file-history.js +232 -9
  370. package/dist/session/memory.d.ts +116 -2
  371. package/dist/session/memory.js +250 -28
  372. package/dist/session/session-manager.d.ts +63 -1
  373. package/dist/session/session-manager.js +186 -5
  374. package/dist/session/simple-diff.d.ts +23 -0
  375. package/dist/session/simple-diff.js +84 -0
  376. package/dist/session/transcript.d.ts +25 -1
  377. package/dist/session/transcript.js +35 -2
  378. package/dist/session/undo-target.d.ts +67 -0
  379. package/dist/session/undo-target.js +144 -0
  380. package/dist/settings/disk-defaults.d.ts +42 -0
  381. package/dist/settings/disk-defaults.js +33 -0
  382. package/dist/settings/feature-flags.d.ts +64 -0
  383. package/dist/settings/feature-flags.js +61 -0
  384. package/dist/settings/manager.d.ts +101 -1
  385. package/dist/settings/manager.js +345 -15
  386. package/dist/settings/migrate-config.d.ts +45 -0
  387. package/dist/settings/migrate-config.js +125 -0
  388. package/dist/settings/personalization.d.ts +19 -0
  389. package/dist/settings/personalization.js +7 -0
  390. package/dist/settings/schema-export.d.ts +25 -0
  391. package/dist/settings/schema-export.js +38 -0
  392. package/dist/settings/schema.d.ts +1827 -396
  393. package/dist/settings/schema.js +361 -81
  394. package/dist/skills/scanner.d.ts +9 -0
  395. package/dist/skills/scanner.js +30 -2
  396. package/dist/stt/resolve-transcribe.d.ts +31 -0
  397. package/dist/stt/resolve-transcribe.js +108 -0
  398. package/dist/stt/transcribe.d.ts +51 -0
  399. package/dist/stt/transcribe.js +65 -0
  400. package/dist/tool-system/browser-bridge.d.ts +226 -0
  401. package/dist/tool-system/browser-bridge.js +163 -0
  402. package/dist/tool-system/builtin/add-marketplace.d.ts +12 -0
  403. package/dist/tool-system/builtin/add-marketplace.js +76 -0
  404. package/dist/tool-system/builtin/agent-heartbeat.d.ts +49 -0
  405. package/dist/tool-system/builtin/agent-heartbeat.js +89 -0
  406. package/dist/tool-system/builtin/agent-notifications.d.ts +12 -3
  407. package/dist/tool-system/builtin/agent-notifications.js +9 -3
  408. package/dist/tool-system/builtin/agent-output-file.d.ts +38 -0
  409. package/dist/tool-system/builtin/agent-output-file.js +72 -0
  410. package/dist/tool-system/builtin/agent-registry.d.ts +23 -0
  411. package/dist/tool-system/builtin/agent-registry.js +16 -4
  412. package/dist/tool-system/builtin/agent.d.ts +50 -11
  413. package/dist/tool-system/builtin/agent.js +576 -73
  414. package/dist/tool-system/builtin/apply-patch/applier.js +66 -8
  415. package/dist/tool-system/builtin/apply-patch/backup-targets.d.ts +10 -0
  416. package/dist/tool-system/builtin/apply-patch/backup-targets.js +30 -0
  417. package/dist/tool-system/builtin/apply-patch/index.js +7 -3
  418. package/dist/tool-system/builtin/arena.js +6 -7
  419. package/dist/tool-system/builtin/background-jobs.d.ts +76 -0
  420. package/dist/tool-system/builtin/background-jobs.js +124 -0
  421. package/dist/tool-system/builtin/background-shell-tools.d.ts +20 -0
  422. package/dist/tool-system/builtin/background-shell-tools.js +108 -0
  423. package/dist/tool-system/builtin/background-work.d.ts +67 -0
  424. package/dist/tool-system/builtin/background-work.js +86 -0
  425. package/dist/tool-system/builtin/bash-output-style.d.ts +32 -0
  426. package/dist/tool-system/builtin/bash-output-style.js +40 -0
  427. package/dist/tool-system/builtin/bash.d.ts +5 -2
  428. package/dist/tool-system/builtin/bash.js +98 -62
  429. package/dist/tool-system/builtin/browser-tools.d.ts +33 -0
  430. package/dist/tool-system/builtin/browser-tools.js +312 -0
  431. package/dist/tool-system/builtin/cancel-goal.d.ts +31 -0
  432. package/dist/tool-system/builtin/cancel-goal.js +64 -0
  433. package/dist/tool-system/builtin/check-quota.d.ts +15 -0
  434. package/dist/tool-system/builtin/check-quota.js +34 -0
  435. package/dist/tool-system/builtin/complete-goal.d.ts +25 -0
  436. package/dist/tool-system/builtin/complete-goal.js +45 -0
  437. package/dist/tool-system/builtin/config.js +7 -0
  438. package/dist/tool-system/builtin/cron.d.ts +7 -0
  439. package/dist/tool-system/builtin/cron.js +105 -9
  440. package/dist/tool-system/builtin/drive-claude-code.d.ts +30 -0
  441. package/dist/tool-system/builtin/drive-claude-code.js +157 -0
  442. package/dist/tool-system/builtin/edit-model-catalog.d.ts +3 -0
  443. package/dist/tool-system/builtin/edit-model-catalog.js +94 -0
  444. package/dist/tool-system/builtin/edit.d.ts +2 -1
  445. package/dist/tool-system/builtin/edit.js +21 -12
  446. package/dist/tool-system/builtin/eol.d.ts +29 -0
  447. package/dist/tool-system/builtin/eol.js +37 -0
  448. package/dist/tool-system/builtin/file-cache.d.ts +6 -0
  449. package/dist/tool-system/builtin/file-cache.js +8 -0
  450. package/dist/tool-system/builtin/generate-image.d.ts +60 -0
  451. package/dist/tool-system/builtin/generate-image.js +374 -0
  452. package/dist/tool-system/builtin/generate-video.d.ts +55 -0
  453. package/dist/tool-system/builtin/generate-video.js +361 -0
  454. package/dist/tool-system/builtin/grep.js +6 -2
  455. package/dist/tool-system/builtin/image-providers.d.ts +86 -0
  456. package/dist/tool-system/builtin/image-providers.js +190 -0
  457. package/dist/tool-system/builtin/image-uploader.d.ts +33 -0
  458. package/dist/tool-system/builtin/image-uploader.js +74 -0
  459. package/dist/tool-system/builtin/index.d.ts +24 -1
  460. package/dist/tool-system/builtin/index.js +310 -25
  461. package/dist/tool-system/builtin/mcp-tools.js +23 -3
  462. package/dist/tool-system/builtin/memory.js +45 -7
  463. package/dist/tool-system/builtin/notebook-edit.d.ts +2 -1
  464. package/dist/tool-system/builtin/notebook-edit.js +1 -1
  465. package/dist/tool-system/builtin/powershell.js +4 -1
  466. package/dist/tool-system/builtin/read.d.ts +2 -1
  467. package/dist/tool-system/builtin/read.js +11 -3
  468. package/dist/tool-system/builtin/repl.js +4 -1
  469. package/dist/tool-system/builtin/skill.js +9 -0
  470. package/dist/tool-system/builtin/sleep.js +12 -5
  471. package/dist/tool-system/builtin/task.js +4 -1
  472. package/dist/tool-system/builtin/tool-search.js +25 -7
  473. package/dist/tool-system/builtin/update-automation-memory.d.ts +24 -0
  474. package/dist/tool-system/builtin/update-automation-memory.js +60 -0
  475. package/dist/tool-system/builtin/video-providers.d.ts +154 -0
  476. package/dist/tool-system/builtin/video-providers.js +235 -0
  477. package/dist/tool-system/builtin/view-image.d.ts +18 -0
  478. package/dist/tool-system/builtin/view-image.js +96 -0
  479. package/dist/tool-system/builtin/web-fetch.js +12 -2
  480. package/dist/tool-system/builtin/web-search.d.ts +4 -1
  481. package/dist/tool-system/builtin/web-search.js +57 -10
  482. package/dist/tool-system/builtin/worktree.d.ts +2 -1
  483. package/dist/tool-system/builtin/worktree.js +31 -4
  484. package/dist/tool-system/builtin/write.d.ts +2 -1
  485. package/dist/tool-system/builtin/write.js +1 -1
  486. package/dist/tool-system/context.d.ts +166 -6
  487. package/dist/tool-system/executor.d.ts +3 -2
  488. package/dist/tool-system/executor.js +197 -119
  489. package/dist/tool-system/investigation-guard.d.ts +4 -1
  490. package/dist/tool-system/investigation-guard.js +20 -4
  491. package/dist/tool-system/mcp-manager.d.ts +78 -16
  492. package/dist/tool-system/mcp-manager.js +357 -28
  493. package/dist/tool-system/path-policy.d.ts +99 -0
  494. package/dist/tool-system/path-policy.js +578 -0
  495. package/dist/tool-system/permission.d.ts +36 -1
  496. package/dist/tool-system/permission.js +322 -117
  497. package/dist/tool-system/plan-mode-allowlist.d.ts +32 -0
  498. package/dist/tool-system/plan-mode-allowlist.js +65 -0
  499. package/dist/tool-system/registry.d.ts +1 -0
  500. package/dist/tool-system/registry.js +26 -1
  501. package/dist/tool-system/sandbox/index.d.ts +8 -0
  502. package/dist/tool-system/sandbox/index.js +7 -2
  503. package/dist/tool-system/validate-tool-metadata.d.ts +36 -0
  504. package/dist/tool-system/validate-tool-metadata.js +63 -0
  505. package/dist/tool-system/validation.d.ts +10 -0
  506. package/dist/tool-system/validation.js +16 -3
  507. package/dist/types.d.ts +301 -15
  508. package/dist/updater.js +20 -9
  509. package/dist/utils/envUtils.d.ts +0 -9
  510. package/dist/utils/envUtils.js +3 -28
  511. package/dist/utils/exec.d.ts +40 -0
  512. package/dist/utils/exec.js +144 -0
  513. package/dist/utils/format.js +4 -2
  514. package/dist/utils/json.d.ts +12 -0
  515. package/dist/utils/json.js +92 -0
  516. package/dist/utils/lockfile.js +9 -2
  517. package/dist/utils/theme.d.ts +7 -1
  518. package/dist/utils/theme.js +5 -3
  519. package/dist/utils/toolDisplay.js +0 -1
  520. package/package.json +14 -7
  521. package/dist/agent/coordinator.d.ts +0 -49
  522. package/dist/agent/coordinator.js +0 -77
  523. package/dist/settings/manager.test.js +0 -73
  524. package/dist/tool-system/builtin/remote-trigger.d.ts +0 -6
  525. package/dist/tool-system/builtin/remote-trigger.js +0 -54
  526. package/dist/tool-system/builtin/send-message.d.ts +0 -6
  527. package/dist/tool-system/builtin/send-message.js +0 -47
  528. /package/dist/{settings/manager.test.d.ts → credentials/types.js} +0 -0
@@ -0,0 +1,623 @@
1
+ /**
2
+ * Cron scheduler — schedule and manage recurring agent tasks.
3
+ *
4
+ * Supports simple cron-like intervals. Each job runs the Engine
5
+ * with a predefined prompt on schedule.
6
+ */
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
+ }
25
+ export class CronScheduler {
26
+ jobs = new Map();
27
+ timers = new Map();
28
+ /** Job ids with an execution currently in flight — prevents a tick from
29
+ * starting a second run of a job whose previous run hasn't finished. */
30
+ running = new Set();
31
+ /** In-flight runs keyed by job id: the AbortController that cancels the run,
32
+ * plus `done` — a promise that resolves when the run has FULLY settled
33
+ * (executor returned, including any post-abort bookkeeping like Engine's
34
+ * final saveState). The re-entrancy guard (`running`) ensures at most one
35
+ * run per job, so one entry per job id is sufficient. `abort(jobId)` trips
36
+ * the controller and returns `done` so callers can wait for the run to
37
+ * actually stop before acting (e.g. deleting its session dir without racing
38
+ * a final write that would recreate it). */
39
+ runningControllers = new Map();
40
+ nextId = 1;
41
+ onExecute;
42
+ /** Optional persistence backend. When set, every create/delete/pause/resume
43
+ * writes the full job set to disk so jobs survive a restart. */
44
+ store;
45
+ /** When false, the scheduler persists + tracks jobs but NEVER arms timers
46
+ * (so it can't execute). Used by the desktop agent worker, a separate
47
+ * process from the main process that owns execution. Default true. */
48
+ executionEnabled = true;
49
+ constructor(store) {
50
+ this.store = store;
51
+ }
52
+ /**
53
+ * Disable (or re-enable) timer arming / execution. A host that only needs to
54
+ * persist + read jobs — never run them — calls setExecutionEnabled(false).
55
+ * Stops any timers already armed when turning off.
56
+ */
57
+ setExecutionEnabled(enabled) {
58
+ this.executionEnabled = enabled;
59
+ if (!enabled) {
60
+ for (const timer of this.timers.values())
61
+ clearTimeout(timer);
62
+ this.timers.clear();
63
+ }
64
+ }
65
+ /** Attach (or replace) the persistence backend. Used to give the shared
66
+ * singleton a store at runtime startup without changing its identity. */
67
+ setStore(store) {
68
+ this.store = store;
69
+ }
70
+ setExecutor(fn) {
71
+ this.onExecute = fn;
72
+ }
73
+ /**
74
+ * Abort the in-flight run of `jobId`, if any. Aborts the AbortSignal handed
75
+ * to the executor (which Engine.run cooperates with — it resolves with
76
+ * reason "aborted_streaming" rather than throwing). Returns false when the
77
+ * job has no run currently in flight (already settled, never started, or
78
+ * unknown id). The run's own finally block clears the controller, so a
79
+ * settled run is a no-op here.
80
+ */
81
+ async abort(jobId) {
82
+ const entry = this.runningControllers.get(jobId);
83
+ if (!entry)
84
+ return false;
85
+ entry.controller.abort();
86
+ // Wait for the run to fully settle (the executor's promise, incl. any
87
+ // post-abort write) so callers don't race its teardown.
88
+ await entry.done;
89
+ return true;
90
+ }
91
+ /**
92
+ * Restore persisted jobs and rebuild their timers. Call once at startup
93
+ * after `setStore`. nextRun is recomputed forward from now — we do NOT
94
+ * catch up on runs missed while the process was down (avoids a restart
95
+ * thundering-herd; aligns with Codex's stateless philosophy). Disabled
96
+ * jobs are restored without a timer.
97
+ */
98
+ /**
99
+ * Reconcile in-memory jobs against the on-disk store (the store is the source
100
+ * of truth). Safe to call repeatedly — used both at startup and as a periodic
101
+ * re-sync when another process (e.g. the desktop agent worker) may have
102
+ * created/deleted/changed jobs through the same store. Reconciliation:
103
+ * - jobs on disk but not in memory → added (and armed if enabled)
104
+ * - jobs in memory but not on disk → removed + timer cleared
105
+ * - jobs whose schedule/enabled differ → re-armed to match disk
106
+ *
107
+ * Pass `{ arm: false }` in a host that must NOT execute jobs (the worker —
108
+ * separate process from the one that owns execution); it still tracks +
109
+ * persists but starts no timers, so jobs never run twice across processes.
110
+ */
111
+ loadJobs(opts) {
112
+ if (!this.store)
113
+ return;
114
+ this.reconcileJobs(this.store.load(), opts);
115
+ }
116
+ reconcileJobs(persisted, opts) {
117
+ const arm = opts?.arm ?? true;
118
+ const onDisk = new Map(persisted.map((j) => [j.id, j]));
119
+ // 1. Drop in-memory jobs that no longer exist on disk (deleted elsewhere).
120
+ for (const id of [...this.jobs.keys()]) {
121
+ if (!onDisk.has(id)) {
122
+ this.clearTimer(id);
123
+ this.jobs.delete(id);
124
+ }
125
+ }
126
+ // 2. Add or update jobs from disk.
127
+ let maxId = 0;
128
+ for (const job of persisted) {
129
+ const prev = this.jobs.get(job.id);
130
+ this.jobs.set(job.id, job);
131
+ const n = parseInt(job.id, 10);
132
+ if (Number.isFinite(n) && n > maxId)
133
+ maxId = n;
134
+ // (Re)arm when execution is on. arm() is idempotent (clears any prior
135
+ // timer first), so calling it for unchanged jobs is harmless; it also
136
+ // refreshes nextRun for display.
137
+ if (arm && job.enabled) {
138
+ this.arm(job);
139
+ }
140
+ else {
141
+ // Disabled (or arm suppressed): ensure no stale timer survives a
142
+ // prior enabled state.
143
+ if (prev && this.timers.has(job.id))
144
+ this.clearTimer(job.id);
145
+ // Still refresh nextRun for display even when not arming.
146
+ if (!arm || !job.enabled)
147
+ this.refreshNextRunForDisplay(job);
148
+ }
149
+ }
150
+ this.nextId = Math.max(this.nextId, maxId + 1);
151
+ }
152
+ nextPersistedId(jobs) {
153
+ let maxId = 0;
154
+ for (const job of jobs) {
155
+ const n = parseInt(job.id, 10);
156
+ if (Number.isFinite(n) && n > maxId)
157
+ maxId = n;
158
+ }
159
+ return String(Math.max(this.nextId, maxId + 1));
160
+ }
161
+ /** Recompute nextRun without arming a timer (for display in disabled/no-arm hosts). */
162
+ refreshNextRunForDisplay(job) {
163
+ if (isCronExpression(job.schedule)) {
164
+ const next = nextCronTime(parseCronExpression(job.schedule), job.timezone ?? "UTC", Date.now());
165
+ job.nextRun = next ?? undefined;
166
+ }
167
+ else {
168
+ try {
169
+ job.nextRun = Date.now() + parseSchedule(job.schedule);
170
+ }
171
+ catch {
172
+ job.nextRun = undefined;
173
+ }
174
+ }
175
+ }
176
+ persist() {
177
+ if (!this.store)
178
+ return;
179
+ try {
180
+ this.store.save([...this.jobs.values()]);
181
+ }
182
+ catch {
183
+ // Persistence is best-effort: an unwritable disk should not break the
184
+ // in-memory scheduler. The store logs the failure.
185
+ }
186
+ }
187
+ persistRunStats(job) {
188
+ // No store → nothing to persist. (persist() would also no-op here.)
189
+ if (!this.store)
190
+ return;
191
+ try {
192
+ this.store.mutate((jobs) => {
193
+ const idx = jobs.findIndex((j) => j.id === job.id);
194
+ if (idx === -1)
195
+ return { jobs, result: null };
196
+ const next = [...jobs];
197
+ next[idx] = {
198
+ ...next[idx],
199
+ lastRun: job.lastRun,
200
+ nextRun: job.nextRun,
201
+ runCount: job.runCount,
202
+ ...(job.lastRunId !== undefined ? { lastRunId: job.lastRunId } : {}),
203
+ };
204
+ return { jobs: next, result: null };
205
+ });
206
+ }
207
+ catch {
208
+ // Persistence is best-effort; missed UI metadata must not stop scheduling.
209
+ }
210
+ }
211
+ create(name, schedule, prompt, opts) {
212
+ // Validate the schedule up front (interval or cron expr) so a bad string
213
+ // surfaces at create time, not silently at the first missed tick.
214
+ validateSchedule(schedule, opts?.timezone);
215
+ if (this.store) {
216
+ const tx = this.store.mutate((jobs) => {
217
+ const id = this.nextPersistedId(jobs);
218
+ const job = {
219
+ id,
220
+ name,
221
+ schedule,
222
+ prompt,
223
+ enabled: true,
224
+ runCount: 0,
225
+ createdAt: Date.now(),
226
+ ...(opts?.cwd !== undefined ? { cwd: opts.cwd } : {}),
227
+ ...(opts?.timezone !== undefined ? { timezone: opts.timezone } : {}),
228
+ ...(opts?.permissionLevel !== undefined ? { permissionLevel: opts.permissionLevel } : {}),
229
+ ...(opts?.once === true ? { once: true } : {}),
230
+ ...(opts?.resumeSessionId !== undefined ? { resumeSessionId: opts.resumeSessionId } : {}),
231
+ };
232
+ this.refreshNextRunForDisplay(job);
233
+ return { jobs: [...jobs, job], result: job };
234
+ });
235
+ this.reconcileJobs(tx.jobs);
236
+ return this.jobs.get(tx.result.id) ?? tx.result;
237
+ }
238
+ const id = String(this.nextId++);
239
+ const job = {
240
+ id,
241
+ name,
242
+ schedule,
243
+ prompt,
244
+ enabled: true,
245
+ runCount: 0,
246
+ createdAt: Date.now(),
247
+ ...(opts?.cwd !== undefined ? { cwd: opts.cwd } : {}),
248
+ ...(opts?.timezone !== undefined ? { timezone: opts.timezone } : {}),
249
+ ...(opts?.permissionLevel !== undefined ? { permissionLevel: opts.permissionLevel } : {}),
250
+ ...(opts?.once === true ? { once: true } : {}),
251
+ ...(opts?.resumeSessionId !== undefined ? { resumeSessionId: opts.resumeSessionId } : {}),
252
+ };
253
+ this.jobs.set(id, job);
254
+ this.arm(job);
255
+ this.persist();
256
+ return job;
257
+ }
258
+ delete(id) {
259
+ if (this.store) {
260
+ const tx = this.store.mutate((jobs) => {
261
+ const next = jobs.filter((j) => j.id !== id);
262
+ return { jobs: next, result: next.length !== jobs.length };
263
+ });
264
+ this.reconcileJobs(tx.jobs);
265
+ return tx.result;
266
+ }
267
+ this.clearTimer(id);
268
+ const deleted = this.jobs.delete(id);
269
+ if (deleted)
270
+ this.persist();
271
+ return deleted;
272
+ }
273
+ list() {
274
+ return [...this.jobs.values()];
275
+ }
276
+ get(id) {
277
+ return this.jobs.get(id);
278
+ }
279
+ pause(id) {
280
+ if (this.store) {
281
+ const tx = this.store.mutate((jobs) => {
282
+ let changed = false;
283
+ const next = jobs.map((j) => {
284
+ if (j.id !== id)
285
+ return j;
286
+ changed = true;
287
+ return { ...j, enabled: false };
288
+ });
289
+ return { jobs: next, result: changed };
290
+ });
291
+ this.reconcileJobs(tx.jobs);
292
+ return tx.result;
293
+ }
294
+ const job = this.jobs.get(id);
295
+ if (!job)
296
+ return false;
297
+ job.enabled = false;
298
+ this.clearTimer(id);
299
+ this.persist();
300
+ return true;
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
+ }
333
+ resume(id) {
334
+ if (this.store) {
335
+ const tx = this.store.mutate((jobs) => {
336
+ let changed = false;
337
+ const next = jobs.map((j) => {
338
+ if (j.id !== id)
339
+ return j;
340
+ changed = true;
341
+ const job = { ...j, enabled: true, disabledReason: undefined };
342
+ this.refreshNextRunForDisplay(job);
343
+ return job;
344
+ });
345
+ return { jobs: next, result: changed };
346
+ });
347
+ this.reconcileJobs(tx.jobs);
348
+ return tx.result;
349
+ }
350
+ const job = this.jobs.get(id);
351
+ if (!job)
352
+ return false;
353
+ job.enabled = true;
354
+ job.disabledReason = undefined;
355
+ this.arm(job);
356
+ this.persist();
357
+ return true;
358
+ }
359
+ /**
360
+ * Edit an existing job's fields (name/prompt/schedule/timezone/cwd/
361
+ * permissionLevel) without recreating it. A changed schedule is validated up
362
+ * front (throws on invalid, leaving the job untouched), then the timer is
363
+ * re-armed so the new schedule takes effect immediately. Enabled state is
364
+ * preserved — a paused job stays paused (no timer). Returns the updated job,
365
+ * or null if the id is unknown.
366
+ */
367
+ update(id, patch) {
368
+ if (this.store) {
369
+ const tx = this.store.mutate((jobs) => {
370
+ let updated = null;
371
+ const next = jobs.map((j) => {
372
+ if (j.id !== id)
373
+ return j;
374
+ const job = { ...j };
375
+ const nextSchedule = patch.schedule ?? job.schedule;
376
+ const nextTimezone = patch.timezone ?? job.timezone;
377
+ if (patch.schedule !== undefined || patch.timezone !== undefined) {
378
+ validateSchedule(nextSchedule, nextTimezone);
379
+ }
380
+ if (patch.name !== undefined)
381
+ job.name = patch.name;
382
+ if (patch.prompt !== undefined)
383
+ job.prompt = patch.prompt;
384
+ if (patch.schedule !== undefined)
385
+ job.schedule = patch.schedule;
386
+ if (patch.timezone !== undefined)
387
+ job.timezone = patch.timezone;
388
+ if (patch.cwd !== undefined)
389
+ job.cwd = patch.cwd;
390
+ if (patch.permissionLevel !== undefined)
391
+ job.permissionLevel = patch.permissionLevel;
392
+ this.refreshNextRunForDisplay(job);
393
+ updated = job;
394
+ return job;
395
+ });
396
+ return { jobs: next, result: updated };
397
+ });
398
+ this.reconcileJobs(tx.jobs);
399
+ return tx.result ? this.jobs.get(id) ?? tx.result : null;
400
+ }
401
+ const job = this.jobs.get(id);
402
+ if (!job)
403
+ return null;
404
+ // Validate a new schedule/timezone BEFORE mutating anything.
405
+ const nextSchedule = patch.schedule ?? job.schedule;
406
+ const nextTimezone = patch.timezone ?? job.timezone;
407
+ if (patch.schedule !== undefined || patch.timezone !== undefined) {
408
+ validateSchedule(nextSchedule, nextTimezone);
409
+ }
410
+ if (patch.name !== undefined)
411
+ job.name = patch.name;
412
+ if (patch.prompt !== undefined)
413
+ job.prompt = patch.prompt;
414
+ if (patch.schedule !== undefined)
415
+ job.schedule = patch.schedule;
416
+ if (patch.timezone !== undefined)
417
+ job.timezone = patch.timezone;
418
+ if (patch.cwd !== undefined)
419
+ job.cwd = patch.cwd;
420
+ if (patch.permissionLevel !== undefined)
421
+ job.permissionLevel = patch.permissionLevel;
422
+ // Re-arm so a schedule/timezone change drives execution now. arm() is
423
+ // idempotent and respects enabled + executionEnabled (paused → no timer,
424
+ // but nextRun still refreshed for display).
425
+ if (job.enabled) {
426
+ this.arm(job);
427
+ }
428
+ else {
429
+ this.clearTimer(id);
430
+ this.refreshNextRunForDisplay(job);
431
+ }
432
+ this.persist();
433
+ return job;
434
+ }
435
+ stopAll() {
436
+ for (const timer of this.timers.values()) {
437
+ clearTimeout(timer);
438
+ }
439
+ this.timers.clear();
440
+ }
441
+ /**
442
+ * Fire a job immediately, out of band of its schedule (the "Run now" button).
443
+ * Respects the re-entrancy guard (no-op if a run is already in flight) and
444
+ * does not disturb the existing timer. Returns false if the id is unknown.
445
+ */
446
+ runNow(id) {
447
+ const job = this.jobs.get(id);
448
+ if (!job)
449
+ return false;
450
+ // Run-stat bookkeeping is shared with scheduled fires; nextRun is left as-is
451
+ // (a manual run shouldn't shift the next scheduled occurrence). force=true
452
+ // so a paused job can still be run on demand.
453
+ void this.fire(job, () => { }, true);
454
+ return true;
455
+ }
456
+ /**
457
+ * Arm a job's timer. Interval schedules ("5m") use setInterval; cron-
458
+ * expression schedules ("0 9 * * 1-5") compute the next trigger in the
459
+ * job's timezone and use setTimeout, re-arming after each fire. nextRun is
460
+ * updated to reflect the scheduled instant.
461
+ */
462
+ arm(job) {
463
+ this.clearTimer(job.id);
464
+ if (isCronExpression(job.schedule)) {
465
+ // Compute nextRun for display even when execution is disabled.
466
+ const cron = parseCronExpression(job.schedule);
467
+ const next = nextCronTime(cron, job.timezone ?? "UTC", Date.now());
468
+ job.nextRun = next ?? undefined;
469
+ if (!this.executionEnabled)
470
+ return;
471
+ this.armCron(job);
472
+ }
473
+ else {
474
+ const intervalMs = parseSchedule(job.schedule);
475
+ job.nextRun = Date.now() + intervalMs;
476
+ if (!this.executionEnabled)
477
+ return;
478
+ const timer = setInterval(() => void this.fire(job, () => this.refreshIntervalNextRun(job, intervalMs)), intervalMs);
479
+ this.timers.set(job.id, timer);
480
+ }
481
+ }
482
+ refreshIntervalNextRun(job, intervalMs) {
483
+ job.nextRun = Date.now() + intervalMs;
484
+ }
485
+ armCron(job) {
486
+ const cron = parseCronExpression(job.schedule);
487
+ const tz = job.timezone ?? "UTC";
488
+ const next = nextCronTime(cron, tz, Date.now());
489
+ if (next === null) {
490
+ // Unsatisfiable within the search window — leave unscheduled.
491
+ job.nextRun = undefined;
492
+ return;
493
+ }
494
+ job.nextRun = next;
495
+ const scheduledFor = next;
496
+ const delay = Math.max(0, next - Date.now());
497
+ const timer = setTimeout(() => {
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())) {
506
+ if (job.enabled)
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);
516
+ });
517
+ }, delay);
518
+ this.timers.set(job.id, timer);
519
+ }
520
+ clearTimer(id) {
521
+ const t = this.timers.get(id);
522
+ if (t) {
523
+ clearTimeout(t);
524
+ this.timers.delete(id);
525
+ }
526
+ }
527
+ /**
528
+ * Shared fire path for both schedule kinds. Re-entrancy guard, run-stat
529
+ * bookkeeping, persistence, then the executor. `afterStats` updates nextRun
530
+ * for the next occurrence (interval: now+interval; cron: re-armed inside).
531
+ */
532
+ async fire(job, afterStats, force = false) {
533
+ if (!job.enabled && !force)
534
+ return;
535
+ // Re-entrancy guard: if this job's previous run is still in flight
536
+ // (onExecute slower than the interval), skip rather than stacking
537
+ // overlapping executions that double-count runCount.
538
+ if (this.running.has(job.id))
539
+ return;
540
+ this.running.add(job.id);
541
+ // One in-flight entry per job. abort(jobId) trips `controller` (Engine.run
542
+ // cooperates and resolves early) and awaits `done`, which we resolve in the
543
+ // finally below once the run — including any post-abort write — has settled.
544
+ const controller = new AbortController();
545
+ let resolveDone;
546
+ const done = new Promise((r) => {
547
+ resolveDone = r;
548
+ });
549
+ this.runningControllers.set(job.id, { controller, done });
550
+ job.lastRun = Date.now();
551
+ job.runCount++;
552
+ afterStats();
553
+ // Persist updated run stats so runCount/lastRun/nextRun survive a restart.
554
+ this.persistRunStats(job);
555
+ try {
556
+ await this.onExecute?.(job, controller.signal);
557
+ }
558
+ catch {
559
+ // Job execution failed — continue scheduling.
560
+ }
561
+ finally {
562
+ // The executor may have recorded lastRunId on the job. Persist only run
563
+ // metadata so an old in-flight job cannot overwrite an edited prompt or
564
+ // schedule with its stale copy.
565
+ this.persistRunStats(job);
566
+ this.running.delete(job.id);
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);
573
+ // Unblock any abort() awaiting this run's teardown.
574
+ resolveDone();
575
+ }
576
+ }
577
+ }
578
+ /** Validate a schedule string (interval or cron expr) without scheduling. Throws on invalid. */
579
+ function validateSchedule(schedule, timezone) {
580
+ if (isCronExpression(schedule)) {
581
+ parseCronExpression(schedule); // throws on bad fields
582
+ // Validate timezone is acceptable to Intl (throws RangeError if not).
583
+ if (timezone !== undefined) {
584
+ new Intl.DateTimeFormat("en-US", { timeZone: timezone });
585
+ }
586
+ return;
587
+ }
588
+ parseSchedule(schedule); // throws on bad interval
589
+ }
590
+ /**
591
+ * Parse a schedule string into milliseconds.
592
+ * Supports: "30s", "5m", "1h", "1d", or raw (all-digit) milliseconds.
593
+ *
594
+ * Throws on anything else rather than silently falling back to a default —
595
+ * a typo like "5mn" should surface as an error, not quietly schedule every
596
+ * 10 minutes (review-2026-05-30).
597
+ */
598
+ export function parseSchedule(schedule) {
599
+ const match = schedule.match(/^(\d+)(s|m|h|d)$/);
600
+ if (match) {
601
+ const value = parseInt(match[1], 10);
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
+ }
612
+ }
613
+ }
614
+ // Raw milliseconds — must be all digits and > 0 (parseInt would otherwise
615
+ // accept "1500abc").
616
+ if (/^\d+$/.test(schedule)) {
617
+ const ms = parseInt(schedule, 10);
618
+ if (ms > 0)
619
+ return ms;
620
+ }
621
+ throw new Error(`Invalid schedule: ${JSON.stringify(schedule)}. Use "30s"/"5m"/"1h"/"1d" or a positive number of milliseconds.`);
622
+ }
623
+ export const cronScheduler = new CronScheduler();
@@ -0,0 +1,39 @@
1
+ /**
2
+ * CronStore — persistence for cron jobs.
3
+ *
4
+ * Writes a single-file JSON snapshot of all jobs to `~/.code-shell/cron.json`
5
+ * (global by default), so scheduled tasks survive a process restart. Uses the
6
+ * same atomic tmp+rename write as FileRunStore so a crash mid-write can't
7
+ * truncate the file and lose every job.
8
+ *
9
+ * Cross-process writes are serialized with a directory lock. Hosts that need
10
+ * read-modify-write behavior should use mutate() so load + save happen under
11
+ * the same lock and one process cannot overwrite another process's new job
12
+ * with a stale in-memory snapshot.
13
+ */
14
+ import type { CronJob } from "./scheduler.js";
15
+ /** Default global location. Mirrors FileRunStore's `~/.code-shell/...` layout. */
16
+ export declare function defaultCronStorePath(): string;
17
+ export declare class CronStore {
18
+ private readonly file;
19
+ constructor(file?: string);
20
+ /** Load all persisted jobs. Returns [] when absent or unreadable. */
21
+ load(): CronJob[];
22
+ /**
23
+ * Atomically load, mutate, and save jobs under the store lock. This is the
24
+ * safe path for create/update/delete/pause/resume across the desktop main
25
+ * process and the agent worker process.
26
+ */
27
+ mutate<T>(fn: (jobs: CronJob[]) => {
28
+ jobs: CronJob[];
29
+ result: T;
30
+ }): {
31
+ jobs: CronJob[];
32
+ result: T;
33
+ };
34
+ /** Persist the full job set. Atomic: stage to .tmp, then rename. */
35
+ save(jobs: CronJob[]): void;
36
+ private loadUnlocked;
37
+ private saveUnlocked;
38
+ private acquireStoreLock;
39
+ }