@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
@@ -6,42 +6,71 @@
6
6
  */
7
7
  import { spawn } from "node:child_process";
8
8
  import { createInterface } from "node:readline";
9
+ /**
10
+ * Build the ssh argv. Each value is a discrete element — spawn runs ssh
11
+ * without a shell, so identityFile/port/host are never shell-interpreted
12
+ * (there is no local command-injection surface here).
13
+ */
14
+ export function buildSSHArgs(config) {
15
+ const args = ["-T"]; // No pseudo-terminal
16
+ if (config.port)
17
+ args.push("-p", String(config.port));
18
+ if (config.identityFile)
19
+ args.push("-i", config.identityFile);
20
+ args.push(config.user ? `${config.user}@${config.host}` : config.host);
21
+ return args;
22
+ }
9
23
  export class RemoteBridge {
10
24
  config;
11
25
  ssh;
12
26
  connected = false;
13
- constructor(config) {
27
+ spawnFn;
28
+ constructor(config, spawnFn) {
14
29
  this.config = config;
30
+ this.spawnFn = spawnFn ?? ((cmd, args) => spawn(cmd, args, { stdio: ["pipe", "pipe", "pipe"] }));
15
31
  }
16
32
  /**
17
33
  * Connect to the remote host via SSH and start code-shell in NDJSON mode.
18
34
  */
19
35
  async connect() {
20
- const sshArgs = this.buildSSHArgs();
36
+ const sshArgs = buildSSHArgs(this.config);
21
37
  const remoteCmd = this.config.remoteCommand ?? "code-shell run --output stream-json";
22
- this.ssh = spawn("ssh", [...sshArgs, remoteCmd], {
23
- stdio: ["pipe", "pipe", "pipe"],
24
- });
38
+ this.ssh = this.spawnFn("ssh", [...sshArgs, remoteCmd]);
25
39
  return new Promise((resolve, reject) => {
40
+ // Settle exactly once: the first stdout resolves; an error/early-exit
41
+ // before that rejects. Events after settlement are ignored (the old
42
+ // code re-rejected an already-settled promise and used a dead
43
+ // `if (!this.connected)` guard that was always true).
44
+ let settled = false;
26
45
  const timer = setTimeout(() => {
46
+ if (settled)
47
+ return;
48
+ settled = true;
27
49
  reject(new Error("SSH connection timed out"));
28
50
  this.disconnect();
29
51
  }, 30000);
30
52
  this.ssh.stdout?.once("data", () => {
53
+ if (settled)
54
+ return;
55
+ settled = true;
31
56
  clearTimeout(timer);
32
57
  this.connected = true;
33
58
  resolve();
34
59
  });
35
60
  this.ssh.on("error", (err) => {
61
+ if (settled)
62
+ return;
63
+ settled = true;
36
64
  clearTimeout(timer);
37
65
  reject(err);
38
66
  });
39
67
  this.ssh.on("exit", (code) => {
40
68
  this.connected = false;
41
- if (!this.connected) {
42
- clearTimeout(timer);
43
- reject(new Error(`SSH exited with code ${code}`));
44
- }
69
+ if (settled)
70
+ return;
71
+ settled = true;
72
+ clearTimeout(timer);
73
+ reject(new Error(`SSH exited with code ${code}`));
45
74
  });
46
75
  });
47
76
  }
@@ -52,7 +81,13 @@ export class RemoteBridge {
52
81
  if (!this.connected || !this.ssh?.stdin) {
53
82
  throw new Error("Not connected");
54
83
  }
55
- this.ssh.stdin.write(JSON.stringify(message) + "\n");
84
+ this.ssh.stdin.write(JSON.stringify(message) + "\n", (err) => {
85
+ if (err) {
86
+ // A broken pipe means the remote is gone — surface it as a
87
+ // disconnect rather than swallowing the failed write.
88
+ this.connected = false;
89
+ }
90
+ });
56
91
  }
57
92
  /**
58
93
  * Async iterator for messages from the remote code-shell.
@@ -61,17 +96,24 @@ export class RemoteBridge {
61
96
  if (!this.ssh?.stdout)
62
97
  return;
63
98
  const rl = createInterface({ input: this.ssh.stdout, crlfDelay: Infinity });
64
- for await (const line of rl) {
65
- const trimmed = line.trim();
66
- if (!trimmed)
67
- continue;
68
- try {
69
- yield JSON.parse(trimmed);
70
- }
71
- catch {
72
- // Skip malformed
99
+ try {
100
+ for await (const line of rl) {
101
+ const trimmed = line.trim();
102
+ if (!trimmed)
103
+ continue;
104
+ try {
105
+ yield JSON.parse(trimmed);
106
+ }
107
+ catch {
108
+ // Skip malformed
109
+ }
73
110
  }
74
111
  }
112
+ finally {
113
+ // Close the interface if the consumer breaks/returns early — otherwise
114
+ // it (and its stdout listener) leaks.
115
+ rl.close();
116
+ }
75
117
  }
76
118
  /**
77
119
  * Disconnect from the remote host.
@@ -86,18 +128,4 @@ export class RemoteBridge {
86
128
  get isConnected() {
87
129
  return this.connected;
88
130
  }
89
- buildSSHArgs() {
90
- const args = ["-T"]; // No pseudo-terminal
91
- if (this.config.port)
92
- args.push("-p", String(this.config.port));
93
- if (this.config.identityFile)
94
- args.push("-i", this.config.identityFile);
95
- if (this.config.user) {
96
- args.push(`${this.config.user}@${this.config.host}`);
97
- }
98
- else {
99
- args.push(this.config.host);
100
- }
101
- return args;
102
- }
103
131
  }
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Code-review prompt builder (TODO 7.3). Produces the instruction sent to the
3
+ * model for `/review`. Pure + testable — the TUI/desktop command gathers the
4
+ * diff or file contents and calls this; the model does the actual reasoning.
5
+ *
6
+ * Findings are structured: priority P0–P3, a confidence score, and a precise
7
+ * location, so the output is consistent and (optionally) machine-readable for
8
+ * CI/CD via `--json`.
9
+ */
10
+ export type ReviewDimension = "security" | "performance" | "readability" | "correctness";
11
+ export declare const ALL_DIMENSIONS: ReviewDimension[];
12
+ export interface ReviewPromptOptions {
13
+ /** The unified diff (incremental) or full file contents to review. */
14
+ content: string;
15
+ /** Which dimensions to weigh. Defaults to all four. */
16
+ dimensions?: ReviewDimension[];
17
+ /** True when reviewing a diff (incremental); false when reviewing whole files. */
18
+ incremental?: boolean;
19
+ /** Emit a machine-readable JSON findings array (for CI/CD) instead of prose. */
20
+ json?: boolean;
21
+ /** Optional label for what's under review (e.g. a file path). */
22
+ label?: string;
23
+ /** Truncate content to this many chars (default 12000). */
24
+ maxChars?: number;
25
+ }
26
+ /** Normalize a comma/space list of dimension names; invalid names dropped. */
27
+ export declare function parseDimensions(input: string | undefined): ReviewDimension[];
28
+ export declare function buildReviewPrompt(opts: ReviewPromptOptions): string;
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Code-review prompt builder (TODO 7.3). Produces the instruction sent to the
3
+ * model for `/review`. Pure + testable — the TUI/desktop command gathers the
4
+ * diff or file contents and calls this; the model does the actual reasoning.
5
+ *
6
+ * Findings are structured: priority P0–P3, a confidence score, and a precise
7
+ * location, so the output is consistent and (optionally) machine-readable for
8
+ * CI/CD via `--json`.
9
+ */
10
+ export const ALL_DIMENSIONS = [
11
+ "correctness",
12
+ "security",
13
+ "performance",
14
+ "readability",
15
+ ];
16
+ const DIMENSION_LABEL = {
17
+ security: "安全 (injection, authz, secret leakage, unsafe deserialization)",
18
+ performance: "性能 (N+1, needless allocation, blocking I/O, complexity)",
19
+ readability: "可读性 (naming, structure, dead code, comment accuracy)",
20
+ correctness: "正确性 (logic bugs, edge cases, error handling, races)",
21
+ };
22
+ /** Normalize a comma/space list of dimension names; invalid names dropped. */
23
+ export function parseDimensions(input) {
24
+ if (!input)
25
+ return ALL_DIMENSIONS;
26
+ const wanted = input
27
+ .split(/[\s,]+/)
28
+ .map((s) => s.trim().toLowerCase())
29
+ .filter(Boolean);
30
+ const picked = ALL_DIMENSIONS.filter((d) => wanted.includes(d));
31
+ return picked.length > 0 ? picked : ALL_DIMENSIONS;
32
+ }
33
+ const PRIORITY_GUIDE = "Priority: P0 = must fix before merge (data loss, security hole, crash); " +
34
+ "P1 = should fix (likely bug, real risk); " +
35
+ "P2 = nice to fix (smell, minor inefficiency); " +
36
+ "P3 = optional (style, nit).";
37
+ export function buildReviewPrompt(opts) {
38
+ const dims = opts.dimensions?.length ? opts.dimensions : ALL_DIMENSIONS;
39
+ const maxChars = opts.maxChars ?? 12_000;
40
+ const body = opts.content.length > maxChars
41
+ ? opts.content.slice(0, maxChars) + "\n…(truncated)…"
42
+ : opts.content;
43
+ const fence = opts.incremental === false ? "" : "diff";
44
+ const what = opts.incremental === false ? "code" : "code changes (diff)";
45
+ const subject = opts.label ? ` for \`${opts.label}\`` : "";
46
+ const dimLines = dims.map((d) => ` - ${DIMENSION_LABEL[d]}`).join("\n");
47
+ if (opts.json) {
48
+ return [
49
+ `Review the following ${what}${subject} across these dimensions:`,
50
+ dimLines,
51
+ ``,
52
+ PRIORITY_GUIDE,
53
+ ``,
54
+ `Respond with ONLY a JSON object (no prose, no markdown fence) of the form:`,
55
+ `{"summary": string, "findings": [{"priority": "P0"|"P1"|"P2"|"P3", ` +
56
+ `"dimension": ${dims.map((d) => `"${d}"`).join("|")}, ` +
57
+ `"confidence": number /*0..1*/, "location": string /*file:line*/, ` +
58
+ `"title": string, "detail": string, "suggestion": string}]}`,
59
+ `Order findings by priority then confidence. Omit a finding rather than guess.`,
60
+ ``,
61
+ "```" + fence,
62
+ body,
63
+ "```",
64
+ ].join("\n");
65
+ }
66
+ return [
67
+ `Review the following ${what}${subject} across these dimensions:`,
68
+ dimLines,
69
+ ``,
70
+ PRIORITY_GUIDE,
71
+ ``,
72
+ `For each finding, give: **[P0-P3]** a short title, the location (file:line), ` +
73
+ `your confidence (low/med/high), what's wrong, and a concrete fix.`,
74
+ `Start with a one-line summary, then list findings ordered by priority. ` +
75
+ `If nothing warrants a finding, say so plainly. Don't pad with nits to look thorough.`,
76
+ ``,
77
+ "```" + fence,
78
+ body,
79
+ "```",
80
+ ].join("\n");
81
+ }
@@ -12,6 +12,7 @@
12
12
  * - Judgment: file writes are artifacts, reads are not
13
13
  */
14
14
  import { nanoid } from "nanoid";
15
+ import { parseRedirectTarget } from "./redirect-target.js";
15
16
  export class ArtifactTracker {
16
17
  config;
17
18
  pendingCalls = new Map();
@@ -111,10 +112,10 @@ export class ArtifactTracker {
111
112
  await this.config.store.appendArtifactRef(ref);
112
113
  return;
113
114
  }
114
- // Redirect output: command > file or command >> file
115
- const redirectMatch = trimmed.match(/>\s*(\S+)\s*$/);
116
- if (redirectMatch) {
117
- await this.recordFileArtifact(redirectMatch[1], "output", "file");
115
+ // Redirect output: command > file or command >> file (quoted-path aware)
116
+ const redirectTarget = parseRedirectTarget(trimmed);
117
+ if (redirectTarget) {
118
+ await this.recordFileArtifact(redirectTarget, "output", "file");
118
119
  return;
119
120
  }
120
121
  // cp / mv — destination is an artifact
@@ -9,9 +9,25 @@
9
9
  * - Return execution result (does NOT manage run state transitions)
10
10
  */
11
11
  import { type EngineConfig, type EngineHookConfig } from "../engine/engine.js";
12
- import type { LLMConfig, RegisteredTool } from "../types.js";
12
+ import type { ClientDefaults, LLMConfig, RegisteredTool } from "../types.js";
13
13
  import type { RunSnapshot, RunExecutionContext, RunExecutionResult } from "./types.js";
14
14
  import { type RunLifecycleHooks } from "./RunApprovalBackend.js";
15
+ import type { ApprovalBackend } from "../tool-system/permission.js";
16
+ /** Unattended runs (those with an injected approval backend) run headless so
17
+ * the in-process AgentServer does not wire an interactive askUser. Exported
18
+ * for unit testing the decision rule. */
19
+ export declare function buildHeadlessFlag(override: ApprovalBackend | undefined): boolean;
20
+ /** Run-metadata `source` value tagging a run as unattended automation
21
+ * (set by the automation host; read here to decide prompt/headless behavior). */
22
+ export declare const AUTOMATION_RUN_SOURCE = "automation";
23
+ /** Appended to the system prompt for unattended automation runs so the model
24
+ * knows it IS the automation and must not ask the user or offer to schedule
25
+ * automation. English by repo convention; the model answers in the user's
26
+ * language regardless. */
27
+ export declare const AUTOMATION_PROMPT_NOTE: string;
28
+ /** Compose the run's appendSystemPrompt: prepend the automation note when the
29
+ * run is tagged source "automation", preserving any host-provided append. */
30
+ export declare function buildAppendSystemPrompt(hostAppend: string | undefined, metadata: Record<string, unknown> | undefined): string | undefined;
15
31
  /**
16
32
  * Handles returned from execute() to allow RunManager to resolve
17
33
  * pending approvals and user input while Engine is suspended.
@@ -48,6 +64,8 @@ export interface CustomToolEntry {
48
64
  }
49
65
  export interface EngineRunnerConfig {
50
66
  llm: LLMConfig;
67
+ /** Cross-model runtime knobs (temperature/timeout/imageDetail). */
68
+ clientDefaults?: ClientDefaults;
51
69
  maxTurns?: number;
52
70
  maxContextTokens?: number;
53
71
  sessionStorageDir?: string;
@@ -61,6 +79,14 @@ export interface EngineRunnerConfig {
61
79
  customTools?: CustomToolEntry[];
62
80
  /** Hooks registered into each Engine instance before run execution. */
63
81
  hooks?: EngineHookConfig[];
82
+ /**
83
+ * Override the approval backend. When set, the run uses THIS backend instead
84
+ * of the interactive run-aware RunApprovalBackend — used by unattended hosts
85
+ * (e.g. automation/cron) that must auto-decide without a UI, e.g. a
86
+ * HeadlessApprovalBackend("approve-read-only"). When unset, the interactive
87
+ * run-aware backend is used (default REPL/desktop behavior).
88
+ */
89
+ approvalBackend?: ApprovalBackend;
64
90
  }
65
91
  export declare class EngineRunner implements RunExecutor {
66
92
  private readonly config;
@@ -11,6 +11,33 @@
11
11
  import { Engine } from "../engine/engine.js";
12
12
  import { RunApprovalBackend, createRunAskUserFn, } from "./RunApprovalBackend.js";
13
13
  import { createInProcessClient } from "../protocol/helpers.js";
14
+ /** Unattended runs (those with an injected approval backend) run headless so
15
+ * the in-process AgentServer does not wire an interactive askUser. Exported
16
+ * for unit testing the decision rule. */
17
+ export function buildHeadlessFlag(override) {
18
+ return override !== undefined;
19
+ }
20
+ /** Run-metadata `source` value tagging a run as unattended automation
21
+ * (set by the automation host; read here to decide prompt/headless behavior). */
22
+ export const AUTOMATION_RUN_SOURCE = "automation";
23
+ /** Appended to the system prompt for unattended automation runs so the model
24
+ * knows it IS the automation and must not ask the user or offer to schedule
25
+ * automation. English by repo convention; the model answers in the user's
26
+ * language regardless. */
27
+ export const AUTOMATION_PROMPT_NOTE = "This is an unattended, scheduled automation run. No human is watching, and " +
28
+ "AskUserQuestion will not reach anyone. You ARE the automation — do not ask " +
29
+ "the user questions and do not offer to set up or schedule automation. " +
30
+ "Produce the requested output directly; when uncertain, state your assumption " +
31
+ "and proceed." +
32
+ " When finished, call UpdateAutomationMemory exactly once with a concise " +
33
+ "summary of this run's key findings/state for the next run.";
34
+ /** Compose the run's appendSystemPrompt: prepend the automation note when the
35
+ * run is tagged source "automation", preserving any host-provided append. */
36
+ export function buildAppendSystemPrompt(hostAppend, metadata) {
37
+ if (metadata?.source !== AUTOMATION_RUN_SOURCE)
38
+ return hostAppend;
39
+ return hostAppend ? `${AUTOMATION_PROMPT_NOTE}\n\n${hostAppend}` : AUTOMATION_PROMPT_NOTE;
40
+ }
14
41
  // ─── EngineRunner (built-in RunExecutor) ────────────────────────
15
42
  export class EngineRunner {
16
43
  config;
@@ -18,23 +45,30 @@ export class EngineRunner {
18
45
  this.config = config;
19
46
  }
20
47
  async execute(run, context, lifecycleHooks, onHandleReady) {
21
- // Create run-aware approval backend
22
- const approvalBackend = new RunApprovalBackend();
48
+ // Run-aware approval backend (interactive: suspends the run and waits for
49
+ // RunManager to resolve via the handle). Always constructed so the handle
50
+ // stays well-formed, but only wired into the engine when no override is set.
51
+ const runApprovalBackend = new RunApprovalBackend();
52
+ // Unattended override: a host (automation/cron) can inject a backend that
53
+ // auto-decides (e.g. approve-read-only). When set, the engine uses it and
54
+ // the interactive resolve path is inert (no UI to resolve approvals).
55
+ const override = this.config.approvalBackend;
56
+ const engineApprovalBackend = override ?? runApprovalBackend;
23
57
  // Create run-aware askUser adapter
24
58
  let resolveInputFn = () => false;
25
59
  let hasPendingInputFn = () => false;
26
60
  let askUserFn;
27
- if (lifecycleHooks) {
28
- approvalBackend.setHooks(lifecycleHooks);
61
+ if (lifecycleHooks && !override) {
62
+ runApprovalBackend.setHooks(lifecycleHooks);
29
63
  const askAdapter = createRunAskUserFn(lifecycleHooks);
30
64
  askUserFn = askAdapter.askUserFn;
31
65
  resolveInputFn = askAdapter.resolveInput;
32
66
  hasPendingInputFn = askAdapter.hasPendingInput;
33
67
  }
34
68
  const handle = {
35
- resolveApproval: (approved, reason) => approvalBackend.resolveApproval(approved ? { approved: true } : { approved: false, reason }),
69
+ resolveApproval: (approved, reason) => runApprovalBackend.resolveApproval(approved ? { approved: true } : { approved: false, reason }),
36
70
  resolveInput: resolveInputFn,
37
- hasPendingApproval: () => approvalBackend.hasPendingApproval(),
71
+ hasPendingApproval: () => runApprovalBackend.hasPendingApproval(),
38
72
  hasPendingInput: hasPendingInputFn,
39
73
  };
40
74
  // Expose handle immediately so RunManager can resolve approvals/input
@@ -42,19 +76,23 @@ export class EngineRunner {
42
76
  onHandleReady?.(handle);
43
77
  const engineConfig = {
44
78
  llm: this.config.llm,
79
+ clientDefaults: this.config.clientDefaults,
45
80
  cwd: run.cwd,
46
81
  maxTurns: this.config.maxTurns ?? 30,
47
82
  maxContextTokens: this.config.maxContextTokens ?? 200_000,
48
83
  permissionMode: this.config.permissionMode ?? "acceptEdits",
84
+ headless: buildHeadlessFlag(override),
49
85
  preset: run.preset,
50
86
  enabledBuiltinTools: this.config.enabledBuiltinTools,
51
87
  disabledBuiltinTools: this.config.disabledBuiltinTools,
52
88
  customSystemPrompt: this.config.customSystemPrompt,
53
- appendSystemPrompt: this.config.appendSystemPrompt,
89
+ // NOTE: callers must not pass appendSystemPrompt in engineConfigOverrides
90
+ // below, or it will clobber this composed (automation note + host) value.
91
+ appendSystemPrompt: buildAppendSystemPrompt(this.config.appendSystemPrompt, run.metadata),
54
92
  sessionStorageDir: this.config.sessionStorageDir,
55
93
  mcpServers: this.config.mcpServers,
56
94
  hooks: this.config.hooks,
57
- approvalBackend,
95
+ approvalBackend: engineApprovalBackend,
58
96
  askUser: askUserFn,
59
97
  ...context.engineConfigOverrides,
60
98
  };
@@ -32,9 +32,16 @@ export class FileRunStore {
32
32
  }
33
33
  writeJson(filePath, data) {
34
34
  const tmp = filePath + ".tmp";
35
- writeFileSync(tmp, JSON.stringify(data, null, 2), "utf-8");
36
- // Atomic rename prevents partial writes on crash
37
- renameSync(tmp, filePath);
35
+ try {
36
+ writeFileSync(tmp, JSON.stringify(data, null, 2), "utf-8");
37
+ // Atomic rename — prevents partial writes on crash
38
+ renameSync(tmp, filePath);
39
+ }
40
+ catch (err) {
41
+ // Don't leave a dangling .tmp behind on a failed write/rename.
42
+ rmSync(tmp, { force: true });
43
+ throw err;
44
+ }
38
45
  }
39
46
  readJson(filePath) {
40
47
  if (!existsSync(filePath))
@@ -44,13 +51,30 @@ export class FileRunStore {
44
51
  /** Serializes concurrent JSONL appends per file path. */
45
52
  appendLocks = new Map();
46
53
  async appendJsonl(filePath, data) {
47
- // Serialize writes to the same file to prevent interleaved output
54
+ // Serialize writes to the same file to prevent interleaved output. The
55
+ // chain we STORE as the lock must never reject — otherwise a single failed
56
+ // write poisons the lock and every later write chains off the rejected
57
+ // promise, skips its callback, and fails forever. So sequence off the
58
+ // previous lock's settlement (.catch(()=>{})), do the write, and surface
59
+ // this write's own error to *this* caller via a separate promise.
48
60
  const prev = this.appendLocks.get(filePath) ?? Promise.resolve();
49
- const current = prev.then(() => {
50
- appendFileSync(filePath, JSON.stringify(data) + "\n", "utf-8");
61
+ let settle;
62
+ const lock = new Promise((resolve) => {
63
+ settle = resolve;
51
64
  });
52
- this.appendLocks.set(filePath, current);
53
- await current;
65
+ this.appendLocks.set(filePath, lock);
66
+ try {
67
+ await prev.catch(() => { });
68
+ appendFileSync(filePath, JSON.stringify(data) + "\n", "utf-8");
69
+ }
70
+ finally {
71
+ // Release the lock for the next writer regardless of success/failure,
72
+ // and drop the map entry if no newer writer has queued behind us.
73
+ settle();
74
+ if (this.appendLocks.get(filePath) === lock) {
75
+ this.appendLocks.delete(filePath);
76
+ }
77
+ }
54
78
  }
55
79
  readJsonl(filePath) {
56
80
  if (!existsSync(filePath))
@@ -102,9 +126,14 @@ export class FileRunStore {
102
126
  }
103
127
  // Sort by createdAt descending (newest first)
104
128
  snapshots.sort((a, b) => b.createdAt - a.createdAt);
105
- // Pagination
106
- const offset = query?.offset ?? 0;
107
- const limit = query?.limit ?? 50;
129
+ // Pagination. Clamp to sane bounds before slicing: a negative offset would
130
+ // make Array.slice count "from the end" and silently return a surprise tail
131
+ // window; a negative limit would drop elements off the end. Both nonsensical
132
+ // for pagination — clamp offset≥0, treat a non-positive limit as an empty page.
133
+ const rawOffset = query?.offset ?? 0;
134
+ const rawLimit = query?.limit ?? 50;
135
+ const offset = Number.isFinite(rawOffset) && rawOffset > 0 ? Math.floor(rawOffset) : 0;
136
+ const limit = Number.isFinite(rawLimit) && rawLimit > 0 ? Math.floor(rawLimit) : 0;
108
137
  return snapshots.slice(offset, offset + limit);
109
138
  }
110
139
  async delete(runId) {
@@ -24,8 +24,15 @@ export class RunApprovalBackend {
24
24
  }
25
25
  async requestApproval(request) {
26
26
  if (!this.hooks) {
27
- // No hooks wired — fall back to auto-approve (shouldn't happen in practice)
28
- return { approved: true };
27
+ // No hooks wired — fail CLOSED. This backend is the engine's approval
28
+ // path for an interactive run; if a host forgot to setHooks() there is
29
+ // no UI to ask, so auto-approving every tool (the old behavior) silently
30
+ // bypassed all approval. Denying is the safe default — a misconfigured
31
+ // run refuses tools instead of running `rm -rf /` unattended. (§5.6 #15)
32
+ return {
33
+ approved: false,
34
+ reason: "run approval backend has no lifecycle hooks wired (denied fail-closed)",
35
+ };
29
36
  }
30
37
  // Notify RunManager that approval is needed
31
38
  const { approvalId } = await this.hooks.onApprovalNeeded(request);
@@ -64,12 +71,25 @@ export class RunApprovalBackend {
64
71
  */
65
72
  export function createRunAskUserFn(hooks) {
66
73
  let pending = null;
74
+ const supersedePending = () => {
75
+ // A run suspends on a single input at a time (RunManager resolves via one
76
+ // handle). If a second ask arrives while one is still pending, the old
77
+ // code overwrote the slot and the first promise hung forever. Reject the
78
+ // prior one so its awaiter unblocks instead of leaking. (§5.6 #15)
79
+ if (pending) {
80
+ pending.reject(new Error("superseded: a newer AskUser request replaced this one before it was answered"));
81
+ pending = null;
82
+ }
83
+ };
67
84
  const askUserFn = async (question) => {
68
85
  // Notify RunManager
69
86
  await hooks.onInputNeeded(question);
70
- // Suspend execution until user provides input
71
- return new Promise((resolve) => {
72
- pending = { resolve, question };
87
+ // Suspend execution until user provides input. The supersede check runs
88
+ // here AFTER the await — so it sees a `pending` set by an earlier ask
89
+ // whose own await already resolved, rather than racing the assignment.
90
+ return new Promise((resolve, reject) => {
91
+ supersedePending();
92
+ pending = { resolve, reject, question };
73
93
  });
74
94
  };
75
95
  const resolveInput = (answer) => {
@@ -10,16 +10,42 @@ export interface RunLockConfig {
10
10
  runsDir?: string;
11
11
  /** Stale lock timeout in ms. Default: 60_000 (1 minute) */
12
12
  staleMs?: number;
13
+ /** How long to wait for runs/<id>/run.json to appear before failing. */
14
+ targetWaitMs?: number;
15
+ /** Poll interval while waiting for the lock target file. */
16
+ targetPollMs?: number;
13
17
  }
18
+ export type RunLockAcquireResult = {
19
+ acquired: true;
20
+ } | {
21
+ acquired: false;
22
+ reason: "missing_target" | "locked";
23
+ message?: string;
24
+ code?: string;
25
+ };
14
26
  export declare class RunLock {
15
27
  private readonly runsDir;
16
28
  private readonly staleMs;
29
+ private readonly targetWaitMs;
30
+ private readonly targetPollMs;
17
31
  private readonly releaseFns;
18
32
  constructor(config?: RunLockConfig);
19
33
  /**
20
- * Acquire a lock for a run. Returns true if acquired, false if already held.
34
+ * Acquire a lock for a run. Missing target and held-lock failures are
35
+ * intentionally distinct so callers don't silently abandon a run as "locked"
36
+ * when the real issue is a bad/mismatched run store path.
37
+ *
38
+ * Race note: if the queue reaches acquire() before the file is visible, a
39
+ * short wait bridges that gap. Only a proper-lockfile conflict is "locked".
21
40
  */
22
- acquire(runId: string): Promise<boolean>;
41
+ acquire(runId: string): Promise<RunLockAcquireResult>;
42
+ /**
43
+ * Wait (up to ~targetWaitMs) for the lock target file to exist, polling on a
44
+ * short interval. Returns true once present, false if it never appears
45
+ * within the window. Bridges the submit→executeRun create race without
46
+ * blocking meaningfully when the file is already there (first check hits).
47
+ */
48
+ private waitForTarget;
23
49
  /**
24
50
  * Release the lock for a run.
25
51
  */