cloving 1.0.1 → 1.2.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 (309) hide show
  1. package/README.md +251 -20
  2. package/assets/watch-fonts/fira-code-OFL.md +93 -0
  3. package/assets/watch-fonts/fira-code-latin-400-normal.woff2 +0 -0
  4. package/assets/watch-fonts/fira-code-latin-500-normal.woff2 +0 -0
  5. package/assets/watch-fonts/heebo-OFL.md +93 -0
  6. package/assets/watch-fonts/heebo-latin-500-normal.woff2 +0 -0
  7. package/assets/watch-fonts/heebo-latin-700-normal.woff2 +0 -0
  8. package/assets/watch-fonts/heebo-latin-800-normal.woff2 +0 -0
  9. package/assets/watch-fonts/manifest.json +112 -0
  10. package/assets/watch-fonts/space-grotesk-OFL.md +93 -0
  11. package/assets/watch-fonts/space-grotesk-latin-400-normal.woff2 +0 -0
  12. package/assets/watch-fonts/space-grotesk-latin-500-normal.woff2 +0 -0
  13. package/assets/watch-fonts/space-grotesk-latin-600-normal.woff2 +0 -0
  14. package/assets/watch-fonts/space-grotesk-latin-700-normal.woff2 +0 -0
  15. package/dist/src/authority/commands.d.ts +1 -0
  16. package/dist/src/authority/commands.js +33 -4
  17. package/dist/src/authority/dispatch-decision.d.ts +1 -0
  18. package/dist/src/authority/dispatch-decision.js +7 -4
  19. package/dist/src/authority/events.js +2 -2
  20. package/dist/src/authority/handoff-chain.d.ts +24 -0
  21. package/dist/src/authority/handoff-chain.js +46 -0
  22. package/dist/src/authority/reconciliation.d.ts +3 -0
  23. package/dist/src/authority/reconciliation.js +21 -5
  24. package/dist/src/authority/transitions.d.ts +1 -1
  25. package/dist/src/authority/transitions.js +5 -0
  26. package/dist/src/broker/actor/authority-queries.d.ts +4 -0
  27. package/dist/src/broker/actor/authority-queries.js +51 -2
  28. package/dist/src/broker/actor/authority-session.d.ts +2 -0
  29. package/dist/src/broker/actor/authority-session.js +3 -4
  30. package/dist/src/broker/actor/delivery-intents.d.ts +1 -0
  31. package/dist/src/broker/actor/effect-delivery.js +9 -0
  32. package/dist/src/broker/authority-admission.js +13 -5
  33. package/dist/src/chats/analysis-batches.d.ts +42 -0
  34. package/dist/src/chats/analysis-batches.js +97 -0
  35. package/dist/src/chats/analysis-checkpoint.d.ts +29 -0
  36. package/dist/src/chats/analysis-checkpoint.js +31 -0
  37. package/dist/src/chats/analysis-contract.d.ts +80 -0
  38. package/dist/src/chats/analysis-contract.js +16 -0
  39. package/dist/src/chats/analysis-data.d.ts +3 -0
  40. package/dist/src/chats/analysis-data.js +85 -0
  41. package/dist/src/chats/analysis-input.d.ts +18 -0
  42. package/dist/src/chats/analysis-input.js +97 -0
  43. package/dist/src/chats/analysis-links.d.ts +2 -0
  44. package/dist/src/chats/analysis-links.js +25 -0
  45. package/dist/src/chats/analysis-merge.d.ts +16 -0
  46. package/dist/src/chats/analysis-merge.js +134 -0
  47. package/dist/src/chats/analysis-prompt.d.ts +18 -0
  48. package/dist/src/chats/analysis-prompt.js +42 -0
  49. package/dist/src/chats/analysis-proposal.d.ts +4 -0
  50. package/dist/src/chats/analysis-proposal.js +41 -0
  51. package/dist/src/chats/analysis-provenance.d.ts +4 -0
  52. package/dist/src/chats/analysis-provenance.js +99 -0
  53. package/dist/src/chats/analysis-shape.d.ts +4 -0
  54. package/dist/src/chats/analysis-shape.js +235 -0
  55. package/dist/src/chats/analysis.d.ts +3 -0
  56. package/dist/src/chats/analysis.js +42 -0
  57. package/dist/src/chats/corpus-input.d.ts +5 -0
  58. package/dist/src/chats/corpus-input.js +288 -0
  59. package/dist/src/chats/destination.js +3 -1
  60. package/dist/src/chats/import.d.ts +8 -6
  61. package/dist/src/chats/import.js +195 -23
  62. package/dist/src/chats/input-file.d.ts +3 -0
  63. package/dist/src/chats/input-file.js +32 -0
  64. package/dist/src/chats/normalize.d.ts +11 -2
  65. package/dist/src/chats/normalize.js +18 -2
  66. package/dist/src/chats/previous-import.d.ts +5 -0
  67. package/dist/src/chats/previous-import.js +34 -0
  68. package/dist/src/chats/reader.d.ts +7 -1
  69. package/dist/src/chats/reader.js +46 -15
  70. package/dist/src/chats/redact-import.d.ts +14 -0
  71. package/dist/src/chats/redact-import.js +141 -0
  72. package/dist/src/chats/redaction.d.ts +41 -0
  73. package/dist/src/chats/redaction.js +161 -0
  74. package/dist/src/chats/reference-mapping.d.ts +16 -0
  75. package/dist/src/chats/reference-mapping.js +153 -0
  76. package/dist/src/chats/revision-input.d.ts +3 -0
  77. package/dist/src/chats/revision-input.js +180 -0
  78. package/dist/src/chats/revision.d.ts +48 -0
  79. package/dist/src/chats/revision.js +94 -0
  80. package/dist/src/chats/selection.d.ts +25 -0
  81. package/dist/src/chats/selection.js +109 -0
  82. package/dist/src/chats/source.d.ts +23 -0
  83. package/dist/src/chats/source.js +135 -0
  84. package/dist/src/chats/structure.d.ts +57 -0
  85. package/dist/src/chats/structure.js +216 -0
  86. package/dist/src/chats/workflow-generation-projection.d.ts +8 -0
  87. package/dist/src/chats/workflow-generation-projection.js +75 -0
  88. package/dist/src/chats/workflow-generation-source.d.ts +25 -0
  89. package/dist/src/chats/workflow-generation-source.js +124 -0
  90. package/dist/src/chats/workflow-generation-text.d.ts +23 -0
  91. package/dist/src/chats/workflow-generation-text.js +74 -0
  92. package/dist/src/chats/workflow-generation.d.ts +69 -0
  93. package/dist/src/chats/workflow-generation.js +142 -0
  94. package/dist/src/cli/arguments.d.ts +8 -0
  95. package/dist/src/cli/arguments.js +94 -13
  96. package/dist/src/cli/client.d.ts +1 -0
  97. package/dist/src/cli/client.js +38 -1
  98. package/dist/src/cli/commands.d.ts +3 -0
  99. package/dist/src/cli/commands.js +29 -11
  100. package/dist/src/cli/main.d.ts +2 -1
  101. package/dist/src/cli/main.js +61 -14
  102. package/dist/src/cli/render.d.ts +3 -0
  103. package/dist/src/cli/render.js +122 -7
  104. package/dist/src/cli/usage-render.d.ts +3 -0
  105. package/dist/src/cli/usage-render.js +28 -0
  106. package/dist/src/cli/usage.d.ts +3 -2
  107. package/dist/src/cli/usage.js +42 -7
  108. package/dist/src/cli/watch-actions.d.ts +10 -0
  109. package/dist/src/cli/watch-actions.js +58 -0
  110. package/dist/src/cli/watch-board-view.d.ts +44 -1
  111. package/dist/src/cli/watch-board-view.js +137 -18
  112. package/dist/src/cli/watch-board.d.ts +7 -1
  113. package/dist/src/cli/watch-board.js +48 -11
  114. package/dist/src/cli/watch-card-client.d.ts +1 -0
  115. package/dist/src/cli/watch-card-client.js +44 -0
  116. package/dist/src/cli/watch-card-forms.d.ts +2 -0
  117. package/dist/src/cli/watch-card-forms.js +33 -0
  118. package/dist/src/cli/watch-card-reply.d.ts +5 -0
  119. package/dist/src/cli/watch-card-reply.js +34 -0
  120. package/dist/src/cli/watch-card-view.d.ts +40 -0
  121. package/dist/src/cli/watch-card-view.js +86 -0
  122. package/dist/src/cli/watch-client.d.ts +1 -0
  123. package/dist/src/cli/watch-client.js +122 -0
  124. package/dist/src/cli/watch-model.d.ts +10 -4
  125. package/dist/src/cli/watch-model.js +61 -67
  126. package/dist/src/cli/watch-page.d.ts +1 -1
  127. package/dist/src/cli/watch-page.js +89 -86
  128. package/dist/src/cli/watch-phases.js +3 -3
  129. package/dist/src/cli/watch-pr-board.d.ts +3 -0
  130. package/dist/src/cli/watch-pr-board.js +26 -0
  131. package/dist/src/cli/watch-pr-command.d.ts +18 -0
  132. package/dist/src/cli/watch-pr-command.js +74 -0
  133. package/dist/src/cli/watch-pr-identity.d.ts +32 -0
  134. package/dist/src/cli/watch-pr-identity.js +87 -0
  135. package/dist/src/cli/watch-pr-observer.d.ts +20 -0
  136. package/dist/src/cli/watch-pr-observer.js +150 -0
  137. package/dist/src/cli/watch-pr-settings.d.ts +8 -0
  138. package/dist/src/cli/watch-pr-settings.js +47 -0
  139. package/dist/src/cli/watch-pull-request.d.ts +10 -0
  140. package/dist/src/cli/watch-pull-request.js +130 -0
  141. package/dist/src/cli/watch-reads.d.ts +7 -1
  142. package/dist/src/cli/watch-reads.js +44 -18
  143. package/dist/src/cli/watch-render.d.ts +29 -2
  144. package/dist/src/cli/watch-render.js +11 -3
  145. package/dist/src/cli/watch-run-input.d.ts +14 -0
  146. package/dist/src/cli/watch-run-input.js +49 -0
  147. package/dist/src/cli/watch-server.d.ts +3 -0
  148. package/dist/src/cli/watch-server.js +77 -8
  149. package/dist/src/cli/watch-start-view.d.ts +18 -0
  150. package/dist/src/cli/watch-start-view.js +77 -0
  151. package/dist/src/cli/watch-turn.d.ts +1 -0
  152. package/dist/src/cli/watch-turn.js +8 -3
  153. package/dist/src/cli/watch-usage.d.ts +6 -0
  154. package/dist/src/cli/watch-usage.js +65 -0
  155. package/dist/src/cli/watch-view.d.ts +22 -0
  156. package/dist/src/cli/watch-view.js +111 -19
  157. package/dist/src/cli.js +48 -6
  158. package/dist/src/daemon/analysis-launch.d.ts +5 -0
  159. package/dist/src/daemon/analysis-launch.js +81 -0
  160. package/dist/src/daemon/analysis-token.d.ts +6 -0
  161. package/dist/src/daemon/analysis-token.js +88 -0
  162. package/dist/src/daemon/analysis-worker.d.ts +20 -0
  163. package/dist/src/daemon/analysis-worker.js +271 -0
  164. package/dist/src/daemon/chats-batch-binding.d.ts +23 -0
  165. package/dist/src/daemon/chats-batch-binding.js +99 -0
  166. package/dist/src/daemon/chats-capture.d.ts +18 -0
  167. package/dist/src/daemon/chats-capture.js +194 -0
  168. package/dist/src/daemon/chats-checkpoints.d.ts +41 -0
  169. package/dist/src/daemon/chats-checkpoints.js +186 -0
  170. package/dist/src/daemon/chats-files.d.ts +42 -0
  171. package/dist/src/daemon/chats-files.js +252 -0
  172. package/dist/src/daemon/chats-follow-up.d.ts +38 -0
  173. package/dist/src/daemon/chats-follow-up.js +180 -0
  174. package/dist/src/daemon/chats-question.d.ts +15 -0
  175. package/dist/src/daemon/chats-question.js +93 -0
  176. package/dist/src/daemon/chats-worker.d.ts +13 -0
  177. package/dist/src/daemon/chats-worker.js +201 -0
  178. package/dist/src/daemon/claude-turn.d.ts +11 -0
  179. package/dist/src/daemon/claude-turn.js +96 -15
  180. package/dist/src/daemon/claude-worker.d.ts +2 -1
  181. package/dist/src/daemon/claude-worker.js +92 -45
  182. package/dist/src/daemon/codex-stream.js +16 -0
  183. package/dist/src/daemon/daemon.d.ts +8 -1
  184. package/dist/src/daemon/daemon.js +51 -14
  185. package/dist/src/daemon/delivery-router.js +6 -0
  186. package/dist/src/daemon/github-calls.d.ts +4 -0
  187. package/dist/src/daemon/github-calls.js +16 -7
  188. package/dist/src/daemon/github-ci.d.ts +6 -0
  189. package/dist/src/daemon/github-ci.js +170 -0
  190. package/dist/src/daemon/github-merge-call.d.ts +14 -0
  191. package/dist/src/daemon/github-merge-call.js +73 -0
  192. package/dist/src/daemon/github-merge.d.ts +3 -5
  193. package/dist/src/daemon/github-merge.js +52 -95
  194. package/dist/src/daemon/github-methods.d.ts +28 -0
  195. package/dist/src/daemon/github-methods.js +84 -16
  196. package/dist/src/daemon/github-operation.d.ts +2 -0
  197. package/dist/src/daemon/github-retry.d.ts +6 -0
  198. package/dist/src/daemon/github-retry.js +49 -0
  199. package/dist/src/daemon/github-ticket-status.d.ts +3 -0
  200. package/dist/src/daemon/github-ticket-status.js +294 -0
  201. package/dist/src/daemon/github-worker.js +2 -1
  202. package/dist/src/daemon/handoff-worker.d.ts +10 -0
  203. package/dist/src/daemon/handoff-worker.js +232 -0
  204. package/dist/src/daemon/issue-queue.d.ts +2 -0
  205. package/dist/src/daemon/issue-queue.js +186 -43
  206. package/dist/src/daemon/notify-journal.d.ts +18 -0
  207. package/dist/src/daemon/notify-journal.js +108 -0
  208. package/dist/src/daemon/notify-message.js +2 -1
  209. package/dist/src/daemon/notify.js +176 -37
  210. package/dist/src/daemon/operation-journal.d.ts +1 -0
  211. package/dist/src/daemon/operation-journal.js +4 -2
  212. package/dist/src/daemon/retrying-turn.d.ts +12 -0
  213. package/dist/src/daemon/retrying-turn.js +231 -0
  214. package/dist/src/daemon/ticket-dependency-waits.d.ts +18 -0
  215. package/dist/src/daemon/ticket-dependency-waits.js +60 -0
  216. package/dist/src/daemon/ticket-registration.d.ts +8 -4
  217. package/dist/src/daemon/ticket-registration.js +76 -22
  218. package/dist/src/daemon/ticket-source.d.ts +4 -1
  219. package/dist/src/daemon/ticket-source.js +8 -2
  220. package/dist/src/decision-visibility.d.ts +2 -0
  221. package/dist/src/decision-visibility.js +10 -0
  222. package/dist/src/execution-pin.d.ts +4 -0
  223. package/dist/src/execution-pin.js +23 -2
  224. package/dist/src/host/start-delivery.d.ts +2 -1
  225. package/dist/src/host/start-delivery.js +1 -1
  226. package/dist/src/host/step-bridge-host.d.ts +1 -0
  227. package/dist/src/host/step-bridge-host.js +16 -0
  228. package/dist/src/host/world-reconciliation.d.ts +3 -0
  229. package/dist/src/host/world-reconciliation.js +9 -0
  230. package/dist/src/host/world-runs.js +14 -1
  231. package/dist/src/issue-identity.d.ts +6 -0
  232. package/dist/src/issue-identity.js +23 -0
  233. package/dist/src/service/queue-runs.d.ts +3 -0
  234. package/dist/src/service/queue-runs.js +39 -0
  235. package/dist/src/service/registry.d.ts +8 -2
  236. package/dist/src/service/registry.js +20 -8
  237. package/dist/src/service/replies.d.ts +2 -0
  238. package/dist/src/service/run-handlers.js +54 -30
  239. package/dist/src/service/service.d.ts +3 -0
  240. package/dist/src/service/service.js +3 -1
  241. package/dist/src/service/submission-handler.d.ts +1 -0
  242. package/dist/src/service/submission-handler.js +92 -13
  243. package/dist/src/service/worker-totals.d.ts +3 -0
  244. package/dist/src/service/worker-totals.js +52 -0
  245. package/dist/src/step-bridge.d.ts +9 -0
  246. package/dist/src/steps/handoff.d.ts +2 -0
  247. package/dist/src/steps/handoff.js +13 -0
  248. package/dist/src/ticket-dependencies.d.ts +1 -0
  249. package/dist/src/ticket-dependencies.js +15 -0
  250. package/dist/src/ticket-status.d.ts +8 -0
  251. package/dist/src/ticket-status.js +48 -0
  252. package/dist/src/token-prices.d.ts +21 -0
  253. package/dist/src/token-prices.js +108 -0
  254. package/dist/src/worker-usage.d.ts +31 -0
  255. package/dist/src/worker-usage.js +44 -0
  256. package/dist/src/workflow-admission.d.ts +1 -0
  257. package/dist/src/workflow-candidate.d.ts +29 -0
  258. package/dist/src/workflow-candidate.js +60 -0
  259. package/dist/src/workflow-contracts.d.ts +4 -0
  260. package/dist/src/workflow-contracts.js +32 -5
  261. package/dist/src/workflow-declaration.d.ts +12 -1
  262. package/dist/src/workflow-declaration.js +71 -13
  263. package/dist/src/workflow-discovery.d.ts +18 -0
  264. package/dist/src/workflow-discovery.js +33 -0
  265. package/dist/src/workflow-refusals.d.ts +6 -0
  266. package/dist/src/workflow-refusals.js +39 -0
  267. package/dist/src/workflows.d.ts +3 -1
  268. package/dist/src/workflows.js +2 -0
  269. package/dist/tools/admit-workflow.d.ts +13 -0
  270. package/dist/tools/admit-workflow.js +94 -0
  271. package/dist/tools/self-host-processes.js +7 -2
  272. package/dist/tools/self-host-project.d.ts +17 -0
  273. package/dist/tools/self-host-project.js +177 -0
  274. package/dist/tools/self-host-workflows.d.ts +1 -1
  275. package/dist/tools/self-host-workflows.js +2 -2
  276. package/dist/tools/self-host.js +30 -84
  277. package/dist/tools/self-update-host.d.ts +7 -0
  278. package/dist/tools/self-update-host.js +48 -1
  279. package/dist/tools/self-update.d.ts +1 -0
  280. package/dist/tools/self-update.js +85 -13
  281. package/dist/tools/workflow-bundle-dependencies.d.ts +5 -0
  282. package/dist/tools/workflow-bundle-dependencies.js +93 -0
  283. package/dist/tools/workflow-bundles.d.ts +20 -0
  284. package/dist/tools/workflow-bundles.js +173 -0
  285. package/dist/tools/workflow-candidate-counts.d.ts +8 -0
  286. package/dist/tools/workflow-candidate-counts.js +251 -0
  287. package/dist/tools/workflow-candidate-program.d.ts +11 -0
  288. package/dist/tools/workflow-candidate-program.js +78 -0
  289. package/dist/tools/workflow-candidate-source.d.ts +6 -0
  290. package/dist/tools/workflow-candidate-source.js +107 -0
  291. package/dist/tools/workflow-candidate-syntax.d.ts +15 -0
  292. package/dist/tools/workflow-candidate-syntax.js +219 -0
  293. package/dist/tools/workflow-folder-capture.d.ts +17 -0
  294. package/dist/tools/workflow-folder-capture.js +216 -0
  295. package/dist/tools/workflow-folders.d.ts +33 -0
  296. package/dist/tools/workflow-folders.js +150 -0
  297. package/dist/tools/workflow-source-effects.d.ts +10 -0
  298. package/dist/tools/workflow-source-effects.js +213 -0
  299. package/dist/workflows/analyze-chats.d.ts +15 -0
  300. package/dist/workflows/analyze-chats.declaration.json +22 -0
  301. package/dist/workflows/analyze-chats.js +250 -0
  302. package/dist/workflows/develop-prd.js +71 -3
  303. package/dist/workflows/develop-ticket.d.ts +1 -7
  304. package/dist/workflows/develop-ticket.js +47 -141
  305. package/dist/workflows/issue-labels.d.ts +3 -1
  306. package/dist/workflows/issue-labels.js +34 -0
  307. package/dist/workflows/ticket-prompts.d.ts +35 -0
  308. package/dist/workflows/ticket-prompts.js +143 -0
  309. package/package.json +25 -5
@@ -0,0 +1,201 @@
1
+ import { saveQuestion } from "./chats-question.js";
2
+ import { saveAcceptedAnalysis, saveFollowUp, } from "./chats-follow-up.js";
3
+ import { record } from "../protocol.js";
4
+ import { validateAnalysis } from "../chats/analysis.js";
5
+ import { analysisDocumentBytes, analysisEvidence, analysisSaveInput, validAnalysisImportId, } from "../chats/analysis-input.js";
6
+ import { analysisBatchData, prepareAnalysisBatch, } from "../chats/analysis-batches.js";
7
+ import { captureAnalysisSnapshot, readCapturedAnalysisSnapshot, findAnalysisCapture, } from "./chats-capture.js";
8
+ import { operationKey } from "./operation-journal.js";
9
+ import { analysisDirectory } from "./chats-files.js";
10
+ function completed(intent, result) {
11
+ return {
12
+ kind: "completed",
13
+ worker: "chats",
14
+ receipt: operationKey(intent.operationId),
15
+ result: JSON.stringify(result),
16
+ };
17
+ }
18
+ function refused(code, codes = [code]) {
19
+ return {
20
+ kind: "failed",
21
+ reason: code,
22
+ result: JSON.stringify({ kind: "blocked", codes }),
23
+ };
24
+ }
25
+ function bounded(text) {
26
+ if (Buffer.byteLength(text) > analysisDocumentBytes)
27
+ throw new Error("analysis-too-large");
28
+ }
29
+ function ownIntent(intent) {
30
+ return (intent.kind === "protected-effect" &&
31
+ intent.capability === "chats" &&
32
+ ["read-analysis", "save-analysis"].includes(intent.method ?? "") &&
33
+ intent.payload !== undefined &&
34
+ intent.leaseGeneration !== undefined);
35
+ }
36
+ async function payloadOf(settings, intent) {
37
+ if (!ownIntent(intent) || intent.payload === undefined)
38
+ throw new Error("unsupported-effect");
39
+ if ((await settings.workflowId(intent.runId)) !== "analyze-chats")
40
+ throw new Error("workflow-not-allowed");
41
+ const text = await settings.document(intent.payload);
42
+ if (text === undefined)
43
+ throw new Error("payload-not-available");
44
+ bounded(text);
45
+ const payload = record(JSON.parse(text));
46
+ if (payload === undefined)
47
+ throw new Error("analysis-input-refused");
48
+ const importId = payload["importId"];
49
+ if (typeof importId !== "string" || importId === "")
50
+ throw new Error("analysis-input-refused");
51
+ if (!validAnalysisImportId(importId))
52
+ throw new Error("invalid-import-id");
53
+ if (intent.target !== importId)
54
+ throw new Error("analysis-input-refused");
55
+ return payload;
56
+ }
57
+ async function read(settings, call) {
58
+ const { importId } = call;
59
+ let directory;
60
+ try {
61
+ directory = await analysisDirectory(settings.runtimeDirectory, importId);
62
+ }
63
+ catch (error) {
64
+ if (Reflect.get(Object(error), "code") === "ENOENT")
65
+ throw new Error("redaction-required", { cause: error });
66
+ throw error;
67
+ }
68
+ const capture = await captureAnalysisSnapshot(directory, {
69
+ importId,
70
+ runId: call.intent.runId,
71
+ });
72
+ const snapshot = await readCapturedAnalysisSnapshot(directory, capture);
73
+ const batch = prepareAnalysisBatch(snapshot, {
74
+ nextRecordIndex: 0,
75
+ completedBatchCount: 0,
76
+ previousResult: null,
77
+ });
78
+ if (batch.kind === "refused")
79
+ throw new Error(batch.code);
80
+ const result = analysisBatchData(batch, { digest: capture.digest, snapshot });
81
+ bounded(JSON.stringify(result));
82
+ return completed(call.intent, result);
83
+ }
84
+ async function saveInput(settings, call) {
85
+ if ("snapshot" in call.payload)
86
+ return analysisSaveInput(call.payload);
87
+ const importId = String(call.payload["importId"]);
88
+ const directory = await analysisDirectory(settings.runtimeDirectory, importId);
89
+ const capture = await findAnalysisCapture(directory, {
90
+ runId: call.intent.runId,
91
+ importId,
92
+ });
93
+ if (capture === undefined)
94
+ throw new Error("analysis-output-failed");
95
+ const snapshot = await readCapturedAnalysisSnapshot(directory, capture);
96
+ return analysisSaveInput({ ...call.payload, snapshot });
97
+ }
98
+ async function save(settings, call) {
99
+ const input = await saveInput(settings, call);
100
+ const { snapshot, candidate } = input;
101
+ if ("followUp" in call.payload)
102
+ return saveFollowUp(settings.runtimeDirectory, { ...call, input });
103
+ if ("batch" in call.payload &&
104
+ Object.hasOwn(record(candidate) ?? {}, "openQuestion"))
105
+ return saveQuestion(settings, { ...call, input });
106
+ const validation = "batch" in call.payload
107
+ ? undefined
108
+ : validateAnalysis(candidate, analysisEvidence(snapshot));
109
+ if (validation === undefined)
110
+ return saveAcceptedAnalysis(settings.runtimeDirectory, { ...call, input });
111
+ if (!validation.accepted)
112
+ return refused(validation.codes[0] ?? "analysis-input-refused", validation.codes);
113
+ const question = validation.result.openQuestion;
114
+ if (question !== undefined)
115
+ return saveQuestion(settings, { ...call, input });
116
+ return saveAcceptedAnalysis(settings.runtimeDirectory, { ...call, input });
117
+ }
118
+ const reasons = new Set([
119
+ "analysis-too-large",
120
+ "redaction-required",
121
+ "invalid-import-id",
122
+ "analysis-invalid-json",
123
+ "analysis-follow-up-refused",
124
+ "analysis-input-refused",
125
+ "analysis-output-failed",
126
+ "analysis-batch-limit",
127
+ "unsupported-effect",
128
+ "workflow-not-allowed",
129
+ "payload-not-available",
130
+ ]);
131
+ async function delivered(settings, call) {
132
+ const { intent, mode } = call;
133
+ try {
134
+ if (call.signal?.aborted)
135
+ return { kind: "stopped" };
136
+ const payload = await payloadOf(settings, intent);
137
+ if (call.signal?.aborted)
138
+ return { kind: "stopped" };
139
+ if (intent.method === "read-analysis" && mode === "reconcile")
140
+ return { kind: "absent" };
141
+ if (intent.method === "read-analysis")
142
+ return await read(settings, {
143
+ intent,
144
+ importId: String(payload["importId"]),
145
+ });
146
+ return await save(settings, { intent, payload, mode });
147
+ }
148
+ catch (error) {
149
+ const message = String(Reflect.get(Object(error), "message"));
150
+ return refused(reasons.has(message) ? message : "analysis-input-refused");
151
+ }
152
+ }
153
+ export function chatsWorker(settings) {
154
+ if (process.platform !== "darwin") {
155
+ const unsupported = () => Promise.resolve(refused("platform-unsupported"));
156
+ return {
157
+ deliver: unsupported,
158
+ reconcile: unsupported,
159
+ stop: unsupported,
160
+ close: () => Promise.resolve(),
161
+ };
162
+ }
163
+ const active = new Map();
164
+ const lifecycle = { closed: false };
165
+ const deliver = (intent, signal) => {
166
+ if (lifecycle.closed || signal.aborted)
167
+ return Promise.resolve({ kind: "stopped" });
168
+ const key = operationKey(JSON.stringify([intent.runId, intent.operationId, intent.inputDigest]));
169
+ const known = active.get(key);
170
+ if (known !== undefined)
171
+ return known;
172
+ const pending = delivered(settings, {
173
+ intent,
174
+ mode: "deliver",
175
+ signal,
176
+ }).finally(() => active.delete(key));
177
+ active.set(key, pending);
178
+ return pending;
179
+ };
180
+ const stop = async (intent) => {
181
+ if (!ownIntent(intent))
182
+ return refused("unsupported-effect");
183
+ if ((await settings.workflowId(intent.runId)) !== "analyze-chats")
184
+ return refused("workflow-not-allowed");
185
+ const key = operationKey(JSON.stringify([intent.runId, intent.operationId, intent.inputDigest]));
186
+ const pending = active.get(key);
187
+ if (pending !== undefined)
188
+ return await pending;
189
+ const result = await delivered(settings, { intent, mode: "reconcile" });
190
+ return result.kind === "absent" ? { kind: "stopped" } : result;
191
+ };
192
+ return {
193
+ deliver,
194
+ reconcile: (intent) => delivered(settings, { intent, mode: "reconcile" }),
195
+ stop,
196
+ close: async () => {
197
+ lifecycle.closed = true;
198
+ await Promise.all(active.values());
199
+ },
200
+ };
201
+ }
@@ -1,22 +1,32 @@
1
+ import { type WorkerUsage, type WorkerAttemptUsage } from "../worker-usage.ts";
1
2
  export type Worker = "claude" | "codex";
2
3
  export interface StreamResult {
4
+ readonly attempts?: readonly WorkerAttemptUsage[];
5
+ readonly subtype?: string;
6
+ readonly errorType?: string;
7
+ readonly model: string | null;
3
8
  readonly text: string;
4
9
  readonly failed: boolean;
5
10
  readonly costUsd: number | null;
11
+ readonly usage: WorkerUsage;
6
12
  readonly sessionId: string | null;
7
13
  readonly turns: number | null;
8
14
  }
9
15
  export interface TurnEnd {
16
+ readonly stopped?: boolean;
10
17
  readonly exitCode: number | null;
11
18
  readonly result: StreamResult | undefined;
12
19
  }
13
20
  export interface TurnStart {
21
+ readonly mode?: "analysis";
22
+ readonly analysisToken?: string;
14
23
  readonly worker?: Worker;
15
24
  readonly turnId?: string;
16
25
  readonly environment?: Readonly<Record<string, string>>;
17
26
  readonly command: readonly string[];
18
27
  readonly directory: string;
19
28
  readonly folder: string;
29
+ readonly activityFolder?: string;
20
30
  readonly prompt: string;
21
31
  }
22
32
  export interface RunningTurn {
@@ -24,5 +34,6 @@ export interface RunningTurn {
24
34
  readonly ended: Promise<TurnEnd>;
25
35
  readonly stop: (graceMilliseconds: number) => void;
26
36
  }
37
+ export declare function capacityRefusal(result: StreamResult | undefined): boolean;
27
38
  export declare function streamResult(line: string): StreamResult | undefined;
28
39
  export declare function startTurn(start: TurnStart): RunningTurn;
@@ -2,6 +2,9 @@ import { spawn } from "node:child_process";
2
2
  import { createWriteStream, mkdtempSync, rmSync } from "node:fs";
3
3
  import { join } from "node:path";
4
4
  import { codexStream } from "./codex-stream.js";
5
+ import { priceOf, usageOf, } from "../worker-usage.js";
6
+ import { commandModel } from "../token-prices.js";
7
+ import { analysisCommand, analysisEnvironment } from "./analysis-launch.js";
5
8
  function parsed(line) {
6
9
  try {
7
10
  const value = JSON.parse(line);
@@ -17,6 +20,13 @@ function numberOf(value) {
17
20
  function textOf(value) {
18
21
  return typeof value === "string" ? value : null;
19
22
  }
23
+ export function capacityRefusal(result) {
24
+ return (result?.failed === true &&
25
+ ["success", "error_during_execution"].includes(result.subtype ?? "error_during_execution") &&
26
+ (result.text ===
27
+ "Selected model is at capacity. Please try a different model." ||
28
+ result.errorType === "overloaded"));
29
+ }
20
30
  export function streamResult(line) {
21
31
  if (!line.includes('"result"'))
22
32
  return undefined;
@@ -25,9 +35,17 @@ export function streamResult(line) {
25
35
  if (field("type") !== "result")
26
36
  return undefined;
27
37
  return {
38
+ ...(typeof field("subtype") === "string"
39
+ ? { subtype: String(field("subtype")) }
40
+ : {}),
41
+ ...(typeof field("error") === "string"
42
+ ? { errorType: String(field("error")) }
43
+ : {}),
28
44
  text: textOf(field("result")) ?? "",
29
45
  failed: field("is_error") === true,
30
- costUsd: numberOf(field("total_cost_usd")),
46
+ costUsd: priceOf(field("total_cost_usd")),
47
+ usage: usageOf(field("usage")),
48
+ model: textOf(field("model")),
31
49
  sessionId: textOf(field("session_id")),
32
50
  turns: numberOf(field("num_turns")),
33
51
  };
@@ -38,6 +56,11 @@ function ended(stream) {
38
56
  });
39
57
  }
40
58
  function turnEnvironment(configuration, start) {
59
+ if (start.mode === "analysis")
60
+ return {
61
+ ...analysisEnvironment(start.folder),
62
+ CLAUDE_CODE_OAUTH_TOKEN: start.analysisToken,
63
+ };
41
64
  const excluded = new Set([
42
65
  "GH_TOKEN",
43
66
  "GITHUB_TOKEN",
@@ -56,7 +79,7 @@ function turnEnvironment(configuration, start) {
56
79
  }
57
80
  function spawnTurn(start) {
58
81
  const configuration = mkdtempSync(join(start.folder, "gh-config-"));
59
- const [executable = "", ...fixed] = start.command;
82
+ const [executable = "", ...fixed] = start.mode === "analysis" ? analysisCommand() : start.command;
60
83
  try {
61
84
  const child = spawn(executable, fixed, {
62
85
  cwd: start.directory,
@@ -70,43 +93,101 @@ function spawnTurn(start) {
70
93
  throw error;
71
94
  }
72
95
  }
96
+ function receivedLines(stream, lines) {
97
+ for (const line of lines) {
98
+ const event = parsed(line);
99
+ const field = (name) => Reflect.get(Object(event), name);
100
+ const type = field("type");
101
+ if (type === "assistant" && field("parent_tool_use_id") == null)
102
+ stream.errorType = textOf(field("error"));
103
+ if (type === "system" || type === "result")
104
+ stream.model = textOf(field("model")) ?? stream.model;
105
+ const result = streamResult(line);
106
+ if (result !== undefined) {
107
+ const errorType = result.errorType ?? stream.errorType;
108
+ stream.result = {
109
+ ...result,
110
+ ...(errorType === null ? {} : { errorType }),
111
+ };
112
+ }
113
+ }
114
+ }
115
+ function activityOutput(start) {
116
+ if (start.mode === "analysis")
117
+ return undefined;
118
+ const output = createWriteStream(join(start.activityFolder ?? start.folder, "turn.jsonl"), { flags: start.activityFolder === undefined ? "w" : "a" });
119
+ if (start.activityFolder !== undefined)
120
+ output.write("\n");
121
+ return output;
122
+ }
73
123
  function turnOutput(start, stdout) {
74
- const output = createWriteStream(join(start.folder, "turn.jsonl"));
124
+ const output = activityOutput(start);
75
125
  const codex = start.worker === "codex" ? codexStream() : undefined;
76
- const stream = { pending: "", result: undefined };
126
+ const stream = {
127
+ pending: "",
128
+ result: undefined,
129
+ model: null,
130
+ errorType: null,
131
+ };
132
+ const received = (lines) => {
133
+ receivedLines(stream, lines);
134
+ };
77
135
  const written = (lines) => {
78
136
  for (const line of lines)
79
- output.write(`${line}\n`);
80
- stream.result = lines.map(streamResult).findLast(Boolean) ?? stream.result;
137
+ output?.write(`${line}\n`);
138
+ received(lines);
81
139
  };
82
140
  stdout.setEncoding("utf8");
83
141
  stdout.on("data", (chunk) => {
84
142
  if (codex === undefined)
85
- output.write(chunk);
143
+ output?.write(chunk);
86
144
  const lines = `${stream.pending}${chunk}`.split("\n");
87
145
  stream.pending = lines.pop() ?? "";
88
146
  if (codex !== undefined) {
89
147
  written(lines.flatMap(codex.line));
90
148
  return;
91
149
  }
92
- stream.result = lines.map(streamResult).findLast(Boolean) ?? stream.result;
150
+ received(lines);
93
151
  });
94
152
  return async (exitCode) => {
95
153
  if (codex !== undefined) {
96
154
  written(codex.line(stream.pending));
97
155
  written([codex.result(exitCode)]);
98
156
  }
99
- await ended(output);
100
- return codex === undefined
101
- ? (streamResult(stream.pending) ?? stream.result)
102
- : stream.result;
157
+ if (output !== undefined)
158
+ await ended(output);
159
+ if (codex === undefined)
160
+ received([stream.pending]);
161
+ const result = stream.result;
162
+ return result === undefined
163
+ ? undefined
164
+ : {
165
+ ...result,
166
+ model: result.model ??
167
+ stream.model ??
168
+ commandModel(start.mode === "analysis" ? analysisCommand() : start.command),
169
+ };
170
+ };
171
+ }
172
+ function withoutAnalysisToken(start, result) {
173
+ const token = start.mode === "analysis" ? start.analysisToken : undefined;
174
+ if (token === undefined || result === undefined)
175
+ return result;
176
+ const redact = (value) => value === null ? null : value.replaceAll(token, "[redacted]");
177
+ return {
178
+ ...result,
179
+ text: redact(result.text) ?? "",
180
+ model: redact(result.model),
181
+ sessionId: redact(result.sessionId),
103
182
  };
104
183
  }
105
184
  export function startTurn(start) {
106
185
  const { child, configuration } = spawnTurn(start);
107
186
  const output = turnOutput(start, child.stdout);
108
- const errors = createWriteStream(join(start.folder, "turn.stderr.log"));
109
- child.stderr.pipe(errors);
187
+ if (start.mode === "analysis")
188
+ child.stderr.resume();
189
+ else
190
+ child.stderr.pipe(createWriteStream(join(start.folder, "turn.stderr.log")));
110
191
  child.stdin.on("error", () => undefined);
111
192
  child.stdin.end(start.prompt);
112
193
  const closed = new Promise((settle) => {
@@ -121,7 +202,7 @@ export function startTurn(start) {
121
202
  timers.forEach(clearTimeout);
122
203
  return {
123
204
  exitCode,
124
- result: await output(exitCode),
205
+ result: withoutAnalysisToken(start, await output(exitCode)),
125
206
  };
126
207
  })
127
208
  .finally(() => {
@@ -1,8 +1,9 @@
1
1
  import { type TurnProfiles } from "../turn-profile.ts";
2
2
  import type { Delivery } from "../broker/actor/delivery-intents.ts";
3
3
  import { type Worker } from "./claude-turn.ts";
4
+ import { type RetrySettings } from "./retrying-turn.ts";
4
5
  import { type WorkerReport } from "./operation-journal.ts";
5
- export interface ClaudeWorkerSettings {
6
+ export interface ClaudeWorkerSettings extends RetrySettings {
6
7
  readonly worker?: Worker;
7
8
  readonly profiles?: TurnProfiles;
8
9
  readonly workflowId?: (runId: string) => Promise<string | undefined>;