@the-open-engine/zeroshot 6.38.0 → 6.39.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (381) hide show
  1. package/cli/event-copy.js +8 -7
  2. package/cli/event-copy.ts +12 -0
  3. package/cli/index.js +7 -31
  4. package/cli/json-export.js +61 -64
  5. package/cli/json-export.ts +112 -0
  6. package/cli/message-formatter-utils.js +68 -56
  7. package/cli/message-formatter-utils.ts +121 -0
  8. package/cli/message-formatters-normal.js +124 -259
  9. package/cli/message-formatters-normal.ts +250 -0
  10. package/cli/message-formatters-watch.js +81 -84
  11. package/cli/message-formatters-watch.ts +189 -0
  12. package/lib/agent-cli-provider/adapters/codex.d.ts.map +1 -1
  13. package/lib/agent-cli-provider/adapters/codex.js +3 -1
  14. package/lib/agent-cli-provider/adapters/codex.js.map +1 -1
  15. package/lib/cluster/generated/protocol-schema.cjs +1 -1
  16. package/lib/cluster/generated/protocol-schema.mjs +1 -1
  17. package/lib/cluster/generated/protocol.d.cts +8 -0
  18. package/lib/cluster/generated/protocol.d.mts +8 -0
  19. package/lib/cluster/generated/protocol.d.ts +8 -0
  20. package/lib/clusters-registry.d.ts +23 -0
  21. package/lib/clusters-registry.js +17 -29
  22. package/lib/completion.d.ts +12 -0
  23. package/lib/completion.js +84 -94
  24. package/lib/compose-utils.d.ts +32 -0
  25. package/lib/compose-utils.js +57 -72
  26. package/lib/detached-startup.d.ts +83 -0
  27. package/lib/detached-startup.js +231 -302
  28. package/lib/docker-config.d.ts +43 -0
  29. package/lib/docker-config.js +150 -325
  30. package/lib/docker-env-auth.d.ts +17 -0
  31. package/lib/docker-env-auth.js +75 -0
  32. package/lib/git-remote-utils.d.ts +48 -0
  33. package/lib/git-remote-utils.js +147 -213
  34. package/lib/id-detector.d.ts +15 -0
  35. package/lib/id-detector.js +37 -41
  36. package/lib/path-check.d.ts +30 -0
  37. package/lib/path-check.js +42 -45
  38. package/lib/process-liveness.d.ts +16 -0
  39. package/lib/process-liveness.js +19 -12
  40. package/lib/provider-credential-path.d.ts +16 -0
  41. package/lib/provider-credential-path.js +31 -29
  42. package/lib/provider-defaults.d.ts +30 -0
  43. package/lib/provider-defaults.js +47 -42
  44. package/lib/provider-detection.d.ts +11 -0
  45. package/lib/provider-detection.js +91 -54
  46. package/lib/provider-names.d.ts +38 -0
  47. package/lib/provider-names.js +56 -64
  48. package/lib/repo-settings.d.ts +28 -0
  49. package/lib/repo-settings.js +83 -59
  50. package/lib/run-mode.d.ts +21 -0
  51. package/lib/run-mode.js +21 -20
  52. package/lib/run-plan.d.ts +28 -0
  53. package/lib/run-plan.js +17 -16
  54. package/lib/settings/claude-auth.d.ts +35 -0
  55. package/lib/settings/claude-auth.js +30 -47
  56. package/lib/settings-defaults.d.ts +20 -0
  57. package/lib/settings-defaults.js +149 -0
  58. package/lib/settings-error.d.ts +7 -0
  59. package/lib/settings-error.js +8 -0
  60. package/lib/settings-issue-providers.d.ts +10 -0
  61. package/lib/settings-issue-providers.js +12 -0
  62. package/lib/settings-models.d.ts +22 -0
  63. package/lib/settings-models.js +93 -0
  64. package/lib/settings-storage.d.ts +23 -0
  65. package/lib/settings-storage.js +205 -0
  66. package/lib/settings-validation.d.ts +7 -0
  67. package/lib/settings-validation.js +182 -0
  68. package/lib/settings.d.ts +29 -0
  69. package/lib/settings.js +41 -736
  70. package/lib/setup-apply-types.d.ts +66 -0
  71. package/lib/setup-apply-types.js +2 -0
  72. package/lib/setup-apply.d.ts +39 -0
  73. package/lib/setup-apply.js +267 -264
  74. package/lib/setup-journal.d.ts +41 -0
  75. package/lib/setup-journal.js +119 -76
  76. package/lib/setup-plan-types.d.ts +102 -0
  77. package/lib/setup-plan-types.js +2 -0
  78. package/lib/setup-plan.d.ts +30 -0
  79. package/lib/setup-plan.js +300 -324
  80. package/lib/setup-undo.d.ts +44 -0
  81. package/lib/setup-undo.js +61 -74
  82. package/lib/start-cluster-config.d.ts +26 -0
  83. package/lib/start-cluster-config.js +56 -0
  84. package/lib/start-cluster-environment.d.ts +40 -0
  85. package/lib/start-cluster-environment.js +134 -0
  86. package/lib/start-cluster-run-options.d.ts +53 -0
  87. package/lib/start-cluster-run-options.js +147 -0
  88. package/lib/start-cluster.d.ts +64 -0
  89. package/lib/start-cluster.js +98 -454
  90. package/lib/stream-json-parser.d.ts +17 -0
  91. package/lib/stream-json-parser.js +51 -52
  92. package/npm-shrinkwrap.json +2 -2
  93. package/package.json +12 -6
  94. package/scripts/postinstall.js +27 -0
  95. package/scripts/rust-distribution.js +23 -14
  96. package/src/agent/agent-command-proofs-context.js +35 -45
  97. package/src/agent/agent-command-proofs-context.ts +87 -0
  98. package/src/agent/agent-config-settings.js +19 -0
  99. package/src/agent/agent-config-settings.ts +41 -0
  100. package/src/agent/agent-config.js +122 -231
  101. package/src/agent/agent-config.ts +285 -0
  102. package/src/agent/agent-context-builder.js +38 -273
  103. package/src/agent/agent-context-builder.ts +51 -0
  104. package/src/agent/agent-context-environment-sections.js +105 -0
  105. package/src/agent/agent-context-environment-sections.ts +134 -0
  106. package/src/agent/agent-context-packs.js +165 -0
  107. package/src/agent/agent-context-packs.ts +296 -0
  108. package/src/agent/agent-context-prompt-sections.js +100 -0
  109. package/src/agent/agent-context-prompt-sections.ts +148 -0
  110. package/src/agent/agent-context-sections.js +25 -334
  111. package/src/agent/agent-context-sections.ts +36 -0
  112. package/src/agent/agent-context-sources.js +96 -149
  113. package/src/agent/agent-context-sources.ts +253 -0
  114. package/src/agent/agent-context-types.js +2 -0
  115. package/src/agent/agent-context-types.ts +132 -0
  116. package/src/agent/agent-context-validation-sections.js +73 -0
  117. package/src/agent/agent-context-validation-sections.ts +129 -0
  118. package/src/agent/agent-input-injector.js +99 -118
  119. package/src/agent/agent-input-injector.ts +195 -0
  120. package/src/agent/agent-liveness-poll.js +74 -78
  121. package/src/agent/agent-liveness-poll.ts +163 -0
  122. package/src/agent/agent-quality-gate-schema.js +77 -86
  123. package/src/agent/agent-quality-gate-schema.ts +135 -0
  124. package/src/agent/agent-quality-gates-context.js +44 -50
  125. package/src/agent/agent-quality-gates-context.ts +91 -0
  126. package/src/agent/agent-stuck-detector.js +171 -239
  127. package/src/agent/agent-stuck-detector.ts +288 -0
  128. package/src/agent/agent-trigger-evaluator.js +29 -46
  129. package/src/agent/agent-trigger-evaluator.ts +98 -0
  130. package/src/agent/context-metrics.js +110 -141
  131. package/src/agent/context-metrics.ts +261 -0
  132. package/src/agent/context-pack-builder.js +72 -358
  133. package/src/agent/context-pack-builder.ts +105 -0
  134. package/src/agent/context-pack-core.js +70 -0
  135. package/src/agent/context-pack-core.ts +96 -0
  136. package/src/agent/context-pack-selection.js +119 -0
  137. package/src/agent/context-pack-selection.ts +187 -0
  138. package/src/agent/context-pack-truncation.js +139 -0
  139. package/src/agent/context-pack-truncation.ts +208 -0
  140. package/src/agent/context-pack-types.js +2 -0
  141. package/src/agent/context-pack-types.ts +98 -0
  142. package/src/agent/context-replay-policy.js +30 -39
  143. package/src/agent/context-replay-policy.ts +71 -0
  144. package/src/agent/critical-agent-policy.js +6 -10
  145. package/src/agent/critical-agent-policy.ts +20 -0
  146. package/src/agent/guidance-queue.js +74 -87
  147. package/src/agent/guidance-queue.ts +166 -0
  148. package/src/agent/output-extraction-error-detail.js +45 -0
  149. package/src/agent/output-extraction-error-detail.ts +49 -0
  150. package/src/agent/output-extraction-failures.js +125 -0
  151. package/src/agent/output-extraction-failures.ts +149 -0
  152. package/src/agent/output-extraction-json.js +234 -0
  153. package/src/agent/output-extraction-json.ts +235 -0
  154. package/src/agent/output-extraction-pi.js +124 -0
  155. package/src/agent/output-extraction-pi.ts +137 -0
  156. package/src/agent/output-extraction-types.js +2 -0
  157. package/src/agent/output-extraction-types.ts +49 -0
  158. package/src/agent/output-extraction.js +17 -617
  159. package/src/agent/output-extraction.ts +30 -0
  160. package/src/agent/output-reformatter-errors.js +83 -0
  161. package/src/agent/output-reformatter-errors.ts +106 -0
  162. package/src/agent/output-reformatter-types.js +2 -0
  163. package/src/agent/output-reformatter-types.ts +86 -0
  164. package/src/agent/output-reformatter.js +140 -185
  165. package/src/agent/output-reformatter.ts +238 -0
  166. package/src/agent/pi-terminal-lifecycle-types.js +2 -0
  167. package/src/agent/pi-terminal-lifecycle-types.ts +41 -0
  168. package/src/agent/pi-terminal-lifecycle.js +186 -206
  169. package/src/agent/pi-terminal-lifecycle.ts +297 -0
  170. package/src/agent/provider-control-plane.js +22 -21
  171. package/src/agent/provider-control-plane.ts +52 -0
  172. package/src/agent/provider-terminal-failure-types.js +2 -0
  173. package/src/agent/provider-terminal-failure-types.ts +60 -0
  174. package/src/agent/provider-terminal-failure.js +194 -191
  175. package/src/agent/provider-terminal-failure.ts +262 -0
  176. package/src/agent/rate-limit-backoff.js +31 -74
  177. package/src/agent/rate-limit-backoff.ts +71 -0
  178. package/src/agent/schema-utils.js +85 -125
  179. package/src/agent/schema-utils.ts +148 -0
  180. package/src/agent/structured-output-error.js +34 -33
  181. package/src/agent/structured-output-error.ts +105 -0
  182. package/src/agent/validation-platform.js +27 -27
  183. package/src/agent/validation-platform.ts +49 -0
  184. package/src/agent-cli-provider/adapters/codex.ts +3 -1
  185. package/src/attach/attach-client.js +232 -405
  186. package/src/attach/attach-client.ts +300 -0
  187. package/src/attach/attach-server-cleanup.js +43 -0
  188. package/src/attach/attach-server-cleanup.ts +39 -0
  189. package/src/attach/attach-server-clients.js +117 -0
  190. package/src/attach/attach-server-clients.ts +122 -0
  191. package/src/attach/attach-server-events.js +38 -0
  192. package/src/attach/attach-server-events.ts +36 -0
  193. package/src/attach/attach-server-pty.js +45 -0
  194. package/src/attach/attach-server-pty.ts +64 -0
  195. package/src/attach/attach-server-runtime.js +73 -0
  196. package/src/attach/attach-server-runtime.ts +62 -0
  197. package/src/attach/attach-server-socket.js +28 -0
  198. package/src/attach/attach-server-socket.ts +23 -0
  199. package/src/attach/attach-server-types.js +2 -0
  200. package/src/attach/attach-server-types.ts +82 -0
  201. package/src/attach/attach-server.js +106 -523
  202. package/src/attach/attach-server.ts +158 -0
  203. package/src/attach/index.js +18 -35
  204. package/src/attach/index.ts +18 -0
  205. package/src/attach/protocol.js +95 -184
  206. package/src/attach/protocol.ts +181 -0
  207. package/src/attach/ring-buffer.js +76 -102
  208. package/src/attach/ring-buffer.ts +109 -0
  209. package/src/attach/send-input.js +64 -75
  210. package/src/attach/send-input.ts +94 -0
  211. package/src/attach/socket-discovery.js +164 -218
  212. package/src/attach/socket-discovery.ts +230 -0
  213. package/src/attach/socket-paths.js +42 -61
  214. package/src/attach/socket-paths.ts +81 -0
  215. package/src/claude-credentials.js +51 -54
  216. package/src/claude-credentials.ts +89 -0
  217. package/src/cluster/generated/protocol-schema.ts +1 -1
  218. package/src/cluster/generated/protocol.ts +2 -1
  219. package/src/command-proofs.js +110 -141
  220. package/src/command-proofs.ts +216 -0
  221. package/src/config-router.js +81 -73
  222. package/src/config-router.ts +131 -0
  223. package/src/copy-worker.js +53 -29
  224. package/src/copy-worker.ts +75 -0
  225. package/src/darwin-keychain-boundary.js +80 -111
  226. package/src/darwin-keychain-boundary.ts +148 -0
  227. package/src/guidance-topics.js +4 -5
  228. package/src/guidance-topics.ts +10 -0
  229. package/src/input-helpers.js +33 -54
  230. package/src/input-helpers.ts +58 -0
  231. package/src/ledger-sequence.js +45 -48
  232. package/src/ledger-sequence.ts +63 -0
  233. package/src/legacy-lib/clusters-registry.ts +40 -0
  234. package/src/legacy-lib/completion.ts +148 -0
  235. package/src/legacy-lib/compose-utils.ts +102 -0
  236. package/src/legacy-lib/detached-startup.ts +449 -0
  237. package/src/legacy-lib/docker-config.ts +282 -0
  238. package/src/legacy-lib/docker-env-auth.ts +116 -0
  239. package/src/legacy-lib/git-remote-utils.ts +244 -0
  240. package/src/legacy-lib/id-detector.ts +57 -0
  241. package/src/legacy-lib/js-yaml.d.ts +3 -0
  242. package/src/legacy-lib/omelette.d.ts +15 -0
  243. package/src/legacy-lib/path-check.ts +89 -0
  244. package/src/legacy-lib/process-liveness.ts +36 -0
  245. package/src/legacy-lib/provider-credential-path.ts +57 -0
  246. package/src/legacy-lib/provider-defaults.ts +114 -0
  247. package/src/legacy-lib/provider-detection.ts +67 -0
  248. package/src/legacy-lib/provider-names.ts +126 -0
  249. package/src/legacy-lib/repo-settings.ts +88 -0
  250. package/src/legacy-lib/run-mode.ts +58 -0
  251. package/src/legacy-lib/run-plan.ts +49 -0
  252. package/src/legacy-lib/settings/claude-auth.ts +80 -0
  253. package/src/legacy-lib/settings-defaults.ts +212 -0
  254. package/src/legacy-lib/settings-error.ts +8 -0
  255. package/src/legacy-lib/settings-issue-providers.ts +18 -0
  256. package/src/legacy-lib/settings-models.ts +124 -0
  257. package/src/legacy-lib/settings-storage.ts +277 -0
  258. package/src/legacy-lib/settings-validation.ts +220 -0
  259. package/src/legacy-lib/settings.ts +87 -0
  260. package/src/legacy-lib/setup-apply-types.ts +70 -0
  261. package/src/legacy-lib/setup-apply.ts +456 -0
  262. package/src/legacy-lib/setup-journal.ts +185 -0
  263. package/src/legacy-lib/setup-plan-types.ts +96 -0
  264. package/src/legacy-lib/setup-plan.ts +500 -0
  265. package/src/legacy-lib/setup-undo.ts +142 -0
  266. package/src/legacy-lib/start-cluster-config.ts +124 -0
  267. package/src/legacy-lib/start-cluster-environment.ts +165 -0
  268. package/src/legacy-lib/start-cluster-run-options.ts +279 -0
  269. package/src/legacy-lib/start-cluster.ts +237 -0
  270. package/src/legacy-lib/stream-json-parser.ts +88 -0
  271. package/src/message-buffer.js +55 -71
  272. package/src/message-buffer.ts +107 -0
  273. package/src/message-bus-bridge.js +92 -133
  274. package/src/message-bus-bridge.ts +149 -0
  275. package/src/name-generator-shared.js +220 -0
  276. package/src/name-generator-shared.ts +231 -0
  277. package/src/name-generator.js +8 -217
  278. package/src/name-generator.ts +27 -0
  279. package/src/omp-blob-root.js +83 -64
  280. package/src/omp-blob-root.ts +116 -0
  281. package/src/omp-config-overlay.js +65 -38
  282. package/src/omp-config-overlay.ts +110 -0
  283. package/src/omp-execution-fingerprint.js +38 -43
  284. package/src/omp-execution-fingerprint.ts +92 -0
  285. package/src/omp-session-limits.js +10 -15
  286. package/src/omp-session-limits.ts +53 -0
  287. package/src/omp-session-partition.js +2 -2
  288. package/src/omp-session-verifier.js +1 -1
  289. package/src/orchestrator.js +19 -4
  290. package/src/providers/anthropic/index.js +3 -1
  291. package/src/providers/anthropic/index.ts +13 -0
  292. package/src/providers/capabilities.js +19 -27
  293. package/src/providers/capabilities.ts +44 -0
  294. package/src/providers/google/index.js +3 -1
  295. package/src/providers/google/index.ts +13 -0
  296. package/src/providers/openai/index.js +3 -1
  297. package/src/providers/openai/index.ts +13 -0
  298. package/src/providers/opencode/index.js +3 -1
  299. package/src/providers/opencode/index.ts +13 -0
  300. package/src/quality-gates.js +67 -127
  301. package/src/quality-gates.ts +149 -0
  302. package/src/repo-settings-access.js +40 -0
  303. package/src/repo-settings-access.ts +64 -0
  304. package/src/schemas/sub-cluster.js +127 -183
  305. package/src/schemas/sub-cluster.ts +238 -0
  306. package/src/state-snapshot-normalization.js +224 -0
  307. package/src/state-snapshot-normalization.ts +222 -0
  308. package/src/state-snapshot.js +192 -359
  309. package/src/state-snapshot.ts +291 -0
  310. package/src/state-snapshotter.js +118 -130
  311. package/src/state-snapshotter.ts +167 -0
  312. package/src/sub-cluster-wrapper.js +4 -13
  313. package/src/task-run-model-args.js +87 -124
  314. package/src/task-run-model-args.ts +204 -0
  315. package/src/task-runner.js +5 -25
  316. package/src/task-runner.ts +28 -0
  317. package/src/task-startup-error.js +73 -58
  318. package/src/task-startup-error.ts +126 -0
  319. package/src/template-validation/consensus-gate-contracts.js +2 -0
  320. package/src/template-validation/consensus-gate-contracts.ts +70 -0
  321. package/src/template-validation/consensus-gate-scenarios.js +76 -0
  322. package/src/template-validation/consensus-gate-scenarios.ts +130 -0
  323. package/src/template-validation/consensus-gate-stage.js +34 -0
  324. package/src/template-validation/consensus-gate-stage.ts +56 -0
  325. package/src/template-validation/random-topology-contracts.js +2 -0
  326. package/src/template-validation/random-topology-contracts.ts +54 -0
  327. package/src/template-validation/random-topology-dispatch.js +25 -0
  328. package/src/template-validation/random-topology-dispatch.ts +33 -0
  329. package/src/template-validation/random-topology-message-loop.js +53 -0
  330. package/src/template-validation/random-topology-message-loop.ts +73 -0
  331. package/src/template-validation/random-topology-operations.js +79 -0
  332. package/src/template-validation/random-topology-operations.ts +101 -0
  333. package/src/template-validation/random-topology-runtime.js +25 -0
  334. package/src/template-validation/random-topology-runtime.ts +43 -0
  335. package/src/template-validation/random-topology-scenario.js +52 -0
  336. package/src/template-validation/random-topology-scenario.ts +57 -0
  337. package/src/template-validation/random-topology-schema.js +159 -0
  338. package/src/template-validation/random-topology-schema.ts +190 -0
  339. package/src/template-validation/random-topology-state.js +28 -0
  340. package/src/template-validation/random-topology-state.ts +30 -0
  341. package/src/template-validation/random-topology-trigger-evaluation.js +45 -0
  342. package/src/template-validation/random-topology-trigger-evaluation.ts +65 -0
  343. package/src/template-validation/random-topology-trigger.js +75 -0
  344. package/src/template-validation/random-topology-trigger.ts +88 -0
  345. package/src/template-validation/report-formatter.js +40 -46
  346. package/src/template-validation/report-formatter.ts +101 -0
  347. package/src/template-validation/simulate-consensus-gates.js +111 -302
  348. package/src/template-validation/simulate-consensus-gates.ts +196 -0
  349. package/src/template-validation/simulate-random-topology.js +26 -519
  350. package/src/template-validation/simulate-random-topology.ts +57 -0
  351. package/src/template-validation/simulate-two-stage-validation.js +41 -265
  352. package/src/template-validation/simulate-two-stage-validation.ts +55 -0
  353. package/src/template-validation/simulation-agent-runtime.js +25 -0
  354. package/src/template-validation/simulation-agent-runtime.ts +40 -0
  355. package/src/template-validation/simulation-agent.js +29 -0
  356. package/src/template-validation/simulation-agent.ts +73 -0
  357. package/src/template-validation/simulation-runtime.js +34 -0
  358. package/src/template-validation/simulation-runtime.ts +72 -0
  359. package/src/template-validation/two-stage-contracts.js +2 -0
  360. package/src/template-validation/two-stage-contracts.ts +41 -0
  361. package/src/template-validation/two-stage-inputs.js +21 -0
  362. package/src/template-validation/two-stage-inputs.ts +29 -0
  363. package/src/template-validation/two-stage-results.js +30 -0
  364. package/src/template-validation/two-stage-results.ts +40 -0
  365. package/src/template-validation/two-stage-scenario.js +86 -0
  366. package/src/template-validation/two-stage-scenario.ts +120 -0
  367. package/src/worktree-claude-config.js +182 -220
  368. package/src/worktree-claude-config.ts +272 -0
  369. package/src/worktree-tooling-env.js +103 -125
  370. package/src/worktree-tooling-env.ts +142 -0
  371. package/task-lib/completion.js +2 -3
  372. package/task-lib/completion.ts +9 -0
  373. package/task-lib/config.js +1 -4
  374. package/task-lib/config.ts +11 -0
  375. package/task-lib/name-generator.js +4 -226
  376. package/task-lib/name-generator.ts +11 -0
  377. package/task-lib/omp-session-cleanup.js +1 -1
  378. package/task-lib/omp-storage-root.js +8 -12
  379. package/task-lib/omp-storage-root.ts +62 -0
  380. package/task-lib/process-termination.js +143 -166
  381. package/task-lib/process-termination.ts +268 -0
@@ -0,0 +1,167 @@
1
+ import crypto = require('crypto');
2
+ import stateSnapshot = require('./state-snapshot');
3
+ import normalization = require('./state-snapshot-normalization');
4
+
5
+ interface SnapshotMessageBus {
6
+ subscribeTopics(topics: string[], handler: (message: unknown) => void): () => void;
7
+ findLast(query: { cluster_id: string; topic: string }): unknown;
8
+ publish(message: {
9
+ cluster_id: string;
10
+ topic: 'STATE_SNAPSHOT';
11
+ sender: 'state-snapshotter';
12
+ receiver: 'broadcast';
13
+ content: { text: string; data: object };
14
+ }): unknown;
15
+ }
16
+
17
+ interface StateSnapshotterOptions {
18
+ messageBus: SnapshotMessageBus;
19
+ clusterId: string;
20
+ }
21
+
22
+ type SnapshotState = ReturnType<typeof stateSnapshot.initStateFromIssue>;
23
+ const SNAPSHOT_TOPICS = [
24
+ 'ISSUE_OPENED',
25
+ 'PLAN_READY',
26
+ 'WORKER_PROGRESS',
27
+ 'IMPLEMENTATION_READY',
28
+ 'VALIDATION_RESULT',
29
+ 'INVESTIGATION_COMPLETE',
30
+ ];
31
+
32
+ function messageTimestamp(message: unknown): number {
33
+ const timestamp = normalization.asRecord(message)?.timestamp;
34
+ return timestamp ? Number(timestamp) : 0;
35
+ }
36
+
37
+ class StateSnapshotter {
38
+ messageBus: SnapshotMessageBus;
39
+ clusterId: string;
40
+ state: object | null;
41
+ lastHash: string | null;
42
+ unsubscribe: (() => void) | null;
43
+
44
+ constructor({ messageBus, clusterId }: StateSnapshotterOptions) {
45
+ this.messageBus = messageBus;
46
+ this.clusterId = clusterId;
47
+ this.state = null;
48
+ this.lastHash = null;
49
+ this.unsubscribe = null;
50
+ }
51
+
52
+ start(): void {
53
+ if (this.unsubscribe) {
54
+ return;
55
+ }
56
+
57
+ this._bootstrapFromLedger();
58
+
59
+ this.unsubscribe = this.messageBus.subscribeTopics(SNAPSHOT_TOPICS, (message: unknown) => {
60
+ if (normalization.asRecord(message)?.cluster_id !== this.clusterId) return;
61
+ this._handleMessage(message);
62
+ });
63
+ }
64
+
65
+ stop(): void {
66
+ if (!this.unsubscribe) return;
67
+ this.unsubscribe();
68
+ this.unsubscribe = null;
69
+ }
70
+
71
+ _bootstrapFromLedger(): void {
72
+ const existing = this.messageBus.findLast({
73
+ cluster_id: this.clusterId,
74
+ topic: 'STATE_SNAPSHOT',
75
+ });
76
+ const existingData = normalization.asRecord(normalization.asRecord(existing)?.content)?.data;
77
+
78
+ if (existingData && typeof existingData === 'object') {
79
+ this.state = existingData;
80
+ this.lastHash = this._hashState(this.state);
81
+ return;
82
+ }
83
+
84
+ const messages = SNAPSHOT_TOPICS.map((topic) =>
85
+ this.messageBus.findLast({ cluster_id: this.clusterId, topic })
86
+ ).filter(Boolean);
87
+
88
+ if (messages.length === 0) {
89
+ return;
90
+ }
91
+
92
+ messages.sort((left, right) => messageTimestamp(left) - messageTimestamp(right));
93
+
94
+ let state: object | null = null;
95
+ for (const message of messages) {
96
+ state = this._applyMessage(state, message);
97
+ }
98
+
99
+ if (state) {
100
+ this.state = state;
101
+ this._publishSnapshot(state);
102
+ }
103
+ }
104
+
105
+ _handleMessage(message: unknown): void {
106
+ const nextState = this._applyMessage(this.state, message);
107
+ if (!nextState) return;
108
+
109
+ this.state = nextState;
110
+ this._publishSnapshot(nextState);
111
+ }
112
+
113
+ _applyMessage(state: object | null, message: unknown): SnapshotState | object | null {
114
+ switch (normalization.asRecord(message)?.topic) {
115
+ case 'ISSUE_OPENED':
116
+ return state
117
+ ? stateSnapshot.applyIssueOpened(state, message)
118
+ : stateSnapshot.initStateFromIssue(message);
119
+ case 'PLAN_READY':
120
+ return stateSnapshot.applyPlanReady(state, message);
121
+ case 'WORKER_PROGRESS':
122
+ return stateSnapshot.applyWorkerProgress(state, message);
123
+ case 'IMPLEMENTATION_READY':
124
+ return stateSnapshot.applyImplementationReady(state, message);
125
+ case 'VALIDATION_RESULT':
126
+ return stateSnapshot.applyValidationResult(state, message);
127
+ case 'INVESTIGATION_COMPLETE':
128
+ return stateSnapshot.applyInvestigationComplete(state, message);
129
+ default:
130
+ return state;
131
+ }
132
+ }
133
+
134
+ _publishSnapshot(state: object): void {
135
+ const hash = this._hashState(state);
136
+ if (this._hashEquals(hash, this.lastHash)) {
137
+ return;
138
+ }
139
+ this.lastHash = hash;
140
+
141
+ this.messageBus.publish({
142
+ cluster_id: this.clusterId,
143
+ topic: 'STATE_SNAPSHOT',
144
+ sender: 'state-snapshotter',
145
+ receiver: 'broadcast',
146
+ content: {
147
+ text: stateSnapshot.renderStateSummary(state),
148
+ data: state,
149
+ },
150
+ });
151
+ }
152
+
153
+ _hashState(state: object): string {
154
+ const serialized = JSON.stringify(state);
155
+ return crypto.createHash('sha256').update(serialized).digest('hex');
156
+ }
157
+
158
+ _hashEquals(left: string | null, right: string | null): boolean {
159
+ if (!left || !right) return false;
160
+ const leftBuffer = Buffer.from(left, 'utf8');
161
+ const rightBuffer = Buffer.from(right, 'utf8');
162
+ if (leftBuffer.length !== rightBuffer.length) return false;
163
+ return crypto.timingSafeEqual(leftBuffer, rightBuffer);
164
+ }
165
+ }
166
+
167
+ export = StateSnapshotter;
@@ -15,6 +15,7 @@
15
15
  const LogicEngine = require('./logic-engine');
16
16
  const MessageBusBridge = require('./message-bus-bridge');
17
17
  const { DEFAULT_MAX_ITERATIONS } = require('./agent/agent-config');
18
+ const { findMatchingTrigger } = require('./agent/agent-trigger-evaluator');
18
19
  const { bufferMessage, scheduleDrain, drainBufferedMessages } = require('./message-buffer');
19
20
 
20
21
  function normalizeParentTopicConfig(entry) {
@@ -217,19 +218,9 @@ class SubClusterWrapper {
217
218
  * @private
218
219
  */
219
220
  _findMatchingTrigger(message) {
220
- if (!this.config.triggers) {
221
- return null;
222
- }
223
-
224
- return this.config.triggers.find((trigger) => {
225
- if (trigger.topic === '*' || trigger.topic === message.topic) {
226
- return true;
227
- }
228
- if (trigger.topic.endsWith('*')) {
229
- const prefix = trigger.topic.slice(0, -1);
230
- return message.topic.startsWith(prefix);
231
- }
232
- return false;
221
+ return findMatchingTrigger({
222
+ triggers: this.config.triggers,
223
+ message,
233
224
  });
234
225
  }
235
226
 
@@ -1,38 +1,34 @@
1
- const { providerSupportsCapability } = require('../lib/provider-names');
2
-
3
- /**
4
- * Append a resolved model selection to a nested `zeroshot task run` invocation.
5
- *
6
- * Direct requests use the public, catalog-strict `--model` channel.
7
- * Provider-level selections carry only their level. The child must resolve the
8
- * concrete model again from its effective provider settings.
9
- *
10
- * @param {string[]} args
11
- * @param {Object|null|undefined} modelSpec
12
- * @param {'direct'|'provider-level'} [modelSpecSource]
13
- * @returns {string[]}
14
- */
1
+ "use strict";
2
+ function isUnknownRecord(value) {
3
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
4
+ }
5
+ function isProviderNamesModule(value) {
6
+ return isUnknownRecord(value) && typeof value.providerSupportsCapability === 'function';
7
+ }
8
+ const providerNames = require('../lib/provider-names');
9
+ if (!isProviderNamesModule(providerNames)) {
10
+ throw new TypeError('provider-names must expose provider capability lookup');
11
+ }
12
+ const { providerSupportsCapability } = providerNames;
15
13
  function appendTaskRunModelArgs(args, modelSpec, modelSpecSource = 'direct') {
16
- if (modelSpecSource === 'provider-level') {
17
- if (!modelSpec?.level) {
18
- throw new Error('Provider-level task model selections require a model level');
14
+ if (modelSpecSource === 'provider-level') {
15
+ if (!modelSpec?.level) {
16
+ throw new Error('Provider-level task model selections require a model level');
17
+ }
18
+ args.push('--model-level', modelSpec.level);
19
19
  }
20
- args.push('--model-level', modelSpec.level);
21
- } else if (modelSpec?.model) {
22
- args.push('--model', modelSpec.model);
23
- }
24
-
25
- if (modelSpec?.reasoningEffort) {
26
- args.push('--reasoning-effort', modelSpec.reasoningEffort);
27
- }
28
-
29
- return args;
20
+ else if (modelSpec?.model) {
21
+ args.push('--model', modelSpec.model);
22
+ }
23
+ if (modelSpec?.reasoningEffort) {
24
+ args.push('--reasoning-effort', modelSpec.reasoningEffort);
25
+ }
26
+ return args;
30
27
  }
31
-
32
28
  const ISOLATED_SETTINGS_FILE_ENV = 'ZEROSHOT_SETTINGS_FILE';
33
29
  const ISOLATED_SETTINGS_FILE_MARKER = 'ZEROSHOT_DOCKER_SETTINGS_FILE';
34
30
  const LEGACY_ISOLATED_PROVIDER_SETTINGS_ENV = 'ZEROSHOT_ISOLATED_PROVIDER_SETTINGS_JSON';
35
- const SETTINGS_BOOTSTRAP_SCRIPT = String.raw`
31
+ const SETTINGS_BOOTSTRAP_SCRIPT = String.raw `
36
32
  const childProcess = require('node:child_process');
37
33
  const fs = require('node:fs');
38
34
  const os = require('node:os');
@@ -60,114 +56,81 @@ try {
60
56
  fs.rmSync(directory, { recursive: true, force: true });
61
57
  }
62
58
  `.trim();
63
-
64
- /**
65
- * Wrap an isolated task command with a Docker-only, temporary settings-file
66
- * bootstrap. The snapshot is a closed projection containing only an enabled
67
- * native-search control and, when needed, the selected OpenCode level/model.
68
- * It never contains credentials or caller-owned keys.
69
- *
70
- * @param {string[]} command
71
- * @param {{providerName: string, settings: Object, modelSpecSource: 'direct'|'provider-level', modelSpec: Object|null|undefined}} context
72
- * @returns {string[]}
73
- */
74
59
  function wrapTaskRunWithIsolatedSettings(command, context) {
75
- const { providerName, settings, modelSpecSource, modelSpec } = context;
76
- if (!providerSupportsCapability(providerName, 'webSearch')) return command;
77
- const includesOpencodeModel =
78
- providerName === 'opencode' && modelSpecSource === 'provider-level';
79
- const snapshot = buildIsolatedSettingsSnapshot(
80
- settings,
81
- providerName,
82
- includesOpencodeModel ? modelSpec : null
83
- );
84
- if (snapshot === null) return command;
85
- return ['node', '-e', SETTINGS_BOOTSTRAP_SCRIPT, snapshot, ...command];
60
+ const { providerName, settings, modelSpecSource, modelSpec } = context;
61
+ if (!providerSupportsCapability(providerName, 'webSearch'))
62
+ return command;
63
+ const includesOpencodeModel = providerName === 'opencode' && modelSpecSource === 'provider-level';
64
+ const snapshot = buildIsolatedSettingsSnapshot(settings, providerName, includesOpencodeModel ? modelSpec : null);
65
+ if (snapshot === null)
66
+ return command;
67
+ return ['node', '-e', SETTINGS_BOOTSTRAP_SCRIPT, snapshot, ...command];
86
68
  }
87
-
88
69
  function buildIsolatedSettingsSnapshot(settings, providerName, opencodeModelSpec) {
89
- const providerSettings = ownRecordValue(settings, 'providerSettings', 'settings') ?? {};
90
- const selectedSettings = ownRecordValue(
91
- providerSettings,
92
- providerName,
93
- 'settings.providerSettings'
94
- );
95
- const webSearch = selectedSettings?.webSearch;
96
- if (webSearch !== undefined && typeof webSearch !== 'boolean') {
97
- throw permanentError(`settings.providerSettings.${providerName}.webSearch must be a boolean.`);
98
- }
99
-
100
- const snapshot = {};
101
- if (webSearch === true) snapshot.webSearch = true;
102
- if (opencodeModelSpec !== null) {
103
- const level = opencodeModelSpec?.level;
104
- if (!['level1', 'level2', 'level3'].includes(level)) {
105
- throw permanentError(
106
- 'Provider-level isolated OpenCode selections require a valid model level.'
107
- );
70
+ const providerSettings = ownRecordValue(settings, 'providerSettings', 'settings') ?? {};
71
+ const selectedSettings = ownRecordValue(providerSettings, providerName, 'settings.providerSettings');
72
+ const webSearch = selectedSettings?.webSearch;
73
+ if (webSearch !== undefined && typeof webSearch !== 'boolean') {
74
+ throw permanentError(`settings.providerSettings.${providerName}.webSearch must be a boolean.`);
108
75
  }
109
-
110
- const levelOverrides = ownRecordValue(
111
- selectedSettings,
112
- 'levelOverrides',
113
- 'settings.providerSettings.opencode'
114
- );
115
- const levelOverride = ownRecordValue(
116
- levelOverrides,
117
- level,
118
- 'settings.providerSettings.opencode.levelOverrides'
119
- );
120
- const configuredModel =
121
- levelOverride && Object.prototype.hasOwnProperty.call(levelOverride, 'model')
76
+ const snapshot = {};
77
+ if (webSearch === true)
78
+ snapshot.webSearch = true;
79
+ if (opencodeModelSpec !== null) {
80
+ const levelOverrides = resolveIsolatedOpenCodeOverrides(selectedSettings, opencodeModelSpec);
81
+ if (levelOverrides !== undefined)
82
+ snapshot.levelOverrides = levelOverrides;
83
+ }
84
+ if (Object.keys(snapshot).length === 0)
85
+ return null;
86
+ return JSON.stringify({
87
+ providerSettings: {
88
+ [providerName]: snapshot,
89
+ },
90
+ });
91
+ }
92
+ function resolveIsolatedOpenCodeOverrides(selectedSettings, modelSpec) {
93
+ const level = modelSpec?.level;
94
+ if (level !== 'level1' && level !== 'level2' && level !== 'level3') {
95
+ throw permanentError('Provider-level isolated OpenCode selections require a valid model level.');
96
+ }
97
+ const levelOverrides = ownRecordValue(selectedSettings, 'levelOverrides', 'settings.providerSettings.opencode');
98
+ const levelOverride = ownRecordValue(levelOverrides, level, 'settings.providerSettings.opencode.levelOverrides');
99
+ const configuredModel = levelOverride && Object.prototype.hasOwnProperty.call(levelOverride, 'model')
122
100
  ? levelOverride.model
123
101
  : null;
124
102
  if (configuredModel !== null && typeof configuredModel !== 'string') {
125
- throw permanentError(`Configured isolated OpenCode ${level} model must be a string or null.`);
103
+ throw permanentError(`Configured isolated OpenCode ${level} model must be a string or null.`);
126
104
  }
127
- if (opencodeModelSpec.model !== configuredModel) {
128
- throw permanentError(
129
- `Provider-level model "${opencodeModelSpec.model}" does not match the effective isolated ${level} model "${configuredModel}".`
130
- );
105
+ if (modelSpec?.model !== configuredModel) {
106
+ throw permanentError(`Provider-level model "${modelSpec?.model}" does not match ` +
107
+ `the effective isolated ${level} model "${configuredModel}".`);
131
108
  }
132
- if (configuredModel !== null) {
133
- snapshot.levelOverrides = {
134
- [level]: { model: configuredModel },
135
- };
136
- }
137
- }
138
-
139
- if (Object.keys(snapshot).length === 0) return null;
140
- return JSON.stringify({
141
- providerSettings: {
142
- [providerName]: snapshot,
143
- },
144
- });
109
+ return configuredModel === null ? undefined : { [level]: { model: configuredModel } };
145
110
  }
146
-
147
111
  function ownRecordValue(record, key, field) {
148
- if (record === null || record === undefined) return undefined;
149
- if (typeof record !== 'object' || Array.isArray(record)) {
150
- throw permanentError(`${field} must be an object.`);
151
- }
152
- if (!Object.prototype.hasOwnProperty.call(record, key)) return undefined;
153
- const value = record[key];
154
- if (value === null || value === undefined) return undefined;
155
- if (typeof value !== 'object' || Array.isArray(value)) {
156
- throw permanentError(`${field}.${key} must be an object.`);
157
- }
158
- return value;
112
+ if (record === null || record === undefined)
113
+ return undefined;
114
+ if (!isUnknownRecord(record)) {
115
+ throw permanentError(`${field} must be an object.`);
116
+ }
117
+ if (!Object.prototype.hasOwnProperty.call(record, key))
118
+ return undefined;
119
+ const value = record[key];
120
+ if (value === null || value === undefined)
121
+ return undefined;
122
+ if (!isUnknownRecord(value)) {
123
+ throw permanentError(`${field}.${key} must be an object.`);
124
+ }
125
+ return value;
159
126
  }
160
-
161
127
  function permanentError(message) {
162
- const error = new Error(message);
163
- error.permanent = true;
164
- return error;
128
+ return Object.assign(new Error(message), { permanent: true });
165
129
  }
166
-
167
130
  module.exports = {
168
- ISOLATED_SETTINGS_FILE_ENV,
169
- ISOLATED_SETTINGS_FILE_MARKER,
170
- LEGACY_ISOLATED_PROVIDER_SETTINGS_ENV,
171
- appendTaskRunModelArgs,
172
- wrapTaskRunWithIsolatedSettings,
131
+ ISOLATED_SETTINGS_FILE_ENV,
132
+ ISOLATED_SETTINGS_FILE_MARKER,
133
+ LEGACY_ISOLATED_PROVIDER_SETTINGS_ENV,
134
+ appendTaskRunModelArgs,
135
+ wrapTaskRunWithIsolatedSettings,
173
136
  };
@@ -0,0 +1,204 @@
1
+ type ModelSpecSource = 'direct' | 'provider-level';
2
+ type ModelLevel = 'level1' | 'level2' | 'level3';
3
+ type UnknownRecord = Record<string, unknown>;
4
+
5
+ interface ProviderNamesModule {
6
+ providerSupportsCapability(providerName: string, capability: string): boolean;
7
+ }
8
+
9
+ interface ModelSpec {
10
+ level?: ModelLevel;
11
+ model?: string | null;
12
+ reasoningEffort?: string;
13
+ }
14
+
15
+ interface IsolatedSettingsContext {
16
+ providerName: string;
17
+ settings: unknown;
18
+ modelSpecSource: ModelSpecSource;
19
+ modelSpec: ModelSpec | null | undefined;
20
+ }
21
+
22
+ interface IsolatedProviderSnapshot {
23
+ webSearch?: true;
24
+ levelOverrides?: Partial<Record<ModelLevel, { model: string }>>;
25
+ }
26
+
27
+ function isUnknownRecord(value: unknown): value is UnknownRecord {
28
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
29
+ }
30
+
31
+ function isProviderNamesModule(value: unknown): value is ProviderNamesModule {
32
+ return isUnknownRecord(value) && typeof value.providerSupportsCapability === 'function';
33
+ }
34
+
35
+ const providerNames: unknown = require('../lib/provider-names');
36
+ if (!isProviderNamesModule(providerNames)) {
37
+ throw new TypeError('provider-names must expose provider capability lookup');
38
+ }
39
+ const { providerSupportsCapability } = providerNames;
40
+
41
+ function appendTaskRunModelArgs(
42
+ args: string[],
43
+ modelSpec: ModelSpec | null | undefined,
44
+ modelSpecSource: ModelSpecSource = 'direct'
45
+ ): string[] {
46
+ if (modelSpecSource === 'provider-level') {
47
+ if (!modelSpec?.level) {
48
+ throw new Error('Provider-level task model selections require a model level');
49
+ }
50
+ args.push('--model-level', modelSpec.level);
51
+ } else if (modelSpec?.model) {
52
+ args.push('--model', modelSpec.model);
53
+ }
54
+
55
+ if (modelSpec?.reasoningEffort) {
56
+ args.push('--reasoning-effort', modelSpec.reasoningEffort);
57
+ }
58
+
59
+ return args;
60
+ }
61
+
62
+ const ISOLATED_SETTINGS_FILE_ENV = 'ZEROSHOT_SETTINGS_FILE';
63
+ const ISOLATED_SETTINGS_FILE_MARKER = 'ZEROSHOT_DOCKER_SETTINGS_FILE';
64
+ const LEGACY_ISOLATED_PROVIDER_SETTINGS_ENV = 'ZEROSHOT_ISOLATED_PROVIDER_SETTINGS_JSON';
65
+ const SETTINGS_BOOTSTRAP_SCRIPT = String.raw`
66
+ const childProcess = require('node:child_process');
67
+ const fs = require('node:fs');
68
+ const os = require('node:os');
69
+ const path = require('node:path');
70
+
71
+ const snapshot = process.argv[1];
72
+ const command = process.argv[2];
73
+ const args = process.argv.slice(3);
74
+ const directory = fs.mkdtempSync(path.join(os.tmpdir(), 'zeroshot-isolated-settings-'));
75
+ const settingsFile = path.join(directory, 'settings.json');
76
+
77
+ try {
78
+ fs.writeFileSync(settingsFile, snapshot, { encoding: 'utf8', flag: 'wx', mode: 0o600 });
79
+ const result = childProcess.spawnSync(command, args, {
80
+ stdio: 'inherit',
81
+ env: {
82
+ ...process.env,
83
+ ${ISOLATED_SETTINGS_FILE_ENV}: settingsFile,
84
+ ${ISOLATED_SETTINGS_FILE_MARKER}: '1',
85
+ },
86
+ });
87
+ if (result.error) throw result.error;
88
+ process.exitCode = result.status === null ? 1 : result.status;
89
+ } finally {
90
+ fs.rmSync(directory, { recursive: true, force: true });
91
+ }
92
+ `.trim();
93
+
94
+ function wrapTaskRunWithIsolatedSettings(
95
+ command: string[],
96
+ context: IsolatedSettingsContext
97
+ ): string[] {
98
+ const { providerName, settings, modelSpecSource, modelSpec } = context;
99
+ if (!providerSupportsCapability(providerName, 'webSearch')) return command;
100
+ const includesOpencodeModel =
101
+ providerName === 'opencode' && modelSpecSource === 'provider-level';
102
+ const snapshot = buildIsolatedSettingsSnapshot(
103
+ settings,
104
+ providerName,
105
+ includesOpencodeModel ? modelSpec : null
106
+ );
107
+ if (snapshot === null) return command;
108
+ return ['node', '-e', SETTINGS_BOOTSTRAP_SCRIPT, snapshot, ...command];
109
+ }
110
+
111
+ function buildIsolatedSettingsSnapshot(
112
+ settings: unknown,
113
+ providerName: string,
114
+ opencodeModelSpec: ModelSpec | null | undefined
115
+ ): string | null {
116
+ const providerSettings = ownRecordValue(settings, 'providerSettings', 'settings') ?? {};
117
+ const selectedSettings = ownRecordValue(
118
+ providerSettings,
119
+ providerName,
120
+ 'settings.providerSettings'
121
+ );
122
+ const webSearch = selectedSettings?.webSearch;
123
+ if (webSearch !== undefined && typeof webSearch !== 'boolean') {
124
+ throw permanentError(`settings.providerSettings.${providerName}.webSearch must be a boolean.`);
125
+ }
126
+
127
+ const snapshot: IsolatedProviderSnapshot = {};
128
+ if (webSearch === true) snapshot.webSearch = true;
129
+ if (opencodeModelSpec !== null) {
130
+ const levelOverrides = resolveIsolatedOpenCodeOverrides(selectedSettings, opencodeModelSpec);
131
+ if (levelOverrides !== undefined) snapshot.levelOverrides = levelOverrides;
132
+ }
133
+
134
+ if (Object.keys(snapshot).length === 0) return null;
135
+ return JSON.stringify({
136
+ providerSettings: {
137
+ [providerName]: snapshot,
138
+ },
139
+ });
140
+ }
141
+
142
+
143
+ function resolveIsolatedOpenCodeOverrides(
144
+ selectedSettings: UnknownRecord | undefined,
145
+ modelSpec: ModelSpec | undefined
146
+ ): IsolatedProviderSnapshot['levelOverrides'] {
147
+ const level = modelSpec?.level;
148
+ if (level !== 'level1' && level !== 'level2' && level !== 'level3') {
149
+ throw permanentError(
150
+ 'Provider-level isolated OpenCode selections require a valid model level.'
151
+ );
152
+ }
153
+
154
+ const levelOverrides = ownRecordValue(
155
+ selectedSettings,
156
+ 'levelOverrides',
157
+ 'settings.providerSettings.opencode'
158
+ );
159
+ const levelOverride = ownRecordValue(
160
+ levelOverrides,
161
+ level,
162
+ 'settings.providerSettings.opencode.levelOverrides'
163
+ );
164
+ const configuredModel =
165
+ levelOverride && Object.prototype.hasOwnProperty.call(levelOverride, 'model')
166
+ ? levelOverride.model
167
+ : null;
168
+ if (configuredModel !== null && typeof configuredModel !== 'string') {
169
+ throw permanentError(`Configured isolated OpenCode ${level} model must be a string or null.`);
170
+ }
171
+ if (modelSpec?.model !== configuredModel) {
172
+ throw permanentError(
173
+ `Provider-level model "${modelSpec?.model}" does not match ` +
174
+ `the effective isolated ${level} model "${configuredModel}".`
175
+ );
176
+ }
177
+ return configuredModel === null ? undefined : { [level]: { model: configuredModel } };
178
+ }
179
+
180
+ function ownRecordValue(record: unknown, key: string, field: string): UnknownRecord | undefined {
181
+ if (record === null || record === undefined) return undefined;
182
+ if (!isUnknownRecord(record)) {
183
+ throw permanentError(`${field} must be an object.`);
184
+ }
185
+ if (!Object.prototype.hasOwnProperty.call(record, key)) return undefined;
186
+ const value = record[key];
187
+ if (value === null || value === undefined) return undefined;
188
+ if (!isUnknownRecord(value)) {
189
+ throw permanentError(`${field}.${key} must be an object.`);
190
+ }
191
+ return value;
192
+ }
193
+
194
+ function permanentError(message: string): Error & { permanent: true } {
195
+ return Object.assign(new Error(message), { permanent: true as const });
196
+ }
197
+
198
+ export = {
199
+ ISOLATED_SETTINGS_FILE_ENV,
200
+ ISOLATED_SETTINGS_FILE_MARKER,
201
+ LEGACY_ISOLATED_PROVIDER_SETTINGS_ENV,
202
+ appendTaskRunModelArgs,
203
+ wrapTaskRunWithIsolatedSettings,
204
+ };
@@ -1,30 +1,10 @@
1
+ "use strict";
1
2
  /**
2
- * TaskRunner - Strategy Pattern interface for executing provider tasks
3
- *
4
- * Implementations must provide a `run()` method that executes a task
5
- * with the given context and options. Different runners can implement various
6
- * execution strategies (CLI, mock responses, etc).
3
+ * TaskRunner - Strategy Pattern interface for executing provider tasks.
7
4
  */
8
5
  class TaskRunner {
9
- /**
10
- * Execute a provider task with the given context and options
11
- *
12
- * @param {string} _context - Full prompt/context for the provider to process
13
- * @param {Object} _options - Execution options
14
- * @param {string} _options.agentId - Identifier for this agent/task
15
- * @param {string} _options.model - Model to use (provider-specific model id)
16
- * @param {string} [_options.provider] - Provider to use (claude|codex|gemini)
17
- * @param {object} [_options.modelSpec] - Resolved model spec (level/model/reasoningEffort)
18
- * @param {string} [_options.outputFormat] - Output format ('text', 'json', 'stream-json')
19
- * @param {Object} [_options.jsonSchema] - JSON schema for structured output validation
20
- * @param {string} [_options.cwd] - Working directory for task execution
21
- * @param {boolean} [_options.isolation] - Whether to run in isolated container
22
- *
23
- * @returns {Promise<{success: boolean, output: string, error: string|null, taskId?: string}>} Result object with success status, output, error message, and optional taskId
24
- */
25
- run(_context, _options) {
26
- throw new Error('TaskRunner.run() not implemented');
27
- }
6
+ run(_context, _options) {
7
+ throw new Error('TaskRunner.run() not implemented');
8
+ }
28
9
  }
29
-
30
10
  module.exports = TaskRunner;