issue-flow 0.12.0 → 0.14.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.
- package/README.md +79 -274
- package/dist/agent-OX3KPHE4.js +30 -0
- package/dist/{analyze-OEET7KGE.js → analyze-WIND2SEB.js} +31 -16
- package/dist/analyze-WIND2SEB.js.map +1 -0
- package/dist/{apply-ZIA3C52S.js → apply-JNOI2LR4.js} +18 -7
- package/dist/{apply-ZIA3C52S.js.map → apply-JNOI2LR4.js.map} +1 -1
- package/dist/bench-B4VZON7E.js +910 -0
- package/dist/bench-B4VZON7E.js.map +1 -0
- package/dist/{chunk-FADTCQGM.js → chunk-2IQ6M4ZE.js} +94 -32
- package/dist/chunk-2IQ6M4ZE.js.map +1 -0
- package/dist/chunk-3BWZO4YI.js +141 -0
- package/dist/chunk-3BWZO4YI.js.map +1 -0
- package/dist/chunk-3WFZETIM.js +163 -0
- package/dist/chunk-3WFZETIM.js.map +1 -0
- package/dist/chunk-67YIU2VB.js +362 -0
- package/dist/chunk-67YIU2VB.js.map +1 -0
- package/dist/{chunk-QCPGHBSZ.js → chunk-6BENHR2I.js} +63 -21
- package/dist/chunk-6BENHR2I.js.map +1 -0
- package/dist/{chunk-BYZDPR7N.js → chunk-6QYMSNVA.js} +194 -235
- package/dist/chunk-6QYMSNVA.js.map +1 -0
- package/dist/{chunk-Y5ZDJ4PJ.js → chunk-76MMPJ53.js} +20 -10
- package/dist/chunk-76MMPJ53.js.map +1 -0
- package/dist/chunk-7Z4Y3VKM.js +26 -0
- package/dist/chunk-7Z4Y3VKM.js.map +1 -0
- package/dist/{chunk-3QHK4YQA.js → chunk-B72RQZBV.js} +346 -119
- package/dist/chunk-B72RQZBV.js.map +1 -0
- package/dist/chunk-BEZ5BA5U.js +625 -0
- package/dist/chunk-BEZ5BA5U.js.map +1 -0
- package/dist/chunk-BRCNQXYQ.js +74 -0
- package/dist/chunk-BRCNQXYQ.js.map +1 -0
- package/dist/chunk-CGKLE6WR.js +1203 -0
- package/dist/chunk-CGKLE6WR.js.map +1 -0
- package/dist/chunk-CRGIQFUQ.js +83 -0
- package/dist/chunk-CRGIQFUQ.js.map +1 -0
- package/dist/{chunk-NS6R37II.js → chunk-F6TOYSYY.js} +141 -12
- package/dist/chunk-F6TOYSYY.js.map +1 -0
- package/dist/chunk-G5EK2XRN.js +25 -0
- package/dist/chunk-G5EK2XRN.js.map +1 -0
- package/dist/chunk-HAKDLR6N.js +134 -0
- package/dist/chunk-HAKDLR6N.js.map +1 -0
- package/dist/chunk-J3SOTUVI.js +298 -0
- package/dist/chunk-J3SOTUVI.js.map +1 -0
- package/dist/chunk-JN6D3MY6.js +30 -0
- package/dist/chunk-JN6D3MY6.js.map +1 -0
- package/dist/{chunk-LAFNLLQP.js → chunk-KMRFRXIT.js} +5 -5
- package/dist/chunk-KT7JKOXB.js +72 -0
- package/dist/chunk-KT7JKOXB.js.map +1 -0
- package/dist/chunk-L6HSKTQE.js +77 -0
- package/dist/chunk-L6HSKTQE.js.map +1 -0
- package/dist/chunk-LBGHI4S2.js +1264 -0
- package/dist/chunk-LBGHI4S2.js.map +1 -0
- package/dist/chunk-LEW4QM74.js +180 -0
- package/dist/chunk-LEW4QM74.js.map +1 -0
- package/dist/{chunk-FJP3UQGD.js → chunk-LFEQIZLB.js} +115 -20
- package/dist/chunk-LFEQIZLB.js.map +1 -0
- package/dist/chunk-OOVG2KBY.js +77 -0
- package/dist/chunk-OOVG2KBY.js.map +1 -0
- package/dist/{chunk-56KS3TFQ.js → chunk-OR43364P.js} +115 -160
- package/dist/chunk-OR43364P.js.map +1 -0
- package/dist/chunk-P3LRUNC6.js +16 -0
- package/dist/chunk-P3LRUNC6.js.map +1 -0
- package/dist/{chunk-TSOLWK7Y.js → chunk-PBTA3QQX.js} +8 -7
- package/dist/{chunk-TSOLWK7Y.js.map → chunk-PBTA3QQX.js.map} +1 -1
- package/dist/{chunk-MJULIKQU.js → chunk-PHW2YV6N.js} +23 -47
- package/dist/chunk-PHW2YV6N.js.map +1 -0
- package/dist/{chunk-73ATPIYX.js → chunk-PZTWU277.js} +36 -71
- package/dist/chunk-PZTWU277.js.map +1 -0
- package/dist/{chunk-M5UCXTIT.js → chunk-QD4VOILZ.js} +22 -18
- package/dist/chunk-QD4VOILZ.js.map +1 -0
- package/dist/chunk-QJ5UZAH5.js +2718 -0
- package/dist/chunk-QJ5UZAH5.js.map +1 -0
- package/dist/chunk-QK7WUO7A.js +283 -0
- package/dist/chunk-QK7WUO7A.js.map +1 -0
- package/dist/{chunk-A4SLHOW7.js → chunk-QZVKRDJY.js} +27 -19
- package/dist/chunk-QZVKRDJY.js.map +1 -0
- package/dist/chunk-REO3PXXO.js +71 -0
- package/dist/chunk-REO3PXXO.js.map +1 -0
- package/dist/{chunk-EZATO3DW.js → chunk-RVO7L4FX.js} +594 -17
- package/dist/chunk-RVO7L4FX.js.map +1 -0
- package/dist/{chunk-XQUSIEKA.js → chunk-SZMHCEYV.js} +63 -14
- package/dist/chunk-SZMHCEYV.js.map +1 -0
- package/dist/chunk-TYRNTSPJ.js +243 -0
- package/dist/chunk-TYRNTSPJ.js.map +1 -0
- package/dist/chunk-UJ3L2MS7.js +238 -0
- package/dist/chunk-UJ3L2MS7.js.map +1 -0
- package/dist/chunk-V7MO5EDS.js +120 -0
- package/dist/chunk-V7MO5EDS.js.map +1 -0
- package/dist/chunk-WB2X37MO.js +415 -0
- package/dist/chunk-WB2X37MO.js.map +1 -0
- package/dist/{chunk-NTMMF5UD.js → chunk-X44FKNKP.js} +525 -252
- package/dist/chunk-X44FKNKP.js.map +1 -0
- package/dist/chunk-XEYH6ZZI.js +289 -0
- package/dist/chunk-XEYH6ZZI.js.map +1 -0
- package/dist/cli.js +267 -44
- package/dist/cli.js.map +1 -1
- package/dist/{config-PRJGWW7J.js → config-HMFMCY2M.js} +31 -5
- package/dist/contract-JH2WBIO6.js +8 -0
- package/dist/conventions-NJF2OPVQ.js +146 -0
- package/dist/conventions-NJF2OPVQ.js.map +1 -0
- package/dist/diagnostics-THH42ZMP.js +23 -0
- package/dist/execute-KFNNZZHI.js +35 -0
- package/dist/{generate-EGB4KV2B.js → generate-FW5C6NP7.js} +37 -20
- package/dist/{generate-EGB4KV2B.js.map → generate-FW5C6NP7.js.map} +1 -1
- package/dist/git-W72QQ6GT.js +33 -0
- package/dist/init-HTN4V67Q.js +24 -0
- package/dist/{operations-BYT626KQ.js → operations-BCFOBH42.js} +27 -15
- package/dist/{operations-BYT626KQ.js.map → operations-BCFOBH42.js.map} +1 -1
- package/dist/permissions-4AKNQZHK.js +18 -0
- package/dist/plan-SIZLGA4V.js +34 -0
- package/dist/{policy-6S4GFC76.js → policy-DT6Q6ZVM.js} +20 -6
- package/dist/policy-DT6Q6ZVM.js.map +1 -0
- package/dist/pr-OMWCGUOW.js +39 -0
- package/dist/pr-review-N24CZPKR.js +32 -0
- package/dist/pr-review-N24CZPKR.js.map +1 -0
- package/dist/prd-5OFTZAHJ.js +33 -0
- package/dist/prd-5OFTZAHJ.js.map +1 -0
- package/dist/ps-RFORTCUD.js +93 -0
- package/dist/ps-RFORTCUD.js.map +1 -0
- package/dist/recorder-KCCPMKQG.js +32 -0
- package/dist/recorder-KCCPMKQG.js.map +1 -0
- package/dist/registry-GLPXOMFG.js +15 -0
- package/dist/registry-GLPXOMFG.js.map +1 -0
- package/dist/{resume-PPCNQVVV.js → resume-M5RLKP4I.js} +55 -34
- package/dist/{resume-PPCNQVVV.js.map → resume-M5RLKP4I.js.map} +1 -1
- package/dist/review-YM4JAABY.js +35 -0
- package/dist/review-YM4JAABY.js.map +1 -0
- package/dist/routing-NNT5WKGX.js +94 -0
- package/dist/routing-NNT5WKGX.js.map +1 -0
- package/dist/run-PZUKHPQK.js +54 -0
- package/dist/run-PZUKHPQK.js.map +1 -0
- package/dist/session-publisher-T7EI3CIP.js +11 -0
- package/dist/session-publisher-T7EI3CIP.js.map +1 -0
- package/dist/{state-manager-2EDVDBAR.js → state-manager-GQH32C44.js} +4 -2
- package/dist/state-manager-GQH32C44.js.map +1 -0
- package/dist/usage-V2CHE5PY.js +177 -0
- package/dist/usage-V2CHE5PY.js.map +1 -0
- package/dist/{web-EF5WIIGG.js → web-EA3KGNFN.js} +45 -30
- package/dist/web-EA3KGNFN.js.map +1 -0
- package/package.json +6 -2
- package/prompts/execute.md +7 -8
- package/prompts/plan.md +4 -5
- package/prompts/pr.md +2 -2
- package/web/AGENTS.md +152 -13
- package/web/public/app.css +380 -109
- package/web/public/app.js +525 -25
- package/web/public/index.html +68 -1
- package/dist/analyze-OEET7KGE.js.map +0 -1
- package/dist/chunk-3QHK4YQA.js.map +0 -1
- package/dist/chunk-42PJFMAR.js +0 -605
- package/dist/chunk-42PJFMAR.js.map +0 -1
- package/dist/chunk-4JSOYE4G.js +0 -368
- package/dist/chunk-4JSOYE4G.js.map +0 -1
- package/dist/chunk-56KS3TFQ.js.map +0 -1
- package/dist/chunk-73ATPIYX.js.map +0 -1
- package/dist/chunk-A4SLHOW7.js.map +0 -1
- package/dist/chunk-BAUPQXPE.js +0 -173
- package/dist/chunk-BAUPQXPE.js.map +0 -1
- package/dist/chunk-BYZDPR7N.js.map +0 -1
- package/dist/chunk-CD5ULRVC.js +0 -615
- package/dist/chunk-CD5ULRVC.js.map +0 -1
- package/dist/chunk-DIDUVL6O.js +0 -1365
- package/dist/chunk-DIDUVL6O.js.map +0 -1
- package/dist/chunk-EZATO3DW.js.map +0 -1
- package/dist/chunk-FADTCQGM.js.map +0 -1
- package/dist/chunk-FJP3UQGD.js.map +0 -1
- package/dist/chunk-LWRSMTTZ.js +0 -18
- package/dist/chunk-LWRSMTTZ.js.map +0 -1
- package/dist/chunk-M5UCXTIT.js.map +0 -1
- package/dist/chunk-M66SJHQQ.js +0 -206
- package/dist/chunk-M66SJHQQ.js.map +0 -1
- package/dist/chunk-MJULIKQU.js.map +0 -1
- package/dist/chunk-NS6R37II.js.map +0 -1
- package/dist/chunk-NTMMF5UD.js.map +0 -1
- package/dist/chunk-QCPGHBSZ.js.map +0 -1
- package/dist/chunk-XQUSIEKA.js.map +0 -1
- package/dist/chunk-Y5ZDJ4PJ.js.map +0 -1
- package/dist/execute-XBNVL753.js +0 -18
- package/dist/init-AJHCXJBP.js +0 -10
- package/dist/plan-QOZ3RIO6.js +0 -21
- package/dist/policy-6S4GFC76.js.map +0 -1
- package/dist/pr-EBBHD2ZX.js +0 -26
- package/dist/pr-review-VVMW5PO4.js +0 -20
- package/dist/prd-JQSZF7PR.js +0 -21
- package/dist/review-3F6MARWH.js +0 -19
- package/dist/run-RXE5GDQO.js +0 -36
- package/dist/web-EF5WIIGG.js.map +0 -1
- /package/dist/{config-PRJGWW7J.js.map → agent-OX3KPHE4.js.map} +0 -0
- /package/dist/{chunk-LAFNLLQP.js.map → chunk-KMRFRXIT.js.map} +0 -0
- /package/dist/{execute-XBNVL753.js.map → config-HMFMCY2M.js.map} +0 -0
- /package/dist/{init-AJHCXJBP.js.map → contract-JH2WBIO6.js.map} +0 -0
- /package/dist/{plan-QOZ3RIO6.js.map → diagnostics-THH42ZMP.js.map} +0 -0
- /package/dist/{pr-EBBHD2ZX.js.map → execute-KFNNZZHI.js.map} +0 -0
- /package/dist/{pr-review-VVMW5PO4.js.map → git-W72QQ6GT.js.map} +0 -0
- /package/dist/{prd-JQSZF7PR.js.map → init-HTN4V67Q.js.map} +0 -0
- /package/dist/{review-3F6MARWH.js.map → permissions-4AKNQZHK.js.map} +0 -0
- /package/dist/{run-RXE5GDQO.js.map → plan-SIZLGA4V.js.map} +0 -0
- /package/dist/{state-manager-2EDVDBAR.js.map → pr-OMWCGUOW.js.map} +0 -0
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
-
|
|
4
|
-
} from "./chunk-
|
|
3
|
+
setTelemetrySessionId
|
|
4
|
+
} from "./chunk-P3LRUNC6.js";
|
|
5
5
|
|
|
6
6
|
// src/core/session-state.ts
|
|
7
|
-
import { mkdir, rename, writeFile } from "fs/promises";
|
|
7
|
+
import { mkdir, rename, utimes, writeFile } from "fs/promises";
|
|
8
8
|
import { dirname } from "path";
|
|
9
9
|
import { stripVTControlCharacters } from "util";
|
|
10
10
|
var DEFAULT_LOG_LIMIT = 200;
|
|
11
11
|
var DEFAULT_THROTTLE_MS = 1e3;
|
|
12
|
+
var DEFAULT_SESSION_HEARTBEAT_MS = 1e4;
|
|
12
13
|
function emptyUsage() {
|
|
13
14
|
return {
|
|
14
15
|
inputTokens: null,
|
|
@@ -18,6 +19,16 @@ function emptyUsage() {
|
|
|
18
19
|
costUsd: null
|
|
19
20
|
};
|
|
20
21
|
}
|
|
22
|
+
function emptyPhaseTiming() {
|
|
23
|
+
return {
|
|
24
|
+
harnessExecutionMs: null,
|
|
25
|
+
orchestrationOverheadMs: null,
|
|
26
|
+
harnessStartupMs: null,
|
|
27
|
+
ttftMs: null,
|
|
28
|
+
attemptCount: null,
|
|
29
|
+
retryDurationMs: null
|
|
30
|
+
};
|
|
31
|
+
}
|
|
21
32
|
function emptyMetrics() {
|
|
22
33
|
return {
|
|
23
34
|
totalInputTokens: null,
|
|
@@ -53,7 +64,24 @@ function createInitialSnapshot() {
|
|
|
53
64
|
stories: [],
|
|
54
65
|
metrics: emptyMetrics(),
|
|
55
66
|
execution: { iteration: 0, retries: 0, correctionCycle: 0, maxCorrectionCycles: null },
|
|
56
|
-
|
|
67
|
+
executions: [],
|
|
68
|
+
processLogs: [],
|
|
69
|
+
configuration: null,
|
|
70
|
+
resilience: {
|
|
71
|
+
attempt: 0,
|
|
72
|
+
provider: null,
|
|
73
|
+
model: null,
|
|
74
|
+
lastFailureKind: null,
|
|
75
|
+
cooldownUntil: null,
|
|
76
|
+
lastActivityAt: null
|
|
77
|
+
},
|
|
78
|
+
git: {
|
|
79
|
+
branch: null,
|
|
80
|
+
baseBranch: null,
|
|
81
|
+
branchCreated: null,
|
|
82
|
+
startCommit: null,
|
|
83
|
+
commits: []
|
|
84
|
+
},
|
|
57
85
|
repository: { name: null, remoteUrl: null, branch: null, headCommit: null, root: null },
|
|
58
86
|
pullRequests: [],
|
|
59
87
|
logs: [],
|
|
@@ -61,7 +89,8 @@ function createInitialSnapshot() {
|
|
|
61
89
|
warnings: [],
|
|
62
90
|
lastError: null,
|
|
63
91
|
nextSteps: [],
|
|
64
|
-
environment: null
|
|
92
|
+
environment: null,
|
|
93
|
+
verification: null
|
|
65
94
|
};
|
|
66
95
|
}
|
|
67
96
|
function accumulate(current, delta) {
|
|
@@ -140,6 +169,16 @@ function reduceSessionEvent(snapshot, event, options) {
|
|
|
140
169
|
function isTerminalStage(stage) {
|
|
141
170
|
return stage === "done" || stage === "failed";
|
|
142
171
|
}
|
|
172
|
+
function transitionStory(story, stage, at, detail) {
|
|
173
|
+
if (story.stage === stage && story.stageDetail === detail) return story;
|
|
174
|
+
return {
|
|
175
|
+
...story,
|
|
176
|
+
stage,
|
|
177
|
+
stageSince: at,
|
|
178
|
+
stageDetail: detail,
|
|
179
|
+
history: [...story.history, { at, stage, detail }]
|
|
180
|
+
};
|
|
181
|
+
}
|
|
143
182
|
function deriveStageOnStoriesUpdate(story, before, at) {
|
|
144
183
|
if (!story.passes) {
|
|
145
184
|
return {
|
|
@@ -156,6 +195,7 @@ function deriveStageOnStoriesUpdate(story, before, at) {
|
|
|
156
195
|
function applyEvent(snapshot, event, options) {
|
|
157
196
|
switch (event.type) {
|
|
158
197
|
case "session:start": {
|
|
198
|
+
setTelemetrySessionId(event.sessionId);
|
|
159
199
|
const initial = createInitialSnapshot();
|
|
160
200
|
return {
|
|
161
201
|
...initial,
|
|
@@ -174,15 +214,28 @@ function applyEvent(snapshot, event, options) {
|
|
|
174
214
|
endedAt: null,
|
|
175
215
|
durationSeconds: null,
|
|
176
216
|
error: null,
|
|
217
|
+
...emptyPhaseTiming(),
|
|
177
218
|
...emptyUsage()
|
|
178
219
|
})),
|
|
179
|
-
git: {
|
|
220
|
+
git: {
|
|
221
|
+
branch: event.branch ?? null,
|
|
222
|
+
baseBranch: event.baseBranch ?? null,
|
|
223
|
+
branchCreated: event.branchCreated ?? null,
|
|
224
|
+
startCommit: event.startCommit ?? null,
|
|
225
|
+
commits: []
|
|
226
|
+
},
|
|
180
227
|
// The branch is the one piece of repository identity the session
|
|
181
228
|
// already knows here; the rest waits for publishGitState. Seeding it
|
|
182
229
|
// keeps git.branch and repository.branch consistent for a poll that
|
|
183
230
|
// lands before the first git:update.
|
|
184
231
|
repository: { ...initial.repository, branch: event.branch ?? null },
|
|
185
|
-
|
|
232
|
+
configuration: event.configuration ?? null,
|
|
233
|
+
environment: event.environment ? {
|
|
234
|
+
node: event.environment.node,
|
|
235
|
+
platform: event.environment.platform,
|
|
236
|
+
agent: event.environment.agent ?? null,
|
|
237
|
+
model: event.environment.model ?? null
|
|
238
|
+
} : null
|
|
186
239
|
};
|
|
187
240
|
}
|
|
188
241
|
case "issue:update":
|
|
@@ -220,11 +273,12 @@ function applyEvent(snapshot, event, options) {
|
|
|
220
273
|
endedAt: null,
|
|
221
274
|
durationSeconds: null,
|
|
222
275
|
error: null,
|
|
276
|
+
...emptyPhaseTiming(),
|
|
223
277
|
...emptyUsage()
|
|
224
278
|
}
|
|
225
279
|
];
|
|
226
280
|
const stories = event.phase === "review" ? snapshot.stories.map(
|
|
227
|
-
(story) => story.passes ?
|
|
281
|
+
(story) => story.passes ? transitionStory(story, "in_review", event.at, null) : story
|
|
228
282
|
) : snapshot.stories;
|
|
229
283
|
return {
|
|
230
284
|
...snapshot,
|
|
@@ -241,14 +295,20 @@ function applyEvent(snapshot, event, options) {
|
|
|
241
295
|
status: event.success ? "completed" : "failed",
|
|
242
296
|
endedAt: event.at,
|
|
243
297
|
durationSeconds: secondsBetween(p.startedAt, event.at),
|
|
244
|
-
error: event.error ? stripVTControlCharacters(event.error) : null
|
|
298
|
+
error: event.error ? stripVTControlCharacters(event.error) : null,
|
|
299
|
+
harnessExecutionMs: event.harnessExecutionMs ?? p.harnessExecutionMs,
|
|
300
|
+
orchestrationOverheadMs: event.orchestrationOverheadMs ?? p.orchestrationOverheadMs,
|
|
301
|
+
harnessStartupMs: event.harnessStartupMs ?? p.harnessStartupMs,
|
|
302
|
+
ttftMs: event.ttftMs ?? p.ttftMs,
|
|
303
|
+
attemptCount: event.attemptCount ?? p.attemptCount,
|
|
304
|
+
retryDurationMs: event.retryDurationMs ?? p.retryDurationMs
|
|
245
305
|
} : p
|
|
246
306
|
);
|
|
247
307
|
const phasesCompleted = phases.filter((p) => p.status === "completed").length;
|
|
248
308
|
const stories = !event.success ? snapshot.stories.map(
|
|
249
|
-
(story) => isTerminalStage(story.stage) ? story :
|
|
309
|
+
(story) => isTerminalStage(story.stage) ? story : transitionStory(story, "failed", event.at, null)
|
|
250
310
|
) : event.phase === "review" ? snapshot.stories.map(
|
|
251
|
-
(story) => story.passes ?
|
|
311
|
+
(story) => story.passes ? transitionStory(story, "done", event.at, null) : story
|
|
252
312
|
) : snapshot.stories;
|
|
253
313
|
return {
|
|
254
314
|
...snapshot,
|
|
@@ -268,9 +328,9 @@ function applyEvent(snapshot, event, options) {
|
|
|
268
328
|
const stories = snapshot.stories.map((story) => {
|
|
269
329
|
if (story.passes) return story;
|
|
270
330
|
if (story.id === storyId) {
|
|
271
|
-
return story
|
|
331
|
+
return transitionStory(story, "executing", event.at, null);
|
|
272
332
|
}
|
|
273
|
-
return story
|
|
333
|
+
return transitionStory(story, "pending", event.at, null);
|
|
274
334
|
});
|
|
275
335
|
return {
|
|
276
336
|
...snapshot,
|
|
@@ -291,11 +351,56 @@ function applyEvent(snapshot, event, options) {
|
|
|
291
351
|
...snapshot,
|
|
292
352
|
execution: { ...snapshot.execution, retries: snapshot.execution.retries + 1 }
|
|
293
353
|
};
|
|
354
|
+
case "agent:attempt":
|
|
355
|
+
return {
|
|
356
|
+
...snapshot,
|
|
357
|
+
resilience: {
|
|
358
|
+
...snapshot.resilience,
|
|
359
|
+
attempt: event.attempt,
|
|
360
|
+
provider: event.provider,
|
|
361
|
+
model: event.model ?? null,
|
|
362
|
+
lastActivityAt: event.at
|
|
363
|
+
}
|
|
364
|
+
};
|
|
365
|
+
case "failover":
|
|
366
|
+
return {
|
|
367
|
+
...snapshot,
|
|
368
|
+
resilience: {
|
|
369
|
+
...snapshot.resilience,
|
|
370
|
+
provider: event.to,
|
|
371
|
+
lastFailureKind: event.reason,
|
|
372
|
+
cooldownUntil: event.cooldownUntil ?? null,
|
|
373
|
+
lastActivityAt: event.at
|
|
374
|
+
}
|
|
375
|
+
};
|
|
376
|
+
case "agent:result":
|
|
377
|
+
return {
|
|
378
|
+
...snapshot,
|
|
379
|
+
resilience: {
|
|
380
|
+
...snapshot.resilience,
|
|
381
|
+
provider: event.provider,
|
|
382
|
+
lastFailureKind: event.failureKind ?? snapshot.resilience.lastFailureKind,
|
|
383
|
+
cooldownUntil: event.cooldownUntil ?? null,
|
|
384
|
+
lastActivityAt: event.at
|
|
385
|
+
}
|
|
386
|
+
};
|
|
387
|
+
case "agent:activity":
|
|
388
|
+
return {
|
|
389
|
+
...snapshot,
|
|
390
|
+
resilience: {
|
|
391
|
+
...snapshot.resilience,
|
|
392
|
+
provider: event.provider,
|
|
393
|
+
lastActivityAt: event.at
|
|
394
|
+
}
|
|
395
|
+
};
|
|
294
396
|
case "stories:update": {
|
|
295
397
|
const previous = new Map(snapshot.stories.map((story) => [story.id, story]));
|
|
296
398
|
const stories = event.stories.map((story) => {
|
|
297
399
|
const before = previous.get(story.id);
|
|
298
400
|
const completedAt = !story.passes ? null : before && !before.passes ? event.at : before?.completedAt ?? null;
|
|
401
|
+
const stage = deriveStageOnStoriesUpdate(story, before, event.at);
|
|
402
|
+
const history = before?.history ?? [];
|
|
403
|
+
const stageChanged = before !== void 0 && before.stage !== stage.stage;
|
|
299
404
|
return {
|
|
300
405
|
id: story.id,
|
|
301
406
|
title: story.title,
|
|
@@ -318,7 +423,8 @@ function applyEvent(snapshot, event, options) {
|
|
|
318
423
|
cacheReadTokens: before?.cacheReadTokens ?? null,
|
|
319
424
|
cacheCreationTokens: before?.cacheCreationTokens ?? null,
|
|
320
425
|
costUsd: before?.costUsd ?? null,
|
|
321
|
-
...
|
|
426
|
+
...stage,
|
|
427
|
+
history: stageChanged ? [...history, { at: event.at, stage: stage.stage, detail: stage.stageDetail }] : history
|
|
322
428
|
};
|
|
323
429
|
});
|
|
324
430
|
return {
|
|
@@ -337,7 +443,11 @@ function applyEvent(snapshot, event, options) {
|
|
|
337
443
|
const detail = event.detail ?? null;
|
|
338
444
|
const current = snapshot.currentActivity;
|
|
339
445
|
const since = current && current.story === story && current.tool === tool && current.detail === detail ? current.since : event.at;
|
|
340
|
-
return {
|
|
446
|
+
return {
|
|
447
|
+
...snapshot,
|
|
448
|
+
currentActivity: { story, tool, detail, since },
|
|
449
|
+
resilience: { ...snapshot.resilience, lastActivityAt: event.at }
|
|
450
|
+
};
|
|
341
451
|
}
|
|
342
452
|
case "log": {
|
|
343
453
|
const limit = options?.logLimit ?? DEFAULT_LOG_LIMIT;
|
|
@@ -349,12 +459,36 @@ function applyEvent(snapshot, event, options) {
|
|
|
349
459
|
const logs = [...snapshot.logs, entry].slice(-Math.max(1, limit));
|
|
350
460
|
return { ...snapshot, logs };
|
|
351
461
|
}
|
|
462
|
+
case "process:output": {
|
|
463
|
+
const limit = options?.logLimit ?? DEFAULT_LOG_LIMIT;
|
|
464
|
+
const entry = {
|
|
465
|
+
at: event.at,
|
|
466
|
+
phase: event.phase,
|
|
467
|
+
executionId: event.executionId,
|
|
468
|
+
provider: event.provider,
|
|
469
|
+
stream: event.stream,
|
|
470
|
+
message: stripVTControlCharacters(event.message)
|
|
471
|
+
};
|
|
472
|
+
return {
|
|
473
|
+
...snapshot,
|
|
474
|
+
processLogs: [...snapshot.processLogs, entry].slice(-Math.max(1, limit))
|
|
475
|
+
};
|
|
476
|
+
}
|
|
477
|
+
case "execution:update": {
|
|
478
|
+
const index = snapshot.executions.findIndex((entry) => entry.id === event.execution.id);
|
|
479
|
+
const executions = [...snapshot.executions];
|
|
480
|
+
if (index === -1) executions.push(event.execution);
|
|
481
|
+
else executions[index] = event.execution;
|
|
482
|
+
return { ...snapshot, executions };
|
|
483
|
+
}
|
|
352
484
|
case "git:update":
|
|
353
485
|
return {
|
|
354
486
|
...snapshot,
|
|
355
487
|
git: {
|
|
356
488
|
branch: event.branch ?? snapshot.git.branch,
|
|
357
489
|
baseBranch: event.baseBranch ?? snapshot.git.baseBranch,
|
|
490
|
+
branchCreated: reported(event.branchCreated, snapshot.git.branchCreated),
|
|
491
|
+
startCommit: snapshot.git.startCommit,
|
|
358
492
|
commits: event.commits ?? snapshot.git.commits
|
|
359
493
|
},
|
|
360
494
|
repository: {
|
|
@@ -371,7 +505,7 @@ function applyEvent(snapshot, event, options) {
|
|
|
371
505
|
case "correction:cycle": {
|
|
372
506
|
const stageDetail = `Cycle ${event.cycle}/${event.maxCycles}`;
|
|
373
507
|
const stories = snapshot.stories.map(
|
|
374
|
-
(story) => story.passes ?
|
|
508
|
+
(story) => story.passes ? transitionStory(story, "in_correction", event.at, stageDetail) : story
|
|
375
509
|
);
|
|
376
510
|
return {
|
|
377
511
|
...snapshot,
|
|
@@ -421,6 +555,15 @@ function applyEvent(snapshot, event, options) {
|
|
|
421
555
|
}
|
|
422
556
|
};
|
|
423
557
|
}
|
|
558
|
+
case "verify:end":
|
|
559
|
+
return {
|
|
560
|
+
...snapshot,
|
|
561
|
+
verification: {
|
|
562
|
+
verdict: event.verdict,
|
|
563
|
+
level: event.level,
|
|
564
|
+
independence: event.independence
|
|
565
|
+
}
|
|
566
|
+
};
|
|
424
567
|
case "session:end":
|
|
425
568
|
return {
|
|
426
569
|
...snapshot,
|
|
@@ -435,7 +578,7 @@ function applyEvent(snapshot, event, options) {
|
|
|
435
578
|
stories: snapshot.stories.map((story) => {
|
|
436
579
|
if (isTerminalStage(story.stage)) return story;
|
|
437
580
|
const stage = event.status === "completed" && story.passes ? "done" : "failed";
|
|
438
|
-
return
|
|
581
|
+
return transitionStory(story, stage, event.at, null);
|
|
439
582
|
}),
|
|
440
583
|
lastError: event.error ? { message: stripVTControlCharacters(event.error), at: event.at } : snapshot.lastError
|
|
441
584
|
};
|
|
@@ -510,6 +653,7 @@ var FilePublisher = class extends MemoryPublisher {
|
|
|
510
653
|
filePath;
|
|
511
654
|
throttleMs;
|
|
512
655
|
timer = null;
|
|
656
|
+
heartbeatTimer = null;
|
|
513
657
|
lastWriteStartedAt = 0;
|
|
514
658
|
lastWrittenVersion = 0;
|
|
515
659
|
writeChain = Promise.resolve();
|
|
@@ -518,10 +662,15 @@ var FilePublisher = class extends MemoryPublisher {
|
|
|
518
662
|
super(options);
|
|
519
663
|
this.filePath = filePath;
|
|
520
664
|
this.throttleMs = options.throttleMs ?? DEFAULT_THROTTLE_MS;
|
|
665
|
+
const heartbeatMs = options.heartbeatMs ?? DEFAULT_SESSION_HEARTBEAT_MS;
|
|
666
|
+
if (heartbeatMs > 0) {
|
|
667
|
+
this.heartbeatTimer = setInterval(() => this.enqueueHeartbeat(), heartbeatMs);
|
|
668
|
+
this.heartbeatTimer.unref();
|
|
669
|
+
}
|
|
521
670
|
}
|
|
522
671
|
afterPublish(event) {
|
|
523
672
|
if (this.closed) return;
|
|
524
|
-
const terminal = event.type === "phase:end" || event.type === "session:end";
|
|
673
|
+
const terminal = event.type === "phase:end" || event.type === "session:end" || event.type === "verify:end";
|
|
525
674
|
this.scheduleWrite(terminal);
|
|
526
675
|
}
|
|
527
676
|
scheduleWrite(force) {
|
|
@@ -560,6 +709,24 @@ var FilePublisher = class extends MemoryPublisher {
|
|
|
560
709
|
}
|
|
561
710
|
});
|
|
562
711
|
}
|
|
712
|
+
/**
|
|
713
|
+
* Keep directory-based discovery alive without changing snapshot content or
|
|
714
|
+
* its content-derived ETag. The write chain serializes the touch with atomic
|
|
715
|
+
* snapshot replacement, and no heartbeat is attempted before the first file
|
|
716
|
+
* has been written successfully.
|
|
717
|
+
*/
|
|
718
|
+
enqueueHeartbeat() {
|
|
719
|
+
if (this.closed) return;
|
|
720
|
+
this.writeChain = this.writeChain.then(async () => {
|
|
721
|
+
if (this.closed || this.lastWrittenVersion === 0) return;
|
|
722
|
+
const now = /* @__PURE__ */ new Date();
|
|
723
|
+
try {
|
|
724
|
+
await utimes(this.filePath, now, now);
|
|
725
|
+
} catch (err) {
|
|
726
|
+
this.warnOnce(err);
|
|
727
|
+
}
|
|
728
|
+
});
|
|
729
|
+
}
|
|
563
730
|
async flush() {
|
|
564
731
|
if (this.timer !== null) {
|
|
565
732
|
clearTimeout(this.timer);
|
|
@@ -571,8 +738,12 @@ var FilePublisher = class extends MemoryPublisher {
|
|
|
571
738
|
await this.writeChain;
|
|
572
739
|
}
|
|
573
740
|
async close() {
|
|
574
|
-
|
|
741
|
+
if (this.heartbeatTimer !== null) {
|
|
742
|
+
clearInterval(this.heartbeatTimer);
|
|
743
|
+
this.heartbeatTimer = null;
|
|
744
|
+
}
|
|
575
745
|
this.closed = true;
|
|
746
|
+
await this.flush();
|
|
576
747
|
}
|
|
577
748
|
};
|
|
578
749
|
async function atomicWriteFile(path, content) {
|
|
@@ -592,225 +763,13 @@ function getSessionPublisher() {
|
|
|
592
763
|
return _publisher;
|
|
593
764
|
}
|
|
594
765
|
|
|
595
|
-
// src/core/verbose.ts
|
|
596
|
-
var _verbose = false;
|
|
597
|
-
function setVerbose(enabled) {
|
|
598
|
-
_verbose = enabled;
|
|
599
|
-
}
|
|
600
|
-
function isVerbose() {
|
|
601
|
-
return _verbose;
|
|
602
|
-
}
|
|
603
|
-
var _onOutput;
|
|
604
|
-
function setOutputCallback(callback) {
|
|
605
|
-
_onOutput = callback;
|
|
606
|
-
}
|
|
607
|
-
function getOutputCallback() {
|
|
608
|
-
return _onOutput;
|
|
609
|
-
}
|
|
610
|
-
var _onStoryUpdate;
|
|
611
|
-
function setStoryUpdateCallback(callback) {
|
|
612
|
-
_onStoryUpdate = callback;
|
|
613
|
-
}
|
|
614
|
-
function getStoryUpdateCallback() {
|
|
615
|
-
return _onStoryUpdate;
|
|
616
|
-
}
|
|
617
|
-
var _onStoryStage;
|
|
618
|
-
function setStoryStageCallback(callback) {
|
|
619
|
-
_onStoryStage = callback;
|
|
620
|
-
}
|
|
621
|
-
function getStoryStageCallback() {
|
|
622
|
-
return _onStoryStage;
|
|
623
|
-
}
|
|
624
|
-
var _globalTimeout;
|
|
625
|
-
function setGlobalTimeout(ms) {
|
|
626
|
-
_globalTimeout = ms;
|
|
627
|
-
}
|
|
628
|
-
function getGlobalTimeout() {
|
|
629
|
-
return _globalTimeout;
|
|
630
|
-
}
|
|
631
|
-
var _inactivityTimeout;
|
|
632
|
-
function setInactivityTimeout(ms) {
|
|
633
|
-
_inactivityTimeout = ms;
|
|
634
|
-
}
|
|
635
|
-
function getInactivityTimeout() {
|
|
636
|
-
return _inactivityTimeout;
|
|
637
|
-
}
|
|
638
|
-
|
|
639
|
-
// src/ui/logger.ts
|
|
640
|
-
import chalk from "chalk";
|
|
641
|
-
import ora from "ora";
|
|
642
|
-
function useUnicode() {
|
|
643
|
-
if (process.env.NO_COLOR != null && process.env.NO_COLOR !== "") return false;
|
|
644
|
-
if (!process.stdout.isTTY) return false;
|
|
645
|
-
return true;
|
|
646
|
-
}
|
|
647
|
-
function useColor() {
|
|
648
|
-
if (process.env.NO_COLOR != null && process.env.NO_COLOR !== "") return false;
|
|
649
|
-
if (!process.stdout.isTTY) return false;
|
|
650
|
-
return true;
|
|
651
|
-
}
|
|
652
|
-
function getIcons() {
|
|
653
|
-
if (useUnicode()) {
|
|
654
|
-
return {
|
|
655
|
-
success: "\u2713",
|
|
656
|
-
fail: "\u2717",
|
|
657
|
-
pending: "\u23F3",
|
|
658
|
-
retry: "\u21BB",
|
|
659
|
-
warn: "\u26A0",
|
|
660
|
-
start: "\u25B6",
|
|
661
|
-
end: "\u25A0",
|
|
662
|
-
notReached: "\u25CB",
|
|
663
|
-
tool: "\u25B8",
|
|
664
|
-
connector: "\u2502"
|
|
665
|
-
};
|
|
666
|
-
}
|
|
667
|
-
return {
|
|
668
|
-
success: "[OK]",
|
|
669
|
-
fail: "[FAIL]",
|
|
670
|
-
pending: "[...]",
|
|
671
|
-
retry: "[RETRY]",
|
|
672
|
-
warn: "[WARN]",
|
|
673
|
-
start: "[START]",
|
|
674
|
-
end: "[END]",
|
|
675
|
-
notReached: "[ ]",
|
|
676
|
-
tool: ">",
|
|
677
|
-
connector: "|"
|
|
678
|
-
};
|
|
679
|
-
}
|
|
680
|
-
function getTermWidth() {
|
|
681
|
-
return process.stdout.columns ?? 80;
|
|
682
|
-
}
|
|
683
|
-
function emit(line, level = "info") {
|
|
684
|
-
getSessionPublisher().publish({ type: "log", at: isoNow(), level, message: line });
|
|
685
|
-
const cb = getOutputCallback();
|
|
686
|
-
if (cb) {
|
|
687
|
-
cb(line);
|
|
688
|
-
} else {
|
|
689
|
-
console.log(line);
|
|
690
|
-
}
|
|
691
|
-
}
|
|
692
|
-
function printSuccess(message) {
|
|
693
|
-
const icons = getIcons();
|
|
694
|
-
if (useColor()) {
|
|
695
|
-
emit(chalk.green(`${icons.success} ${message}`));
|
|
696
|
-
} else {
|
|
697
|
-
emit(`${icons.success} ${message}`);
|
|
698
|
-
}
|
|
699
|
-
}
|
|
700
|
-
function printError(message) {
|
|
701
|
-
const icons = getIcons();
|
|
702
|
-
if (useColor()) {
|
|
703
|
-
emit(chalk.red(`${icons.fail} ${message}`), "error");
|
|
704
|
-
} else {
|
|
705
|
-
emit(`${icons.fail} ${message}`, "error");
|
|
706
|
-
}
|
|
707
|
-
}
|
|
708
|
-
function printWarning(message) {
|
|
709
|
-
const icons = getIcons();
|
|
710
|
-
if (useColor()) {
|
|
711
|
-
emit(chalk.yellow(`${icons.warn} ${message}`), "warn");
|
|
712
|
-
} else {
|
|
713
|
-
emit(`${icons.warn} ${message}`, "warn");
|
|
714
|
-
}
|
|
715
|
-
}
|
|
716
|
-
function printRetry(message) {
|
|
717
|
-
const icons = getIcons();
|
|
718
|
-
if (useColor()) {
|
|
719
|
-
emit(chalk.yellow(`${icons.retry} ${message}`), "warn");
|
|
720
|
-
} else {
|
|
721
|
-
emit(`${icons.retry} ${message}`, "warn");
|
|
722
|
-
}
|
|
723
|
-
}
|
|
724
|
-
function printInfo(message) {
|
|
725
|
-
const icons = getIcons();
|
|
726
|
-
if (useColor()) {
|
|
727
|
-
emit(chalk.blue(`${icons.start} ${message}`));
|
|
728
|
-
} else {
|
|
729
|
-
emit(`${icons.start} ${message}`);
|
|
730
|
-
}
|
|
731
|
-
}
|
|
732
|
-
function createSpinner(message) {
|
|
733
|
-
return ora({
|
|
734
|
-
text: message,
|
|
735
|
-
color: "blue",
|
|
736
|
-
spinner: "dots"
|
|
737
|
-
});
|
|
738
|
-
}
|
|
739
|
-
function formatDuration(totalSeconds) {
|
|
740
|
-
const hours = Math.floor(totalSeconds / 3600);
|
|
741
|
-
const mins = Math.floor(totalSeconds % 3600 / 60);
|
|
742
|
-
const secs = totalSeconds % 60;
|
|
743
|
-
if (hours > 0) {
|
|
744
|
-
return `${hours}h ${mins}m ${secs}s`;
|
|
745
|
-
}
|
|
746
|
-
if (mins > 0) {
|
|
747
|
-
return `${mins}m ${secs}s`;
|
|
748
|
-
}
|
|
749
|
-
return `${secs}s`;
|
|
750
|
-
}
|
|
751
|
-
var ElapsedTimer = class {
|
|
752
|
-
constructor(onTick) {
|
|
753
|
-
this.onTick = onTick;
|
|
754
|
-
this.startTime = Date.now();
|
|
755
|
-
}
|
|
756
|
-
onTick;
|
|
757
|
-
startTime;
|
|
758
|
-
intervalId = null;
|
|
759
|
-
cleanup = () => this.stop();
|
|
760
|
-
start() {
|
|
761
|
-
this.startTime = Date.now();
|
|
762
|
-
this.intervalId = setInterval(() => {
|
|
763
|
-
const seconds = Math.floor((Date.now() - this.startTime) / 1e3);
|
|
764
|
-
this.onTick(formatDuration(seconds));
|
|
765
|
-
}, 1e3);
|
|
766
|
-
if (this.intervalId && typeof this.intervalId === "object" && "unref" in this.intervalId) {
|
|
767
|
-
this.intervalId.unref();
|
|
768
|
-
}
|
|
769
|
-
process.on("exit", this.cleanup);
|
|
770
|
-
return this;
|
|
771
|
-
}
|
|
772
|
-
getElapsedSeconds() {
|
|
773
|
-
return Math.floor((Date.now() - this.startTime) / 1e3);
|
|
774
|
-
}
|
|
775
|
-
stop() {
|
|
776
|
-
if (this.intervalId) {
|
|
777
|
-
clearInterval(this.intervalId);
|
|
778
|
-
this.intervalId = null;
|
|
779
|
-
}
|
|
780
|
-
process.removeListener("exit", this.cleanup);
|
|
781
|
-
return this.getElapsedSeconds();
|
|
782
|
-
}
|
|
783
|
-
};
|
|
784
|
-
|
|
785
766
|
export {
|
|
767
|
+
createInitialSnapshot,
|
|
768
|
+
reduceSessionEvent,
|
|
786
769
|
NullPublisher,
|
|
787
770
|
MemoryPublisher,
|
|
788
771
|
FilePublisher,
|
|
789
772
|
setSessionPublisher,
|
|
790
|
-
getSessionPublisher
|
|
791
|
-
setVerbose,
|
|
792
|
-
isVerbose,
|
|
793
|
-
setOutputCallback,
|
|
794
|
-
getOutputCallback,
|
|
795
|
-
setStoryUpdateCallback,
|
|
796
|
-
getStoryUpdateCallback,
|
|
797
|
-
setStoryStageCallback,
|
|
798
|
-
getStoryStageCallback,
|
|
799
|
-
setGlobalTimeout,
|
|
800
|
-
getGlobalTimeout,
|
|
801
|
-
setInactivityTimeout,
|
|
802
|
-
getInactivityTimeout,
|
|
803
|
-
useUnicode,
|
|
804
|
-
useColor,
|
|
805
|
-
getIcons,
|
|
806
|
-
getTermWidth,
|
|
807
|
-
printSuccess,
|
|
808
|
-
printError,
|
|
809
|
-
printWarning,
|
|
810
|
-
printRetry,
|
|
811
|
-
printInfo,
|
|
812
|
-
createSpinner,
|
|
813
|
-
formatDuration,
|
|
814
|
-
ElapsedTimer
|
|
773
|
+
getSessionPublisher
|
|
815
774
|
};
|
|
816
|
-
//# sourceMappingURL=chunk-
|
|
775
|
+
//# sourceMappingURL=chunk-6QYMSNVA.js.map
|