@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
@@ -1,619 +1,19 @@
1
- /**
2
- * Output Extraction Module - Multi-Provider JSON Extraction
3
- *
4
- * Clean extraction pipeline for structured JSON from AI provider outputs.
5
- * Each provider has different output formats - this module normalizes them.
6
- *
7
- * Provider formats:
8
- * - Claude: {"type":"result","result":{...}} or {"type":"result","structured_output":{...}}
9
- * - Codex: Raw text in item.created events, turn.completed has NO result field
10
- * - Gemini: Raw text in message events, result event may have NO result field
11
- *
12
- * Extraction priority (most specific → least specific):
13
- * 1. Result wrapper with content (type:result + result/structured_output field)
14
- * 2. Accumulated text from provider parser events
15
- * 3. Markdown code block extraction
16
- * 4. Direct JSON parse of entire output
17
- */
18
-
19
- const { createHash } = require('node:crypto');
20
- const { parseProviderChunk } = require('../providers');
21
-
22
- const MAX_CLI_ERROR_BYTES = 4096;
23
- const CLI_ERROR_TRUNCATION_SUFFIX = '… [truncated]';
24
-
25
- function truncateUtf8(text, maxBytes = MAX_CLI_ERROR_BYTES) {
26
- if (Buffer.byteLength(text) <= maxBytes) return text;
27
-
28
- const suffixBytes = Buffer.byteLength(CLI_ERROR_TRUNCATION_SUFFIX);
29
- const contentBudget = Math.max(0, maxBytes - suffixBytes);
30
- let bytes = 0;
31
- let truncated = '';
32
- for (const character of text) {
33
- const characterBytes = Buffer.byteLength(character);
34
- if (bytes + characterBytes > contentBudget) break;
35
- truncated += character;
36
- bytes += characterBytes;
37
- }
38
- return `${truncated}${CLI_ERROR_TRUNCATION_SUFFIX}`;
39
- }
40
-
41
- function primitiveErrorText(value) {
42
- return typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean'
43
- ? String(value)
44
- : '';
45
- }
46
-
47
- function cliErrorDetail(value, fallback) {
48
- const candidate = Array.isArray(value)
49
- ? value
50
- .map(primitiveErrorText)
51
- .filter((message) => message.trim())
52
- .join('; ')
53
- : primitiveErrorText(value);
54
- const raw = candidate.trim() ? candidate : fallback;
55
- return {
56
- error: truncateUtf8(raw.trim()),
57
- diagnostic: {
58
- byteLength: Buffer.byteLength(raw),
59
- sha256: createHash('sha256').update(raw).digest('hex'),
60
- },
61
- };
62
- }
63
-
64
- /**
65
- * Strip timestamp prefix from log lines.
66
- * Format: [epochMs]content or [epochMs]{json...}
67
- *
68
- * @param {string} line - Raw log line
69
- * @returns {string} Content without timestamp prefix
70
- */
71
- function stripTimestamp(line) {
72
- if (!line || typeof line !== 'string') return '';
73
- let trimmed = line.trim().replace(/\r$/, '');
74
- if (!trimmed) return '';
75
-
76
- const tsMatch = trimmed.match(/^\[(\d{13})\](.*)$/);
77
- if (tsMatch) trimmed = (tsMatch[2] || '').trimStart();
78
-
79
- // In cluster logs, lines are often prefixed like:
80
- // "validator | {json...}"
81
- // Strip the "<agent> | " prefix so we can JSON.parse the event line.
82
- if (!trimmed.startsWith('{') && !trimmed.startsWith('[')) {
83
- const pipeMatch = trimmed.match(/^[^|]{1,40}\|\s*(.*)$/);
84
- if (pipeMatch) {
85
- const afterPipe = (pipeMatch[1] || '').trimStart();
86
- if (afterPipe.startsWith('{') || afterPipe.startsWith('[')) return afterPipe;
87
- }
88
- }
89
-
90
- return trimmed;
91
- }
92
-
93
- /**
94
- * Strategy 1: Extract from result wrapper
95
- * Handles Claude CLI format: {"type":"result","result":{...}}
96
- *
97
- * @param {string} output - Raw output
98
- * @returns {object|null} Extracted JSON or null
99
- */
100
- function extractFromResultWrapper(output) {
101
- const lines = output.split('\n');
102
-
103
- for (const line of lines) {
104
- const content = stripTimestamp(line);
105
- if (!content.startsWith('{')) continue;
106
-
107
- try {
108
- const obj = JSON.parse(content);
109
- const extracted = extractResultContent(obj);
110
- if (extracted) return extracted;
111
- } catch {
112
- // Not valid JSON, continue to next line
113
- }
114
- }
115
-
116
- return null;
117
- }
118
-
119
- function extractResultContent(obj) {
120
- // Must be type:result WITH actual content
121
- if (obj?.type !== 'result') return null;
122
-
123
- // Check structured_output first (standard CLI format)
124
- if (obj.structured_output && typeof obj.structured_output === 'object') {
125
- return obj.structured_output;
126
- }
127
-
128
- // Check result field - can be object or string
129
- if (!obj.result) return null;
130
-
131
- if (typeof obj.result === 'object') {
132
- return obj.result;
133
- }
134
-
135
- if (typeof obj.result !== 'string') return null;
136
-
137
- // Result is string - might contain markdown-wrapped JSON
138
- return extractFromMarkdown(obj.result) || extractDirectJson(obj.result);
139
- }
140
-
141
- /**
142
- * Strategy 2: Extract from accumulated text events
143
- * Handles non-Claude providers where JSON is in text content
144
- *
145
- * @param {string} output - Raw output
146
- * @param {string} providerName - Provider name for parser selection
147
- * @returns {object|null} Extracted JSON or null
148
- */
149
- function extractFromTextEvents(output, providerName) {
150
- const normalized = output
151
- .split('\n')
152
- .map((line) => stripTimestamp(line))
153
- .filter(Boolean)
154
- .join('\n');
155
- const events = parseProviderChunk(providerName, normalized);
156
-
157
- // Fast-path: many providers eventually emit the full JSON as a single text event.
158
- // Scan from the end to find the last parseable JSON snippet without requiring
159
- // the entire concatenated stream to be valid JSON.
160
- for (let i = events.length - 1; i >= 0; i--) {
161
- const e = events[i];
162
- if (e.type !== 'text' || typeof e.text !== 'string') continue;
163
- const direct = extractDirectJson(e.text) || extractFromMarkdown(e.text);
164
- if (direct) return direct;
165
- }
166
-
167
- // Accumulate all text events
168
- const textEvents = events.filter((e) => e.type === 'text').map((e) => e.text);
169
- const textContent = textEvents.join('');
170
-
171
- if (!textContent.trim()) return null;
172
-
173
- // Try parsing accumulated text as JSON
174
- const combined = extractDirectJson(textContent) || extractFromMarkdown(textContent);
175
- if (combined) return combined;
176
-
177
- for (let i = textEvents.length - 1; i >= 0; i--) {
178
- const candidate = textEvents[i];
179
- const parsed = extractDirectJson(candidate) || extractFromMarkdown(candidate);
180
- if (parsed) return parsed;
181
- }
182
-
183
- return null;
184
- }
185
-
186
- /**
187
- * Assemble assistant text through the active provider parser. Recovery prompts
188
- * use this instead of exposing raw event envelopes when model text exists.
189
- *
190
- * @param {string} output
191
- * @param {string} providerName
192
- * @returns {string|null}
193
- */
194
- function extractModelTextFromOutput(output, providerName) {
195
- if (!output || typeof output !== 'string') return null;
196
- const normalized = output
197
- .split('\n')
198
- .map((line) => stripTimestamp(line))
199
- .filter(Boolean)
200
- .join('\n');
201
- const text = parseProviderChunk(providerName, normalized)
202
- .filter((event) => event.type === 'text' && typeof event.text === 'string')
203
- .map((event) => event.text)
204
- .join('');
205
- return text.trim() ? text : null;
206
- }
207
-
208
- /**
209
- * Strategy 3: Extract JSON from markdown code block
210
- * Handles: ```json\n{...}\n```
211
- *
212
- * @param {string} text - Text that may contain markdown
213
- * @returns {object|null} Extracted JSON or null
214
- */
215
- function extractFromMarkdown(text) {
216
- if (!text) return null;
217
-
218
- // Match ```json ... ``` with any whitespace
219
- const match = text.match(/```json\s*([\s\S]*?)```/);
220
- if (!match) return null;
221
-
222
- try {
223
- const parsed = JSON.parse(match[1].trim());
224
- if (typeof parsed === 'object' && parsed !== null) {
225
- return parsed;
226
- }
227
- } catch {
228
- // Invalid JSON in markdown block
229
- }
230
-
231
- return null;
232
- }
233
-
234
- /**
235
- * CLI metadata fields that indicate raw provider output (not agent content).
236
- * These objects should be rejected - they're wrapper metadata, not actual output.
237
- */
238
- const CLI_METADATA_FIELDS = new Set([
239
- 'duration_ms',
240
- 'duration_api_ms',
241
- 'total_cost_usd',
242
- 'session_id',
243
- 'num_turns',
244
- 'permission_denials',
245
- 'modelUsage',
246
- ]);
247
-
248
- /**
249
- * Check if an object looks like CLI metadata rather than agent output.
250
- * CLI metadata has specific fields like duration_ms, session_id, etc.
251
- *
252
- * @param {object} obj - Parsed JSON object
253
- * @returns {boolean} True if this looks like CLI metadata
254
- */
255
- function isCliMetadata(obj) {
256
- if (!obj || typeof obj !== 'object') return false;
257
-
258
- // If it has type:result, it's definitely CLI wrapper (should have been handled by extractFromResultWrapper)
259
- if (obj.type === 'result') return true;
260
-
261
- // Check for CLI-specific metadata fields
262
- const keys = Object.keys(obj);
263
- const metadataFieldCount = keys.filter((k) => CLI_METADATA_FIELDS.has(k)).length;
264
-
265
- // If 2+ CLI metadata fields present, reject as CLI output
266
- return metadataFieldCount >= 2;
267
- }
268
-
269
- /**
270
- * Strategy 4: Direct JSON parse
271
- * Handles raw JSON output (single-line or multi-line)
272
- *
273
- * IMPORTANT: Rejects CLI metadata objects to prevent schema validation
274
- * against wrong data structure (e.g., validating {duration_ms, session_id}
275
- * against agent schema expecting {summary, completionStatus}).
276
- *
277
- * @param {string} text - Text to parse
278
- * @returns {object|null} Parsed JSON or null
279
- */
280
- function extractDirectJson(text) {
281
- if (!text) return null;
282
-
283
- const trimmed = text.trim();
284
- if (!trimmed) return null;
285
-
286
- try {
287
- const parsed = JSON.parse(trimmed);
288
- if (typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed)) {
289
- // Reject CLI metadata - this is wrapper output, not agent content
290
- if (isCliMetadata(parsed)) {
291
- return null;
292
- }
293
- return parsed;
294
- }
295
- } catch {
296
- // Not valid JSON
297
- }
298
-
299
- return null;
300
- }
301
-
302
- /**
303
- * Extract deterministic Claude Vertex model-unavailability metadata from the raw CLI envelope.
304
- *
305
- * @param {string} output - Raw Claude CLI output
306
- * @param {{useVertex?: boolean}} [options] - Whether the Claude task was configured for Vertex
307
- * @returns {{model: string}|null} Vertex model metadata or null
308
- */
309
- function extractClaudeVertexModelError(output, { useVertex = false } = {}) {
310
- if (!output || typeof output !== 'string') return null;
311
-
312
- for (const line of output.split('\n')) {
313
- const content = stripTimestamp(line);
314
- if (!content.startsWith('{')) continue;
315
-
316
- try {
317
- const parsed = JSON.parse(content);
318
- if (
319
- parsed.type !== 'result' ||
320
- parsed.is_error !== true ||
321
- parsed.api_error_status !== 404 ||
322
- typeof parsed.result !== 'string'
323
- ) {
324
- continue;
325
- }
326
- const modelMatch = parsed.result.match(/model\s+\(([^)]+)\)/);
327
- const hasExplicitVertexSignal = parsed.result.includes('vertex deployment');
328
- const isVertexFallback =
329
- useVertex && parsed.result.includes('may not exist or you may not have access');
330
- if (!modelMatch || (!hasExplicitVertexSignal && !isVertexFallback)) continue;
331
-
332
- return { model: modelMatch[1] };
333
- } catch {
334
- // Not a JSON result envelope.
335
- }
336
- }
337
-
338
- return null;
339
- }
340
-
341
- /**
342
- * Extract CLI error from provider output (all providers).
343
- * Returns the error message if the CLI reported an error, null otherwise.
344
- *
345
- * Provider error formats:
346
- * - Claude: {type:"result", is_error:true, errors:["msg"]} or {type:"result", subtype:"error"}
347
- * - Codex: {type:"turn.failed", error:{message:"msg"}}
348
- * - Gemini: {type:"result", status:"error", error:{message:"msg"}} or {type:"error", severity:"error"}
349
- * - Opencode: {type:"session.error", error:{message:"msg"}}
350
- * - Pi: latest assistant message_end, finalized only by a later agent_settled
351
- *
352
- * @param {string} providerName - Active provider whose terminal errors may be inspected
353
- * @returns {{error: string, provider: string}|null} Error info or null
354
- */
355
- function claudeFailureFromObject(obj) {
356
- if (obj.type !== 'result') return null;
357
- if (obj.is_error === true) {
358
- const detail = cliErrorDetail(
359
- Array.isArray(obj.errors) ? obj.errors : obj.error || obj.result,
360
- 'Unknown CLI error'
361
- );
362
- return { ...detail, provider: 'claude' };
363
- }
364
- if (obj.subtype !== 'error') return null;
365
- return {
366
- ...cliErrorDetail(obj.error || obj.result, 'CLI returned error'),
367
- provider: 'claude',
368
- };
369
- }
370
-
371
- function codexFailureFromObject(obj) {
372
- if (obj.type !== 'turn.failed') return null;
373
- return {
374
- ...cliErrorDetail(obj.error?.message || obj.error?.code || obj.error, 'Turn failed'),
375
- provider: 'codex',
376
- };
377
- }
378
-
379
- function geminiFailureFromObject(obj) {
380
- const geminiFailure =
381
- (obj.type === 'result' && obj.status === 'error') ||
382
- (obj.type === 'error' && obj.severity === 'error');
383
- if (!geminiFailure) return null;
384
- return {
385
- ...cliErrorDetail(obj.error?.message || obj.message, 'Gemini CLI error'),
386
- provider: 'gemini',
387
- };
388
- }
389
-
390
- function opencodeFailureFromObject(obj) {
391
- if (obj.type !== 'session.error' && obj.type !== 'error') return null;
392
- return {
393
- ...cliErrorDetail(
394
- obj.error?.data?.message || obj.error?.message || obj.error?.name,
395
- 'Session error'
396
- ),
397
- provider: 'opencode',
398
- };
399
- }
400
-
401
- function piFailureFromMessage(message) {
402
- const stopReason = message.stopReason;
403
- const errorMessage = message.errorMessage;
404
- if (stopReason === 'deferred') {
405
- return {
406
- ...cliErrorDetail('Pi turn deferred without completing.', 'Pi turn deferred'),
407
- provider: 'pi',
408
- };
409
- }
410
- if (stopReason !== 'error' && stopReason !== 'aborted' && !errorMessage) return null;
411
- return {
412
- ...cliErrorDetail(errorMessage || stopReason, 'Pi turn failed'),
413
- provider: 'pi',
414
- };
415
- }
416
-
417
- function failureFromProviderObject(obj, providerName) {
418
- if (providerName === 'claude') return claudeFailureFromObject(obj);
419
- if (providerName === 'codex') return codexFailureFromObject(obj);
420
- if (providerName === 'gemini') return geminiFailureFromObject(obj);
421
- if (providerName === 'opencode') return opencodeFailureFromObject(obj);
422
- return null;
423
- }
424
-
425
- function piProtocolFailure(message) {
426
- return { ...cliErrorDetail(message, message), provider: 'pi' };
427
- }
428
-
429
- const PI_STOP_REASONS = new Set(['stop', 'length', 'toolUse', 'error', 'aborted', 'deferred']);
430
- const PI_USAGE_FIELDS = ['input', 'output', 'cacheRead', 'cacheWrite', 'totalTokens'];
431
- const PI_COST_FIELDS = ['input', 'output', 'cacheRead', 'cacheWrite', 'total'];
432
-
433
- function parsePiProtocolObject(content) {
434
- if (!content.startsWith('{')) return null;
435
- try {
436
- const parsed = JSON.parse(content);
437
- return parsed && typeof parsed === 'object' && !Array.isArray(parsed) ? parsed : null;
438
- } catch {
439
- return null;
440
- }
441
- }
442
-
443
- function isPiRecord(value) {
444
- return value !== null && typeof value === 'object' && !Array.isArray(value);
445
- }
446
-
447
- function hasPiNumericFields(value, fields) {
448
- return isPiRecord(value) && fields.every((field) => typeof value[field] === 'number');
449
- }
450
-
451
- function isValidPiUsage(usage) {
452
- if (!hasPiNumericFields(usage, PI_USAGE_FIELDS)) return false;
453
- if (!hasPiNumericFields(usage.cost, PI_COST_FIELDS)) return false;
454
- return (
455
- (usage.cacheWrite1h === undefined || typeof usage.cacheWrite1h === 'number') &&
456
- (usage.reasoning === undefined || typeof usage.reasoning === 'number')
457
- );
458
- }
459
-
460
- function isValidPiAssistantMessage(message) {
461
- return (
462
- isPiRecord(message) &&
463
- message.role === 'assistant' &&
464
- Array.isArray(message.content) &&
465
- isValidPiUsage(message.usage) &&
466
- PI_STOP_REASONS.has(message.stopReason)
467
- );
468
- }
469
-
470
- function piMessageRole(message) {
471
- if (!message || typeof message !== 'object' || Array.isArray(message)) return null;
472
- return typeof message.role === 'string' ? message.role : null;
473
- }
474
-
475
- function applyPiProtocolLine(content, state) {
476
- if (!content) return null;
477
- if (
478
- content.startsWith('[ZEROSHOT] Earlier provider output omitted') ||
479
- content.startsWith('[ZEROSHOT] Provider output record retained') ||
480
- content.startsWith('[ZEROSHOT][PROVIDER_STDERR] ')
481
- ) {
482
- return null;
483
- }
484
- if (state.settled) return piProtocolFailure('Pi emitted output after agent_settled.');
485
- const parsed = parsePiProtocolObject(content);
486
- if (parsed === null) return piProtocolFailure('Pi JSON stream contained malformed output.');
487
- if (typeof parsed.type !== 'string') {
488
- return piProtocolFailure('Pi JSON stream contained an event without a valid type.');
489
- }
490
- if (parsed.type === 'message_end') {
491
- const role = piMessageRole(parsed.message);
492
- if (role === null) return piProtocolFailure('Pi message_end did not contain a valid message.');
493
- if (role !== 'assistant') return null;
494
- if (!isValidPiAssistantMessage(parsed.message)) {
495
- return piProtocolFailure('Pi message_end did not contain a valid assistant message.');
496
- }
497
- state.latestAssistant = parsed.message;
498
- } else if (parsed.type === 'agent_settled') {
499
- state.settled = true;
500
- }
501
- return null;
502
- }
503
-
504
- function extractSettledPiFailure(lines) {
505
- const state = { latestAssistant: null, settled: false };
506
- for (const line of lines) {
507
- const content = stripTimestamp(line);
508
- const failure = applyPiProtocolLine(content, state);
509
- if (failure) return failure;
510
- }
511
-
512
- if (!state.settled) return piProtocolFailure('Pi JSON stream ended before agent_settled.');
513
- if (state.latestAssistant === null) {
514
- return piProtocolFailure('Pi settled without a valid assistant message_end.');
515
- }
516
- return piFailureFromMessage(state.latestAssistant);
517
- }
518
-
519
- function extractCliFailure(output, providerName = 'claude') {
520
- if (providerName === 'pi') {
521
- const lines = typeof output === 'string' ? output.split('\n') : [];
522
- return extractSettledPiFailure(lines);
523
- }
524
- if (!output || typeof output !== 'string') return null;
525
-
526
- const lines = output.split('\n');
527
- // Codex terminal truth is a turn.failed record at the newest end of JSONL output.
528
- // Search it newest-first so a preserved terminal tail wins over older provider chatter.
529
- if (providerName === 'codex') lines.reverse();
530
-
531
- for (const line of lines) {
532
- const content = stripTimestamp(line);
533
- if (!content.startsWith('{')) continue;
534
- try {
535
- const failure = failureFromProviderObject(JSON.parse(content), providerName);
536
- if (failure) return failure;
537
- } catch {
538
- // Ignore non-JSON output lines.
539
- }
540
- }
541
-
542
- return null;
543
- }
544
-
545
- function extractCliError(output, providerName = 'claude') {
546
- const failure = extractCliFailure(output, providerName);
547
- return failure ? { error: failure.error, provider: failure.provider } : null;
548
- }
549
-
550
- /**
551
- * Detects fatal standalone output lines that indicate no task output was produced.
552
- * Only matches when the line itself is the fatal message (not when it appears inside JSON).
553
- *
554
- * @param {string} output - Raw output text
555
- * @returns {boolean} True if a standalone fatal line is present
556
- */
557
- function hasFatalStandaloneOutput(output) {
558
- if (!output || typeof output !== 'string') return false;
559
- const lines = output.split('\n');
560
- for (const line of lines) {
561
- const stripped = stripTimestamp(line).trim();
562
- if (!stripped) continue;
563
- if (/^(task not found|process terminated)\b/i.test(stripped)) {
564
- return true;
565
- }
566
- }
567
- return false;
568
- }
569
-
570
- /**
571
- * Main extraction function - tries all strategies in priority order
572
- *
573
- * @param {string} output - Raw output from AI provider CLI
574
- * @param {string} providerName - Provider name ('claude', 'codex', 'gemini')
575
- * @returns {object|null} Extracted JSON object or null if extraction failed
576
- */
577
- function extractJsonFromOutput(output, providerName = 'claude') {
578
- if (!output || typeof output !== 'string') return null;
579
-
580
- const trimmedOutput = output.trim();
581
- if (!trimmedOutput) return null;
582
-
583
- // Strategy 1: Result wrapper (Claude format)
584
- const fromWrapper = extractFromResultWrapper(trimmedOutput);
585
- if (fromWrapper) return fromWrapper;
586
-
587
- // Strategy 2: Text events (non-Claude providers)
588
- const fromText = extractFromTextEvents(trimmedOutput, providerName);
589
- if (fromText) return fromText;
590
-
591
- // Strategy 3: Markdown extraction
592
- const fromMarkdown = extractFromMarkdown(trimmedOutput);
593
- if (fromMarkdown) return fromMarkdown;
594
-
595
- // Strategy 4: Direct JSON parse (raw output)
596
- const fromDirect = extractDirectJson(trimmedOutput);
597
- if (fromDirect) return fromDirect;
598
-
599
- if (hasFatalStandaloneOutput(trimmedOutput)) {
600
- return null;
601
- }
602
-
603
- return null;
604
- }
605
-
1
+ "use strict";
2
+ const failureExtraction = require("./output-extraction-failures");
3
+ const jsonExtraction = require("./output-extraction-json");
4
+ const { MAX_CLI_ERROR_BYTES, extractClaudeVertexModelError, extractCliError, extractCliFailure } = failureExtraction;
5
+ const { extractDirectJson, extractFromMarkdown, extractFromResultWrapper, extractFromTextEvents, extractJsonFromOutput, extractModelTextFromOutput, hasFatalStandaloneOutput, stripTimestamp, } = jsonExtraction;
606
6
  module.exports = {
607
- MAX_CLI_ERROR_BYTES,
608
- extractJsonFromOutput,
609
- extractModelTextFromOutput,
610
- extractCliFailure,
611
- extractCliError,
612
- extractClaudeVertexModelError,
613
- extractFromResultWrapper,
614
- extractFromTextEvents,
615
- extractFromMarkdown,
616
- extractDirectJson,
617
- stripTimestamp,
618
- hasFatalStandaloneOutput,
7
+ MAX_CLI_ERROR_BYTES,
8
+ extractJsonFromOutput,
9
+ extractModelTextFromOutput,
10
+ extractCliFailure,
11
+ extractCliError,
12
+ extractClaudeVertexModelError,
13
+ extractFromResultWrapper,
14
+ extractFromTextEvents,
15
+ extractFromMarkdown,
16
+ extractDirectJson,
17
+ stripTimestamp,
18
+ hasFatalStandaloneOutput,
619
19
  };
@@ -0,0 +1,30 @@
1
+ import failureExtraction = require('./output-extraction-failures');
2
+ import jsonExtraction = require('./output-extraction-json');
3
+
4
+ const { MAX_CLI_ERROR_BYTES, extractClaudeVertexModelError, extractCliError, extractCliFailure } =
5
+ failureExtraction;
6
+ const {
7
+ extractDirectJson,
8
+ extractFromMarkdown,
9
+ extractFromResultWrapper,
10
+ extractFromTextEvents,
11
+ extractJsonFromOutput,
12
+ extractModelTextFromOutput,
13
+ hasFatalStandaloneOutput,
14
+ stripTimestamp,
15
+ } = jsonExtraction;
16
+
17
+ export = {
18
+ MAX_CLI_ERROR_BYTES,
19
+ extractJsonFromOutput,
20
+ extractModelTextFromOutput,
21
+ extractCliFailure,
22
+ extractCliError,
23
+ extractClaudeVertexModelError,
24
+ extractFromResultWrapper,
25
+ extractFromTextEvents,
26
+ extractFromMarkdown,
27
+ extractDirectJson,
28
+ stripTimestamp,
29
+ hasFatalStandaloneOutput,
30
+ };