issue-flow 0.11.1 → 0.13.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-BXRIEKVM.js +238 -0
- package/dist/agent-BXRIEKVM.js.map +1 -0
- package/dist/{analyze-XV3K25K3.js → analyze-WS47UYGN.js} +32 -15
- package/dist/analyze-WS47UYGN.js.map +1 -0
- package/dist/{apply-WUJHDD7A.js → apply-OS62UWRN.js} +15 -5
- package/dist/{apply-WUJHDD7A.js.map → apply-OS62UWRN.js.map} +1 -1
- package/dist/bench-SA3BOME5.js +906 -0
- package/dist/bench-SA3BOME5.js.map +1 -0
- package/dist/chunk-37N2RJW2.js +120 -0
- package/dist/chunk-37N2RJW2.js.map +1 -0
- package/dist/chunk-3XLCNVMD.js +180 -0
- package/dist/chunk-3XLCNVMD.js.map +1 -0
- package/dist/chunk-5TB6KLC2.js +72 -0
- package/dist/chunk-5TB6KLC2.js.map +1 -0
- package/dist/{chunk-OBLVLIUS.js → chunk-664Y3NDX.js} +25 -13
- package/dist/chunk-664Y3NDX.js.map +1 -0
- package/dist/chunk-6FDFRNXZ.js +357 -0
- package/dist/chunk-6FDFRNXZ.js.map +1 -0
- package/dist/chunk-7KD66LIM.js +658 -0
- package/dist/chunk-7KD66LIM.js.map +1 -0
- package/dist/chunk-7Z4Y3VKM.js +26 -0
- package/dist/chunk-7Z4Y3VKM.js.map +1 -0
- package/dist/chunk-ARFVHC2F.js +1111 -0
- package/dist/chunk-ARFVHC2F.js.map +1 -0
- package/dist/{chunk-RKTEV6EG.js → chunk-BHJCGWQX.js} +141 -12
- package/dist/chunk-BHJCGWQX.js.map +1 -0
- package/dist/chunk-BQDQTIM7.js +74 -0
- package/dist/chunk-BQDQTIM7.js.map +1 -0
- package/dist/chunk-CNBYCMSU.js +2709 -0
- package/dist/chunk-CNBYCMSU.js.map +1 -0
- package/dist/chunk-CRGIQFUQ.js +83 -0
- package/dist/chunk-CRGIQFUQ.js.map +1 -0
- package/dist/chunk-DIG5XKQQ.js +298 -0
- package/dist/chunk-DIG5XKQQ.js.map +1 -0
- package/dist/chunk-FZDR7CGH.js +71 -0
- package/dist/chunk-FZDR7CGH.js.map +1 -0
- package/dist/chunk-HEF2RMKN.js +413 -0
- package/dist/chunk-HEF2RMKN.js.map +1 -0
- package/dist/{chunk-IVHZEYAX.js → chunk-HJGGNLWI.js} +25 -19
- package/dist/chunk-HJGGNLWI.js.map +1 -0
- package/dist/chunk-HQAHNIAR.js +283 -0
- package/dist/chunk-HQAHNIAR.js.map +1 -0
- package/dist/{chunk-GANSDJV7.js → chunk-IHIEXUTC.js} +46 -24
- package/dist/chunk-IHIEXUTC.js.map +1 -0
- package/dist/chunk-IV5SS4JN.js +84 -0
- package/dist/chunk-IV5SS4JN.js.map +1 -0
- package/dist/{chunk-HC2MT7BX.js → chunk-IYV6KNVF.js} +158 -592
- package/dist/chunk-IYV6KNVF.js.map +1 -0
- package/dist/{chunk-LVKQ2AKT.js → chunk-J62QSVP6.js} +10 -8
- package/dist/chunk-J62QSVP6.js.map +1 -0
- package/dist/chunk-KMMASOA6.js +134 -0
- package/dist/chunk-KMMASOA6.js.map +1 -0
- package/dist/chunk-KQHB7ZT3.js +559 -0
- package/dist/chunk-KQHB7ZT3.js.map +1 -0
- package/dist/chunk-L6HSKTQE.js +77 -0
- package/dist/chunk-L6HSKTQE.js.map +1 -0
- package/dist/{chunk-6N7LZZ5U.js → chunk-LZ6GFQAG.js} +474 -160
- package/dist/chunk-LZ6GFQAG.js.map +1 -0
- package/dist/{chunk-HQYXVIH6.js → chunk-MIVHK5YI.js} +5 -5
- package/dist/chunk-NEZZ6KDR.js +1217 -0
- package/dist/chunk-NEZZ6KDR.js.map +1 -0
- package/dist/{run-DBF2VWUN.js → chunk-OPNGPUKJ.js} +747 -594
- package/dist/chunk-OPNGPUKJ.js.map +1 -0
- package/dist/chunk-P3LRUNC6.js +16 -0
- package/dist/chunk-P3LRUNC6.js.map +1 -0
- package/dist/{chunk-BXCPXRBR.js → chunk-PIVGJM6K.js} +129 -32
- package/dist/chunk-PIVGJM6K.js.map +1 -0
- package/dist/{chunk-AAY6KM7N.js → chunk-PV4OX5TC.js} +167 -196
- package/dist/chunk-PV4OX5TC.js.map +1 -0
- package/dist/chunk-QCXPNSEL.js +141 -0
- package/dist/chunk-QCXPNSEL.js.map +1 -0
- package/dist/{chunk-34WNTK3K.js → chunk-QXDNBYQF.js} +53 -13
- package/dist/chunk-QXDNBYQF.js.map +1 -0
- package/dist/chunk-SNTTOQAD.js +30 -0
- package/dist/chunk-SNTTOQAD.js.map +1 -0
- package/dist/{chunk-EY6WMHV2.js → chunk-TM67EHSV.js} +67 -23
- package/dist/chunk-TM67EHSV.js.map +1 -0
- package/dist/chunk-TVN2JVOF.js +77 -0
- package/dist/chunk-TVN2JVOF.js.map +1 -0
- package/dist/chunk-TX5WIVYP.js +129 -0
- package/dist/chunk-TX5WIVYP.js.map +1 -0
- package/dist/{chunk-KQ4JQN7T.js → chunk-UJ7XWK7J.js} +83 -21
- package/dist/chunk-UJ7XWK7J.js.map +1 -0
- package/dist/{chunk-47VIN33V.js → chunk-UOCPC2Y2.js} +596 -17
- package/dist/chunk-UOCPC2Y2.js.map +1 -0
- package/dist/chunk-XEYH6ZZI.js +289 -0
- package/dist/chunk-XEYH6ZZI.js.map +1 -0
- package/dist/cli.js +390 -40
- package/dist/cli.js.map +1 -1
- package/dist/config-MEM2IWWN.js +76 -0
- package/dist/contract-JH2WBIO6.js +8 -0
- package/dist/conventions-WV4NDXGH.js +143 -0
- package/dist/conventions-WV4NDXGH.js.map +1 -0
- package/dist/execute-NITIHHCK.js +31 -0
- package/dist/{generate-TBVTLMOP.js → generate-MVQI7A45.js} +39 -19
- package/dist/{generate-TBVTLMOP.js.map → generate-MVQI7A45.js.map} +1 -1
- package/dist/git-YRVRUN3C.js +31 -0
- package/dist/init-OKWEC3EV.js +21 -0
- package/dist/operations-LU6JA3BX.js +374 -0
- package/dist/operations-LU6JA3BX.js.map +1 -0
- package/dist/permissions-7NMDFU27.js +18 -0
- package/dist/plan-LEJJF3DE.js +31 -0
- package/dist/{policy-XQW5NUIE.js → policy-JSYEK5B2.js} +17 -4
- package/dist/policy-JSYEK5B2.js.map +1 -0
- package/dist/pr-HPVUZ7S3.js +36 -0
- package/dist/pr-review-R2QZBT3F.js +29 -0
- package/dist/pr-review-R2QZBT3F.js.map +1 -0
- package/dist/prd-5O6GYCC6.js +30 -0
- package/dist/prd-5O6GYCC6.js.map +1 -0
- package/dist/ps-TNE44R5V.js +90 -0
- package/dist/ps-TNE44R5V.js.map +1 -0
- package/dist/recorder-XGF55WXI.js +31 -0
- package/dist/recorder-XGF55WXI.js.map +1 -0
- package/dist/registry-LGPE53QD.js +15 -0
- package/dist/registry-LGPE53QD.js.map +1 -0
- package/dist/resume-QMEPMSZW.js +238 -0
- package/dist/resume-QMEPMSZW.js.map +1 -0
- package/dist/review-YKWD6SNN.js +32 -0
- package/dist/review-YKWD6SNN.js.map +1 -0
- package/dist/routing-2ZUMZPJB.js +91 -0
- package/dist/routing-2ZUMZPJB.js.map +1 -0
- package/dist/run-YU4TR62R.js +50 -0
- package/dist/run-YU4TR62R.js.map +1 -0
- package/dist/state-manager-X3PT3FGT.js +36 -0
- package/dist/state-manager-X3PT3FGT.js.map +1 -0
- package/dist/usage-VCFLDA5Y.js +174 -0
- package/dist/usage-VCFLDA5Y.js.map +1 -0
- package/dist/{web-ANQQTTRD.js → web-XVHLX62B.js} +43 -27
- package/dist/web-XVHLX62B.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 +13 -6
- package/web/AGENTS.md +3 -3
- package/web/public/app.css +38 -0
- package/web/public/app.js +132 -10
- package/web/public/index.html +24 -0
- package/dist/analyze-XV3K25K3.js.map +0 -1
- package/dist/chunk-34WNTK3K.js.map +0 -1
- package/dist/chunk-3BOHTH4V.js +0 -58
- package/dist/chunk-3BOHTH4V.js.map +0 -1
- package/dist/chunk-47VIN33V.js.map +0 -1
- package/dist/chunk-6N7LZZ5U.js.map +0 -1
- package/dist/chunk-AAY6KM7N.js.map +0 -1
- package/dist/chunk-BXCPXRBR.js.map +0 -1
- package/dist/chunk-EWDJENFW.js +0 -303
- package/dist/chunk-EWDJENFW.js.map +0 -1
- package/dist/chunk-EY6WMHV2.js.map +0 -1
- package/dist/chunk-GANSDJV7.js.map +0 -1
- package/dist/chunk-HC2MT7BX.js.map +0 -1
- package/dist/chunk-HDV3YDTG.js +0 -52
- package/dist/chunk-HDV3YDTG.js.map +0 -1
- package/dist/chunk-IVHZEYAX.js.map +0 -1
- package/dist/chunk-KQ4JQN7T.js.map +0 -1
- package/dist/chunk-LVKQ2AKT.js.map +0 -1
- package/dist/chunk-OBLVLIUS.js.map +0 -1
- package/dist/chunk-RKTEV6EG.js.map +0 -1
- package/dist/chunk-VQ5VN7DF.js +0 -1018
- package/dist/chunk-VQ5VN7DF.js.map +0 -1
- package/dist/config-4THHOXNN.js +0 -41
- package/dist/execute-5OEKLM5X.js +0 -15
- package/dist/init-PRMOTQ7N.js +0 -9
- package/dist/plan-Y2BYZD24.js +0 -17
- package/dist/policy-XQW5NUIE.js.map +0 -1
- package/dist/pr-H6GLOSXF.js +0 -21
- package/dist/pr-review-CK5FR6WX.js +0 -17
- package/dist/prd-4PWLCGH5.js +0 -17
- package/dist/review-QGVAHEZF.js +0 -15
- package/dist/run-DBF2VWUN.js.map +0 -1
- package/dist/web-ANQQTTRD.js.map +0 -1
- /package/dist/{chunk-HQYXVIH6.js.map → chunk-MIVHK5YI.js.map} +0 -0
- /package/dist/{config-4THHOXNN.js.map → config-MEM2IWWN.js.map} +0 -0
- /package/dist/{execute-5OEKLM5X.js.map → contract-JH2WBIO6.js.map} +0 -0
- /package/dist/{init-PRMOTQ7N.js.map → execute-NITIHHCK.js.map} +0 -0
- /package/dist/{plan-Y2BYZD24.js.map → git-YRVRUN3C.js.map} +0 -0
- /package/dist/{pr-H6GLOSXF.js.map → init-OKWEC3EV.js.map} +0 -0
- /package/dist/{pr-review-CK5FR6WX.js.map → permissions-7NMDFU27.js.map} +0 -0
- /package/dist/{prd-4PWLCGH5.js.map → plan-LEJJF3DE.js.map} +0 -0
- /package/dist/{review-QGVAHEZF.js.map → pr-HPVUZ7S3.js.map} +0 -0
|
@@ -1,339 +1,18 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
docs: z.boolean().default(true),
|
|
9
|
-
codeowners: z.boolean().default(true),
|
|
10
|
-
labels: z.boolean().default(true),
|
|
11
|
-
issueTypes: z.boolean().default(true)
|
|
12
|
-
});
|
|
13
|
-
var policyIssuesDeclarationSchema = z.object({
|
|
14
|
-
titleConvention: z.string().min(1).optional(),
|
|
15
|
-
/**
|
|
16
|
-
* Whether Issue Flow may create a label the repository does not have.
|
|
17
|
-
*
|
|
18
|
-
* `.optional()` rather than `.default(false)`: the resolved declarations must
|
|
19
|
-
* stay "only what was written", or the group would always look declared and
|
|
20
|
-
* `sources` would report a provenance nobody asked for. The effective default
|
|
21
|
-
* — false — lives at the call site.
|
|
22
|
-
*
|
|
23
|
-
* That default is a deliberate change of behaviour: creating taxonomy without
|
|
24
|
-
* asking is the defect this exists to stop. A repository that wants the old
|
|
25
|
-
* behaviour opts back into it.
|
|
26
|
-
*/
|
|
27
|
-
allowLabelCreation: z.boolean().optional()
|
|
28
|
-
});
|
|
29
|
-
var policyPullRequestsDeclarationSchema = z.object({
|
|
30
|
-
baseBranch: z.string().min(1).optional(),
|
|
31
|
-
titleConvention: z.string().min(1).optional()
|
|
32
|
-
});
|
|
33
|
-
var policyGitDeclarationSchema = z.object({
|
|
34
|
-
branchConvention: z.string().min(1).optional(),
|
|
35
|
-
commitConvention: z.string().min(1).optional()
|
|
36
|
-
});
|
|
37
|
-
var policyConfigSchema = z.object({
|
|
38
|
-
enabled: z.boolean().default(true),
|
|
39
|
-
/**
|
|
40
|
-
* Token budget for the `__REPO_POLICY__` projection. Sections above it are
|
|
41
|
-
* replaced whole by a pointer rather than truncated — see
|
|
42
|
-
* `policy/placeholders.ts`.
|
|
43
|
-
*/
|
|
44
|
-
contextBudget: z.number().int().positive().default(1500),
|
|
45
|
-
discovery: policyDiscoveryConfigSchema.prefault({}),
|
|
46
|
-
issues: policyIssuesDeclarationSchema.prefault({}),
|
|
47
|
-
pullRequests: policyPullRequestsDeclarationSchema.prefault({}),
|
|
48
|
-
git: policyGitDeclarationSchema.prefault({})
|
|
49
|
-
});
|
|
50
|
-
var policyConfigInputSchema = z.object({
|
|
51
|
-
enabled: z.boolean().optional(),
|
|
52
|
-
contextBudget: z.number().int().positive().optional(),
|
|
53
|
-
// Spelled out rather than `policyDiscoveryConfigSchema.partial()`: in zod 4
|
|
54
|
-
// a `.default()` survives `.partial()`, so every toggle would come back
|
|
55
|
-
// materialized and the input layer would stop meaning "what the user wrote".
|
|
56
|
-
discovery: z.object({
|
|
57
|
-
issueTemplates: z.boolean().optional(),
|
|
58
|
-
pullRequestTemplate: z.boolean().optional(),
|
|
59
|
-
docs: z.boolean().optional(),
|
|
60
|
-
codeowners: z.boolean().optional(),
|
|
61
|
-
labels: z.boolean().optional(),
|
|
62
|
-
issueTypes: z.boolean().optional()
|
|
63
|
-
}).optional(),
|
|
64
|
-
issues: z.object({ titleConvention: z.string().nullish(), allowLabelCreation: z.boolean().optional() }).optional(),
|
|
65
|
-
pullRequests: z.object({ baseBranch: z.string().nullish(), titleConvention: z.string().nullish() }).optional(),
|
|
66
|
-
git: z.object({ branchConvention: z.string().nullish(), commitConvention: z.string().nullish() }).optional()
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
// src/schemas.ts
|
|
70
|
-
import { z as z2 } from "zod";
|
|
71
|
-
var claudeUsageSchema = z2.object({
|
|
72
|
-
inputTokens: z2.number().optional(),
|
|
73
|
-
outputTokens: z2.number().optional(),
|
|
74
|
-
cacheReadTokens: z2.number().optional(),
|
|
75
|
-
cacheCreationTokens: z2.number().optional(),
|
|
76
|
-
costUsd: z2.number().optional()
|
|
77
|
-
});
|
|
78
|
-
var userStoryStatusSchema = z2.enum(["backlog", "in_progress", "in_review", "done"]);
|
|
79
|
-
var storyStageSchema = z2.enum([
|
|
80
|
-
"pending",
|
|
81
|
-
"executing",
|
|
82
|
-
"awaiting_review",
|
|
83
|
-
"in_review",
|
|
84
|
-
"in_correction",
|
|
85
|
-
"done",
|
|
86
|
-
"failed"
|
|
87
|
-
]);
|
|
88
|
-
var userStorySchema = z2.object({
|
|
89
|
-
id: z2.string(),
|
|
90
|
-
title: z2.string(),
|
|
91
|
-
description: z2.string(),
|
|
92
|
-
acceptanceCriteria: z2.array(z2.string()),
|
|
93
|
-
priority: z2.number().int().positive(),
|
|
94
|
-
passes: z2.boolean(),
|
|
95
|
-
notes: z2.string(),
|
|
96
|
-
...claudeUsageSchema.shape,
|
|
97
|
-
durationSeconds: z2.number().optional(),
|
|
98
|
-
status: userStoryStatusSchema.optional(),
|
|
99
|
-
dependencies: z2.array(z2.string()).optional(),
|
|
100
|
-
stage: storyStageSchema.optional(),
|
|
101
|
-
stageSince: z2.string().optional(),
|
|
102
|
-
stageDetail: z2.string().optional()
|
|
103
|
-
});
|
|
104
|
-
var pipelineStateSchema = z2.object({
|
|
105
|
-
analyzeCompleted: z2.boolean().optional(),
|
|
106
|
-
prdCompleted: z2.boolean(),
|
|
107
|
-
jsonCompleted: z2.boolean(),
|
|
108
|
-
executionCompleted: z2.boolean(),
|
|
109
|
-
reviewCompleted: z2.boolean(),
|
|
110
|
-
prCreated: z2.boolean(),
|
|
111
|
-
prReviewCompleted: z2.boolean().optional()
|
|
112
|
-
});
|
|
113
|
-
var pullRequestRefSchema = z2.object({
|
|
114
|
-
number: z2.number().int().positive(),
|
|
115
|
-
url: z2.string(),
|
|
116
|
-
headBranch: z2.string(),
|
|
117
|
-
createdAt: z2.string()
|
|
118
|
-
});
|
|
119
|
-
var prReviewRecommendationSchema = z2.enum([
|
|
120
|
-
"APPROVE",
|
|
121
|
-
"APPROVE_WITH_SUGGESTIONS",
|
|
122
|
-
"REQUEST_CHANGES"
|
|
123
|
-
]);
|
|
124
|
-
var prReviewStateSchema = z2.object({
|
|
125
|
-
enabled: z2.boolean().default(false),
|
|
126
|
-
pullRequestNumber: z2.number().int().positive().optional(),
|
|
127
|
-
rounds: z2.number().int().min(0).default(0),
|
|
128
|
-
lastRecommendation: prReviewRecommendationSchema.optional(),
|
|
129
|
-
lastReviewedAt: z2.string().optional()
|
|
130
|
-
});
|
|
131
|
-
var lastErrorSchema = z2.object({
|
|
132
|
-
category: z2.string(),
|
|
133
|
-
message: z2.string(),
|
|
134
|
-
at: z2.string()
|
|
135
|
-
});
|
|
136
|
-
var issueMetadataSchema = z2.object({
|
|
137
|
-
schemaVersion: z2.literal(1),
|
|
138
|
-
id: z2.string().min(1),
|
|
139
|
-
number: z2.number().int().positive().nullable(),
|
|
140
|
-
source: z2.enum(["github", "local"]),
|
|
141
|
-
title: z2.string(),
|
|
142
|
-
labels: z2.array(z2.string()),
|
|
143
|
-
state: z2.enum(["open", "closed"]),
|
|
144
|
-
createdAt: z2.string(),
|
|
145
|
-
updatedAt: z2.string(),
|
|
146
|
-
contentHash: z2.string(),
|
|
147
|
-
remote: z2.object({
|
|
148
|
-
provider: z2.enum(["github", "local"]),
|
|
149
|
-
ref: z2.string(),
|
|
150
|
-
syncedAt: z2.string(),
|
|
151
|
-
syncedContentHash: z2.string()
|
|
152
|
-
}).optional()
|
|
153
|
-
});
|
|
154
|
-
var taskPlanSchema = z2.object({
|
|
155
|
-
project: z2.string(),
|
|
156
|
-
issueNumber: z2.union([z2.number().int().positive(), z2.string().min(1)]),
|
|
157
|
-
issueUrl: z2.string().optional().default(""),
|
|
158
|
-
branchName: z2.string(),
|
|
159
|
-
noBranch: z2.boolean().optional().default(false),
|
|
160
|
-
description: z2.string(),
|
|
161
|
-
issueStatus: z2.enum(["pending", "in_progress", "completed"]),
|
|
162
|
-
completedAt: z2.string().nullable(),
|
|
163
|
-
lastAttemptAt: z2.string().nullable(),
|
|
164
|
-
lastError: lastErrorSchema.nullable(),
|
|
165
|
-
correctionCycle: z2.number().int().min(0),
|
|
166
|
-
maxCorrectionCycles: z2.number().int().min(0),
|
|
167
|
-
/**
|
|
168
|
-
* Findings from the most recent failed review, verbatim. Non-null means the
|
|
169
|
-
* issue has a pending correction even if every userStories[].passes is
|
|
170
|
-
* already true — the execute phase must address these before the field is
|
|
171
|
-
* cleared back to null. See core/engine.ts's early-return guards.
|
|
172
|
-
*/
|
|
173
|
-
lastReviewFindings: z2.string().nullable().optional().default(null),
|
|
174
|
-
pipeline: pipelineStateSchema,
|
|
175
|
-
pullRequest: pullRequestRefSchema.optional(),
|
|
176
|
-
prReview: prReviewStateSchema.optional(),
|
|
177
|
-
userStories: z2.array(userStorySchema)
|
|
178
|
-
});
|
|
179
|
-
var headlessResultSchema = z2.object({
|
|
180
|
-
success: z2.boolean(),
|
|
181
|
-
result: z2.string(),
|
|
182
|
-
cost: claudeUsageSchema.nullable(),
|
|
183
|
-
error: z2.string().nullable()
|
|
184
|
-
});
|
|
185
|
-
var sessionLogEntrySchema = z2.object({
|
|
186
|
-
at: z2.string(),
|
|
187
|
-
level: z2.enum(["info", "warn", "error"]),
|
|
188
|
-
message: z2.string()
|
|
189
|
-
});
|
|
190
|
-
var sessionUsageShape = {
|
|
191
|
-
inputTokens: z2.number().nullable().default(null),
|
|
192
|
-
outputTokens: z2.number().nullable().default(null),
|
|
193
|
-
cacheReadTokens: z2.number().nullable().default(null),
|
|
194
|
-
cacheCreationTokens: z2.number().nullable().default(null),
|
|
195
|
-
costUsd: z2.number().nullable().default(null)
|
|
196
|
-
};
|
|
197
|
-
var sessionPhaseSchema = z2.object({
|
|
198
|
-
name: z2.string(),
|
|
199
|
-
status: z2.enum(["pending", "running", "completed", "failed"]),
|
|
200
|
-
startedAt: z2.string().nullable(),
|
|
201
|
-
endedAt: z2.string().nullable(),
|
|
202
|
-
durationSeconds: z2.number().nullable(),
|
|
203
|
-
error: z2.string().nullable(),
|
|
204
|
-
...sessionUsageShape
|
|
205
|
-
});
|
|
206
|
-
var sessionStorySchema = z2.object({
|
|
207
|
-
id: z2.string(),
|
|
208
|
-
title: z2.string(),
|
|
209
|
-
priority: z2.number(),
|
|
210
|
-
passes: z2.boolean(),
|
|
211
|
-
completedAt: z2.string().nullable(),
|
|
212
|
-
// Also introduced with the metrics, hence the same tolerant default.
|
|
213
|
-
durationSeconds: z2.number().nullable().default(null),
|
|
214
|
-
// Snapshot fields are always present on output and defaulted on input, so a
|
|
215
|
-
// session.json written before they existed still parses. This is the mirror
|
|
216
|
-
// image of userStorySchema, where the same two fields are plainly optional.
|
|
217
|
-
status: userStoryStatusSchema.default("backlog"),
|
|
218
|
-
dependencies: z2.array(z2.string()).default([]),
|
|
219
|
-
// Published for the panel's story detail view. Same tolerant default as the
|
|
220
|
-
// fields above: absent (older session.json) and empty resolve to the same
|
|
221
|
-
// value, so the client never has to tell them apart.
|
|
222
|
-
description: z2.string().default(""),
|
|
223
|
-
acceptanceCriteria: z2.array(z2.string()).default([]),
|
|
224
|
-
// Additive like the rest of this schema: a session.json written before
|
|
225
|
-
// `stage` existed parses into 'pending'/null, the same values a fresh
|
|
226
|
-
// snapshot starts a story at.
|
|
227
|
-
stage: storyStageSchema.default("pending"),
|
|
228
|
-
stageSince: z2.string().nullable().default(null),
|
|
229
|
-
stageDetail: z2.string().nullable().default(null),
|
|
230
|
-
...sessionUsageShape
|
|
231
|
-
});
|
|
232
|
-
var sessionSnapshotSchema = z2.object({
|
|
233
|
-
schemaVersion: z2.literal(1),
|
|
234
|
-
sessionId: z2.string().nullable(),
|
|
235
|
-
readOnly: z2.literal(true),
|
|
236
|
-
capabilities: z2.array(z2.string()),
|
|
237
|
-
issue: z2.object({
|
|
238
|
-
number: z2.number().nullable(),
|
|
239
|
-
url: z2.string().nullable(),
|
|
240
|
-
// Additive: a session.json written before the Issue section was enriched
|
|
241
|
-
// parses into the same "not reported" values createInitialSnapshot() uses.
|
|
242
|
-
title: z2.string().nullable().default(null),
|
|
243
|
-
description: z2.string().nullable().default(null),
|
|
244
|
-
labels: z2.array(z2.string()).default([]),
|
|
245
|
-
state: z2.string().nullable().default(null)
|
|
246
|
-
}),
|
|
247
|
-
status: z2.enum(["idle", "running", "completed", "failed"]),
|
|
248
|
-
startedAt: z2.string().nullable(),
|
|
249
|
-
updatedAt: z2.string().nullable(),
|
|
250
|
-
endedAt: z2.string().nullable(),
|
|
251
|
-
elapsedSeconds: z2.number().nullable(),
|
|
252
|
-
estimatedRemainingSeconds: z2.number().nullable(),
|
|
253
|
-
progress: z2.object({
|
|
254
|
-
percent: z2.number(),
|
|
255
|
-
phasesCompleted: z2.number(),
|
|
256
|
-
phasesTotal: z2.number(),
|
|
257
|
-
storiesCompleted: z2.number(),
|
|
258
|
-
storiesTotal: z2.number()
|
|
259
|
-
}),
|
|
260
|
-
currentPhase: z2.string().nullable(),
|
|
261
|
-
currentActivity: z2.object({
|
|
262
|
-
story: z2.string().nullable(),
|
|
263
|
-
tool: z2.string().nullable(),
|
|
264
|
-
detail: z2.string().nullable(),
|
|
265
|
-
since: z2.string()
|
|
266
|
-
}).nullable(),
|
|
267
|
-
phases: z2.array(sessionPhaseSchema),
|
|
268
|
-
stories: z2.array(sessionStorySchema),
|
|
269
|
-
// The whole aggregate is additive: a snapshot from before it existed parses
|
|
270
|
-
// into the same "nothing reported" object the reducer starts from.
|
|
271
|
-
metrics: z2.object({
|
|
272
|
-
totalInputTokens: z2.number().nullable().default(null),
|
|
273
|
-
totalOutputTokens: z2.number().nullable().default(null),
|
|
274
|
-
totalCacheReadTokens: z2.number().nullable().default(null),
|
|
275
|
-
totalCacheCreationTokens: z2.number().nullable().default(null),
|
|
276
|
-
totalCostUsd: z2.number().nullable().default(null)
|
|
277
|
-
}).default({
|
|
278
|
-
totalInputTokens: null,
|
|
279
|
-
totalOutputTokens: null,
|
|
280
|
-
totalCacheReadTokens: null,
|
|
281
|
-
totalCacheCreationTokens: null,
|
|
282
|
-
totalCostUsd: null
|
|
283
|
-
}),
|
|
284
|
-
execution: z2.object({
|
|
285
|
-
iteration: z2.number(),
|
|
286
|
-
retries: z2.number(),
|
|
287
|
-
correctionCycle: z2.number(),
|
|
288
|
-
maxCorrectionCycles: z2.number().nullable()
|
|
289
|
-
}),
|
|
290
|
-
git: z2.object({
|
|
291
|
-
branch: z2.string().nullable(),
|
|
292
|
-
baseBranch: z2.string().nullable(),
|
|
293
|
-
commits: z2.array(z2.object({ hash: z2.string(), subject: z2.string() }))
|
|
294
|
-
}),
|
|
295
|
-
// Additive like the metrics aggregate: a session.json written before the
|
|
296
|
-
// repository section existed parses into the same all-null object
|
|
297
|
-
// createInitialSnapshot() starts from.
|
|
298
|
-
repository: z2.object({
|
|
299
|
-
name: z2.string().nullable().default(null),
|
|
300
|
-
remoteUrl: z2.string().nullable().default(null),
|
|
301
|
-
branch: z2.string().nullable().default(null),
|
|
302
|
-
headCommit: z2.string().nullable().default(null),
|
|
303
|
-
root: z2.string().nullable().default(null)
|
|
304
|
-
}).default({ name: null, remoteUrl: null, branch: null, headCommit: null, root: null }),
|
|
305
|
-
pullRequests: z2.array(z2.object({ number: z2.number(), url: z2.string(), title: z2.string() })),
|
|
306
|
-
logs: z2.array(sessionLogEntrySchema),
|
|
307
|
-
errors: z2.array(sessionLogEntrySchema),
|
|
308
|
-
warnings: z2.array(sessionLogEntrySchema),
|
|
309
|
-
lastError: z2.object({ message: z2.string(), at: z2.string() }).nullable(),
|
|
310
|
-
nextSteps: z2.array(z2.string()),
|
|
311
|
-
environment: z2.object({ node: z2.string(), platform: z2.string() }).nullable()
|
|
312
|
-
});
|
|
313
|
-
var webConfigSchema = z2.object({
|
|
314
|
-
enabled: z2.boolean().default(false),
|
|
315
|
-
port: z2.number().int().min(1).max(65535).default(3737),
|
|
316
|
-
host: z2.string().min(1).default("0.0.0.0"),
|
|
317
|
-
refreshSeconds: z2.number().positive().default(5),
|
|
318
|
-
logLimit: z2.number().int().positive().default(200),
|
|
319
|
-
includeLogs: z2.boolean().default(true)
|
|
320
|
-
});
|
|
321
|
-
var issuesConfigSchema = z2.object({
|
|
322
|
-
defaultGenerateTarget: z2.enum(["github", "local", "both"]).default("github"),
|
|
323
|
-
preferredProvider: z2.enum(["github", "local"]).default("github"),
|
|
324
|
-
conflictPolicy: z2.enum(["ask", "prefer-local", "prefer-github"]).default("ask"),
|
|
325
|
-
requireConfirmation: z2.boolean().default(true)
|
|
326
|
-
});
|
|
327
|
-
var prReviewConfigSchema = z2.object({
|
|
328
|
-
publisher: z2.enum(["local"]).default("local")
|
|
329
|
-
});
|
|
2
|
+
import {
|
|
3
|
+
setTelemetrySessionId
|
|
4
|
+
} from "./chunk-P3LRUNC6.js";
|
|
5
|
+
import {
|
|
6
|
+
isoNow
|
|
7
|
+
} from "./chunk-DIG5XKQQ.js";
|
|
330
8
|
|
|
331
9
|
// src/core/session-state.ts
|
|
332
|
-
import { mkdir, rename, writeFile } from "fs/promises";
|
|
10
|
+
import { mkdir, rename, utimes, writeFile } from "fs/promises";
|
|
333
11
|
import { dirname } from "path";
|
|
334
12
|
import { stripVTControlCharacters } from "util";
|
|
335
13
|
var DEFAULT_LOG_LIMIT = 200;
|
|
336
14
|
var DEFAULT_THROTTLE_MS = 1e3;
|
|
15
|
+
var DEFAULT_SESSION_HEARTBEAT_MS = 1e4;
|
|
337
16
|
function emptyUsage() {
|
|
338
17
|
return {
|
|
339
18
|
inputTokens: null,
|
|
@@ -343,6 +22,16 @@ function emptyUsage() {
|
|
|
343
22
|
costUsd: null
|
|
344
23
|
};
|
|
345
24
|
}
|
|
25
|
+
function emptyPhaseTiming() {
|
|
26
|
+
return {
|
|
27
|
+
harnessExecutionMs: null,
|
|
28
|
+
orchestrationOverheadMs: null,
|
|
29
|
+
harnessStartupMs: null,
|
|
30
|
+
ttftMs: null,
|
|
31
|
+
attemptCount: null,
|
|
32
|
+
retryDurationMs: null
|
|
33
|
+
};
|
|
34
|
+
}
|
|
346
35
|
function emptyMetrics() {
|
|
347
36
|
return {
|
|
348
37
|
totalInputTokens: null,
|
|
@@ -378,6 +67,14 @@ function createInitialSnapshot() {
|
|
|
378
67
|
stories: [],
|
|
379
68
|
metrics: emptyMetrics(),
|
|
380
69
|
execution: { iteration: 0, retries: 0, correctionCycle: 0, maxCorrectionCycles: null },
|
|
70
|
+
resilience: {
|
|
71
|
+
attempt: 0,
|
|
72
|
+
provider: null,
|
|
73
|
+
model: null,
|
|
74
|
+
lastFailureKind: null,
|
|
75
|
+
cooldownUntil: null,
|
|
76
|
+
lastActivityAt: null
|
|
77
|
+
},
|
|
381
78
|
git: { branch: null, baseBranch: null, commits: [] },
|
|
382
79
|
repository: { name: null, remoteUrl: null, branch: null, headCommit: null, root: null },
|
|
383
80
|
pullRequests: [],
|
|
@@ -386,7 +83,8 @@ function createInitialSnapshot() {
|
|
|
386
83
|
warnings: [],
|
|
387
84
|
lastError: null,
|
|
388
85
|
nextSteps: [],
|
|
389
|
-
environment: null
|
|
86
|
+
environment: null,
|
|
87
|
+
verification: null
|
|
390
88
|
};
|
|
391
89
|
}
|
|
392
90
|
function accumulate(current, delta) {
|
|
@@ -481,6 +179,7 @@ function deriveStageOnStoriesUpdate(story, before, at) {
|
|
|
481
179
|
function applyEvent(snapshot, event, options) {
|
|
482
180
|
switch (event.type) {
|
|
483
181
|
case "session:start": {
|
|
182
|
+
setTelemetrySessionId(event.sessionId);
|
|
484
183
|
const initial = createInitialSnapshot();
|
|
485
184
|
return {
|
|
486
185
|
...initial,
|
|
@@ -499,6 +198,7 @@ function applyEvent(snapshot, event, options) {
|
|
|
499
198
|
endedAt: null,
|
|
500
199
|
durationSeconds: null,
|
|
501
200
|
error: null,
|
|
201
|
+
...emptyPhaseTiming(),
|
|
502
202
|
...emptyUsage()
|
|
503
203
|
})),
|
|
504
204
|
git: { branch: event.branch ?? null, baseBranch: event.baseBranch ?? null, commits: [] },
|
|
@@ -507,7 +207,12 @@ function applyEvent(snapshot, event, options) {
|
|
|
507
207
|
// keeps git.branch and repository.branch consistent for a poll that
|
|
508
208
|
// lands before the first git:update.
|
|
509
209
|
repository: { ...initial.repository, branch: event.branch ?? null },
|
|
510
|
-
environment: event.environment
|
|
210
|
+
environment: event.environment ? {
|
|
211
|
+
node: event.environment.node,
|
|
212
|
+
platform: event.environment.platform,
|
|
213
|
+
agent: event.environment.agent ?? null,
|
|
214
|
+
model: event.environment.model ?? null
|
|
215
|
+
} : null
|
|
511
216
|
};
|
|
512
217
|
}
|
|
513
218
|
case "issue:update":
|
|
@@ -545,6 +250,7 @@ function applyEvent(snapshot, event, options) {
|
|
|
545
250
|
endedAt: null,
|
|
546
251
|
durationSeconds: null,
|
|
547
252
|
error: null,
|
|
253
|
+
...emptyPhaseTiming(),
|
|
548
254
|
...emptyUsage()
|
|
549
255
|
}
|
|
550
256
|
];
|
|
@@ -566,7 +272,13 @@ function applyEvent(snapshot, event, options) {
|
|
|
566
272
|
status: event.success ? "completed" : "failed",
|
|
567
273
|
endedAt: event.at,
|
|
568
274
|
durationSeconds: secondsBetween(p.startedAt, event.at),
|
|
569
|
-
error: event.error ? stripVTControlCharacters(event.error) : null
|
|
275
|
+
error: event.error ? stripVTControlCharacters(event.error) : null,
|
|
276
|
+
harnessExecutionMs: event.harnessExecutionMs ?? p.harnessExecutionMs,
|
|
277
|
+
orchestrationOverheadMs: event.orchestrationOverheadMs ?? p.orchestrationOverheadMs,
|
|
278
|
+
harnessStartupMs: event.harnessStartupMs ?? p.harnessStartupMs,
|
|
279
|
+
ttftMs: event.ttftMs ?? p.ttftMs,
|
|
280
|
+
attemptCount: event.attemptCount ?? p.attemptCount,
|
|
281
|
+
retryDurationMs: event.retryDurationMs ?? p.retryDurationMs
|
|
570
282
|
} : p
|
|
571
283
|
);
|
|
572
284
|
const phasesCompleted = phases.filter((p) => p.status === "completed").length;
|
|
@@ -616,6 +328,48 @@ function applyEvent(snapshot, event, options) {
|
|
|
616
328
|
...snapshot,
|
|
617
329
|
execution: { ...snapshot.execution, retries: snapshot.execution.retries + 1 }
|
|
618
330
|
};
|
|
331
|
+
case "agent:attempt":
|
|
332
|
+
return {
|
|
333
|
+
...snapshot,
|
|
334
|
+
resilience: {
|
|
335
|
+
...snapshot.resilience,
|
|
336
|
+
attempt: event.attempt,
|
|
337
|
+
provider: event.provider,
|
|
338
|
+
model: event.model ?? null,
|
|
339
|
+
lastActivityAt: event.at
|
|
340
|
+
}
|
|
341
|
+
};
|
|
342
|
+
case "failover":
|
|
343
|
+
return {
|
|
344
|
+
...snapshot,
|
|
345
|
+
resilience: {
|
|
346
|
+
...snapshot.resilience,
|
|
347
|
+
provider: event.to,
|
|
348
|
+
lastFailureKind: event.reason,
|
|
349
|
+
cooldownUntil: event.cooldownUntil ?? null,
|
|
350
|
+
lastActivityAt: event.at
|
|
351
|
+
}
|
|
352
|
+
};
|
|
353
|
+
case "agent:result":
|
|
354
|
+
return {
|
|
355
|
+
...snapshot,
|
|
356
|
+
resilience: {
|
|
357
|
+
...snapshot.resilience,
|
|
358
|
+
provider: event.provider,
|
|
359
|
+
lastFailureKind: event.failureKind ?? snapshot.resilience.lastFailureKind,
|
|
360
|
+
cooldownUntil: event.cooldownUntil ?? null,
|
|
361
|
+
lastActivityAt: event.at
|
|
362
|
+
}
|
|
363
|
+
};
|
|
364
|
+
case "agent:activity":
|
|
365
|
+
return {
|
|
366
|
+
...snapshot,
|
|
367
|
+
resilience: {
|
|
368
|
+
...snapshot.resilience,
|
|
369
|
+
provider: event.provider,
|
|
370
|
+
lastActivityAt: event.at
|
|
371
|
+
}
|
|
372
|
+
};
|
|
619
373
|
case "stories:update": {
|
|
620
374
|
const previous = new Map(snapshot.stories.map((story) => [story.id, story]));
|
|
621
375
|
const stories = event.stories.map((story) => {
|
|
@@ -662,7 +416,11 @@ function applyEvent(snapshot, event, options) {
|
|
|
662
416
|
const detail = event.detail ?? null;
|
|
663
417
|
const current = snapshot.currentActivity;
|
|
664
418
|
const since = current && current.story === story && current.tool === tool && current.detail === detail ? current.since : event.at;
|
|
665
|
-
return {
|
|
419
|
+
return {
|
|
420
|
+
...snapshot,
|
|
421
|
+
currentActivity: { story, tool, detail, since },
|
|
422
|
+
resilience: { ...snapshot.resilience, lastActivityAt: event.at }
|
|
423
|
+
};
|
|
666
424
|
}
|
|
667
425
|
case "log": {
|
|
668
426
|
const limit = options?.logLimit ?? DEFAULT_LOG_LIMIT;
|
|
@@ -746,6 +504,15 @@ function applyEvent(snapshot, event, options) {
|
|
|
746
504
|
}
|
|
747
505
|
};
|
|
748
506
|
}
|
|
507
|
+
case "verify:end":
|
|
508
|
+
return {
|
|
509
|
+
...snapshot,
|
|
510
|
+
verification: {
|
|
511
|
+
verdict: event.verdict,
|
|
512
|
+
level: event.level,
|
|
513
|
+
independence: event.independence
|
|
514
|
+
}
|
|
515
|
+
};
|
|
749
516
|
case "session:end":
|
|
750
517
|
return {
|
|
751
518
|
...snapshot,
|
|
@@ -835,6 +602,7 @@ var FilePublisher = class extends MemoryPublisher {
|
|
|
835
602
|
filePath;
|
|
836
603
|
throttleMs;
|
|
837
604
|
timer = null;
|
|
605
|
+
heartbeatTimer = null;
|
|
838
606
|
lastWriteStartedAt = 0;
|
|
839
607
|
lastWrittenVersion = 0;
|
|
840
608
|
writeChain = Promise.resolve();
|
|
@@ -843,10 +611,15 @@ var FilePublisher = class extends MemoryPublisher {
|
|
|
843
611
|
super(options);
|
|
844
612
|
this.filePath = filePath;
|
|
845
613
|
this.throttleMs = options.throttleMs ?? DEFAULT_THROTTLE_MS;
|
|
614
|
+
const heartbeatMs = options.heartbeatMs ?? DEFAULT_SESSION_HEARTBEAT_MS;
|
|
615
|
+
if (heartbeatMs > 0) {
|
|
616
|
+
this.heartbeatTimer = setInterval(() => this.enqueueHeartbeat(), heartbeatMs);
|
|
617
|
+
this.heartbeatTimer.unref();
|
|
618
|
+
}
|
|
846
619
|
}
|
|
847
620
|
afterPublish(event) {
|
|
848
621
|
if (this.closed) return;
|
|
849
|
-
const terminal = event.type === "phase:end" || event.type === "session:end";
|
|
622
|
+
const terminal = event.type === "phase:end" || event.type === "session:end" || event.type === "verify:end";
|
|
850
623
|
this.scheduleWrite(terminal);
|
|
851
624
|
}
|
|
852
625
|
scheduleWrite(force) {
|
|
@@ -885,6 +658,24 @@ var FilePublisher = class extends MemoryPublisher {
|
|
|
885
658
|
}
|
|
886
659
|
});
|
|
887
660
|
}
|
|
661
|
+
/**
|
|
662
|
+
* Keep directory-based discovery alive without changing snapshot content or
|
|
663
|
+
* its content-derived ETag. The write chain serializes the touch with atomic
|
|
664
|
+
* snapshot replacement, and no heartbeat is attempted before the first file
|
|
665
|
+
* has been written successfully.
|
|
666
|
+
*/
|
|
667
|
+
enqueueHeartbeat() {
|
|
668
|
+
if (this.closed) return;
|
|
669
|
+
this.writeChain = this.writeChain.then(async () => {
|
|
670
|
+
if (this.closed || this.lastWrittenVersion === 0) return;
|
|
671
|
+
const now = /* @__PURE__ */ new Date();
|
|
672
|
+
try {
|
|
673
|
+
await utimes(this.filePath, now, now);
|
|
674
|
+
} catch (err) {
|
|
675
|
+
this.warnOnce(err);
|
|
676
|
+
}
|
|
677
|
+
});
|
|
678
|
+
}
|
|
888
679
|
async flush() {
|
|
889
680
|
if (this.timer !== null) {
|
|
890
681
|
clearTimeout(this.timer);
|
|
@@ -896,8 +687,12 @@ var FilePublisher = class extends MemoryPublisher {
|
|
|
896
687
|
await this.writeChain;
|
|
897
688
|
}
|
|
898
689
|
async close() {
|
|
899
|
-
|
|
690
|
+
if (this.heartbeatTimer !== null) {
|
|
691
|
+
clearInterval(this.heartbeatTimer);
|
|
692
|
+
this.heartbeatTimer = null;
|
|
693
|
+
}
|
|
900
694
|
this.closed = true;
|
|
695
|
+
await this.flush();
|
|
901
696
|
}
|
|
902
697
|
};
|
|
903
698
|
async function atomicWriteFile(path, content) {
|
|
@@ -917,230 +712,6 @@ function getSessionPublisher() {
|
|
|
917
712
|
return _publisher;
|
|
918
713
|
}
|
|
919
714
|
|
|
920
|
-
// src/core/state-manager.ts
|
|
921
|
-
import { readFile } from "fs/promises";
|
|
922
|
-
import { ZodError } from "zod";
|
|
923
|
-
|
|
924
|
-
// src/utils/fs.ts
|
|
925
|
-
import { copyFile, mkdtemp, rename as rename2, unlink, writeFile as writeFile2 } from "fs/promises";
|
|
926
|
-
import { tmpdir } from "os";
|
|
927
|
-
import { basename, join } from "path";
|
|
928
|
-
async function writeFileAtomic(path, content) {
|
|
929
|
-
const tmpDir = await mkdtemp(join(tmpdir(), "issue-flow-"));
|
|
930
|
-
const tmpFile = join(tmpDir, basename(path));
|
|
931
|
-
await writeFile2(tmpFile, content, "utf-8");
|
|
932
|
-
try {
|
|
933
|
-
await rename2(tmpFile, path);
|
|
934
|
-
} catch (err) {
|
|
935
|
-
if (err.code === "EXDEV") {
|
|
936
|
-
await copyFile(tmpFile, path);
|
|
937
|
-
await unlink(tmpFile);
|
|
938
|
-
} else {
|
|
939
|
-
throw err;
|
|
940
|
-
}
|
|
941
|
-
}
|
|
942
|
-
}
|
|
943
|
-
|
|
944
|
-
// src/core/metrics.ts
|
|
945
|
-
var USAGE_FIELDS = [
|
|
946
|
-
"inputTokens",
|
|
947
|
-
"outputTokens",
|
|
948
|
-
"cacheReadTokens",
|
|
949
|
-
"cacheCreationTokens",
|
|
950
|
-
"costUsd"
|
|
951
|
-
];
|
|
952
|
-
function num(value) {
|
|
953
|
-
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
954
|
-
}
|
|
955
|
-
function isRecord(value) {
|
|
956
|
-
return typeof value === "object" && value !== null;
|
|
957
|
-
}
|
|
958
|
-
function parseUsage(payload) {
|
|
959
|
-
if (!isRecord(payload)) return null;
|
|
960
|
-
const usageRaw = isRecord(payload.usage) ? payload.usage : void 0;
|
|
961
|
-
const usage = {};
|
|
962
|
-
const inputTokens = usageRaw ? num(usageRaw.input_tokens) : void 0;
|
|
963
|
-
const outputTokens = usageRaw ? num(usageRaw.output_tokens) : void 0;
|
|
964
|
-
const cacheReadTokens = usageRaw ? num(usageRaw.cache_read_input_tokens) : void 0;
|
|
965
|
-
const cacheCreationTokens = usageRaw ? num(usageRaw.cache_creation_input_tokens) : void 0;
|
|
966
|
-
const costUsd = num(payload.total_cost_usd);
|
|
967
|
-
const legacyInput = num(payload.num_input_tokens);
|
|
968
|
-
const legacyOutput = num(payload.num_output_tokens);
|
|
969
|
-
const legacyCost = num(payload.cost_usd);
|
|
970
|
-
const resolvedInput = inputTokens ?? legacyInput;
|
|
971
|
-
const resolvedOutput = outputTokens ?? legacyOutput;
|
|
972
|
-
const resolvedCost = costUsd ?? legacyCost;
|
|
973
|
-
if (resolvedInput !== void 0) usage.inputTokens = resolvedInput;
|
|
974
|
-
if (resolvedOutput !== void 0) usage.outputTokens = resolvedOutput;
|
|
975
|
-
if (cacheReadTokens !== void 0) usage.cacheReadTokens = cacheReadTokens;
|
|
976
|
-
if (cacheCreationTokens !== void 0) usage.cacheCreationTokens = cacheCreationTokens;
|
|
977
|
-
if (resolvedCost !== void 0) usage.costUsd = resolvedCost;
|
|
978
|
-
return Object.keys(usage).length > 0 ? usage : null;
|
|
979
|
-
}
|
|
980
|
-
function sumUsage(a, b) {
|
|
981
|
-
const result = {};
|
|
982
|
-
for (const field of USAGE_FIELDS) {
|
|
983
|
-
const left = a?.[field];
|
|
984
|
-
const right = b?.[field];
|
|
985
|
-
if (left === void 0 && right === void 0) continue;
|
|
986
|
-
result[field] = (left ?? 0) + (right ?? 0);
|
|
987
|
-
}
|
|
988
|
-
return result;
|
|
989
|
-
}
|
|
990
|
-
function divideUsage(usage, parts) {
|
|
991
|
-
const result = {};
|
|
992
|
-
if (!usage) return result;
|
|
993
|
-
const divisor = Number.isFinite(parts) && parts > 1 ? parts : 1;
|
|
994
|
-
for (const field of USAGE_FIELDS) {
|
|
995
|
-
const value = usage[field];
|
|
996
|
-
if (value === void 0) continue;
|
|
997
|
-
result[field] = field === "costUsd" ? value / divisor : Math.round(value / divisor);
|
|
998
|
-
}
|
|
999
|
-
return result;
|
|
1000
|
-
}
|
|
1001
|
-
function compactTokens(value) {
|
|
1002
|
-
const abs = Math.abs(value);
|
|
1003
|
-
if (abs >= 1e6) return `${(value / 1e6).toFixed(1)}M`;
|
|
1004
|
-
if (abs >= 1e3) return `${(value / 1e3).toFixed(1)}k`;
|
|
1005
|
-
return String(Math.round(value));
|
|
1006
|
-
}
|
|
1007
|
-
function formatTokens(usage) {
|
|
1008
|
-
if (!usage) return "";
|
|
1009
|
-
const segments = [];
|
|
1010
|
-
const io = [];
|
|
1011
|
-
if (usage.inputTokens !== void 0) io.push(`${compactTokens(usage.inputTokens)} in`);
|
|
1012
|
-
if (usage.outputTokens !== void 0) io.push(`${compactTokens(usage.outputTokens)} out`);
|
|
1013
|
-
if (io.length > 0) segments.push(io.join(" / "));
|
|
1014
|
-
const cache = usage.cacheReadTokens !== void 0 || usage.cacheCreationTokens !== void 0 ? (usage.cacheReadTokens ?? 0) + (usage.cacheCreationTokens ?? 0) : void 0;
|
|
1015
|
-
if (cache !== void 0) segments.push(`${compactTokens(cache)} cache`);
|
|
1016
|
-
if (usage.costUsd !== void 0) segments.push(`~$${usage.costUsd.toFixed(4)}`);
|
|
1017
|
-
return segments.join(" \xB7 ");
|
|
1018
|
-
}
|
|
1019
|
-
function hasUsageData(usage) {
|
|
1020
|
-
if (!usage) return false;
|
|
1021
|
-
return USAGE_FIELDS.some((field) => usage[field] !== void 0);
|
|
1022
|
-
}
|
|
1023
|
-
|
|
1024
|
-
// src/core/state-manager.ts
|
|
1025
|
-
function isoNow() {
|
|
1026
|
-
return (/* @__PURE__ */ new Date()).toISOString().replace(/\.\d{3}Z$/, "Z");
|
|
1027
|
-
}
|
|
1028
|
-
async function loadTaskPlan(path) {
|
|
1029
|
-
const content = await readFile(path, "utf-8");
|
|
1030
|
-
const raw = JSON.parse(content);
|
|
1031
|
-
try {
|
|
1032
|
-
return taskPlanSchema.parse(raw);
|
|
1033
|
-
} catch (err) {
|
|
1034
|
-
if (err instanceof ZodError) {
|
|
1035
|
-
const issues = err.issues.map((i) => ` - ${i.path.join(".")}: ${i.message}`).join("\n");
|
|
1036
|
-
throw new Error(`Invalid tasks.json at ${path}:
|
|
1037
|
-
${issues}`);
|
|
1038
|
-
}
|
|
1039
|
-
throw err;
|
|
1040
|
-
}
|
|
1041
|
-
}
|
|
1042
|
-
async function saveTaskPlan(path, plan) {
|
|
1043
|
-
await writeFileAtomic(path, `${JSON.stringify(plan, null, 2)}
|
|
1044
|
-
`);
|
|
1045
|
-
}
|
|
1046
|
-
function initializeState(plan) {
|
|
1047
|
-
const defaultPipeline = {
|
|
1048
|
-
prdCompleted: false,
|
|
1049
|
-
jsonCompleted: false,
|
|
1050
|
-
executionCompleted: false,
|
|
1051
|
-
reviewCompleted: false,
|
|
1052
|
-
prCreated: false
|
|
1053
|
-
};
|
|
1054
|
-
return {
|
|
1055
|
-
...plan,
|
|
1056
|
-
issueStatus: plan.issueStatus ?? "pending",
|
|
1057
|
-
completedAt: plan.completedAt ?? null,
|
|
1058
|
-
lastAttemptAt: plan.lastAttemptAt ?? null,
|
|
1059
|
-
lastError: plan.lastError ?? null,
|
|
1060
|
-
correctionCycle: plan.correctionCycle ?? 0,
|
|
1061
|
-
maxCorrectionCycles: plan.maxCorrectionCycles ?? 3,
|
|
1062
|
-
lastReviewFindings: plan.lastReviewFindings ?? null,
|
|
1063
|
-
pipeline: plan.pipeline ? { ...defaultPipeline, ...plan.pipeline } : defaultPipeline
|
|
1064
|
-
};
|
|
1065
|
-
}
|
|
1066
|
-
function hasPendingCorrection(plan) {
|
|
1067
|
-
return Boolean(plan.lastReviewFindings);
|
|
1068
|
-
}
|
|
1069
|
-
function allStoriesPass(plan) {
|
|
1070
|
-
if (plan.userStories.length === 0) {
|
|
1071
|
-
return false;
|
|
1072
|
-
}
|
|
1073
|
-
return plan.userStories.every((story) => story.passes === true);
|
|
1074
|
-
}
|
|
1075
|
-
function selectActiveStory(stories) {
|
|
1076
|
-
return [...stories].filter((story) => !story.passes).sort((a, b) => a.priority - b.priority)[0];
|
|
1077
|
-
}
|
|
1078
|
-
function applyStoryMetrics(plan, storyIds, share, durationSeconds) {
|
|
1079
|
-
if (storyIds.length === 0) return plan;
|
|
1080
|
-
const targets = new Set(storyIds);
|
|
1081
|
-
return {
|
|
1082
|
-
...plan,
|
|
1083
|
-
userStories: plan.userStories.map((story) => {
|
|
1084
|
-
if (!targets.has(story.id)) return story;
|
|
1085
|
-
const updated = { ...story, ...sumUsage(story, share) };
|
|
1086
|
-
if (story.durationSeconds !== void 0 || durationSeconds !== void 0) {
|
|
1087
|
-
updated.durationSeconds = (story.durationSeconds ?? 0) + (durationSeconds ?? 0);
|
|
1088
|
-
}
|
|
1089
|
-
return updated;
|
|
1090
|
-
})
|
|
1091
|
-
};
|
|
1092
|
-
}
|
|
1093
|
-
function markIssueInProgress(plan, timestamp) {
|
|
1094
|
-
const ts = timestamp ?? isoNow();
|
|
1095
|
-
return {
|
|
1096
|
-
...plan,
|
|
1097
|
-
issueStatus: "in_progress",
|
|
1098
|
-
completedAt: null,
|
|
1099
|
-
lastAttemptAt: ts
|
|
1100
|
-
};
|
|
1101
|
-
}
|
|
1102
|
-
function markIssueCompleted(plan) {
|
|
1103
|
-
const ts = isoNow();
|
|
1104
|
-
return {
|
|
1105
|
-
...plan,
|
|
1106
|
-
issueStatus: "completed",
|
|
1107
|
-
completedAt: ts,
|
|
1108
|
-
lastAttemptAt: ts,
|
|
1109
|
-
lastError: null,
|
|
1110
|
-
pipeline: plan.pipeline ? { ...plan.pipeline, executionCompleted: true } : plan.pipeline
|
|
1111
|
-
};
|
|
1112
|
-
}
|
|
1113
|
-
function setLastError(plan, category, message) {
|
|
1114
|
-
const ts = isoNow();
|
|
1115
|
-
const error = {
|
|
1116
|
-
category,
|
|
1117
|
-
message,
|
|
1118
|
-
at: ts
|
|
1119
|
-
};
|
|
1120
|
-
return {
|
|
1121
|
-
...plan,
|
|
1122
|
-
lastAttemptAt: ts,
|
|
1123
|
-
lastError: error
|
|
1124
|
-
};
|
|
1125
|
-
}
|
|
1126
|
-
function clearLastError(plan, attemptStartedAt) {
|
|
1127
|
-
const ts = isoNow();
|
|
1128
|
-
if (plan.lastError && plan.lastError.at > attemptStartedAt) {
|
|
1129
|
-
return {
|
|
1130
|
-
...plan,
|
|
1131
|
-
lastAttemptAt: ts
|
|
1132
|
-
};
|
|
1133
|
-
}
|
|
1134
|
-
return {
|
|
1135
|
-
...plan,
|
|
1136
|
-
lastAttemptAt: ts,
|
|
1137
|
-
lastError: null
|
|
1138
|
-
};
|
|
1139
|
-
}
|
|
1140
|
-
function trimErrorMessage(message) {
|
|
1141
|
-
return message.split("\n").filter((line) => line.trim().length > 0).slice(0, 8).join("\n");
|
|
1142
|
-
}
|
|
1143
|
-
|
|
1144
715
|
// src/core/verbose.ts
|
|
1145
716
|
var _verbose = false;
|
|
1146
717
|
function setVerbose(enabled) {
|
|
@@ -1170,6 +741,13 @@ function setStoryStageCallback(callback) {
|
|
|
1170
741
|
function getStoryStageCallback() {
|
|
1171
742
|
return _onStoryStage;
|
|
1172
743
|
}
|
|
744
|
+
var _onActivity;
|
|
745
|
+
function setActivityCallback(callback) {
|
|
746
|
+
_onActivity = callback;
|
|
747
|
+
}
|
|
748
|
+
function getActivityCallback() {
|
|
749
|
+
return _onActivity;
|
|
750
|
+
}
|
|
1173
751
|
var _globalTimeout;
|
|
1174
752
|
function setGlobalTimeout(ms) {
|
|
1175
753
|
_globalTimeout = ms;
|
|
@@ -1177,6 +755,13 @@ function setGlobalTimeout(ms) {
|
|
|
1177
755
|
function getGlobalTimeout() {
|
|
1178
756
|
return _globalTimeout;
|
|
1179
757
|
}
|
|
758
|
+
var _inactivityTimeout;
|
|
759
|
+
function setInactivityTimeout(ms) {
|
|
760
|
+
_inactivityTimeout = ms;
|
|
761
|
+
}
|
|
762
|
+
function getInactivityTimeout() {
|
|
763
|
+
return _inactivityTimeout;
|
|
764
|
+
}
|
|
1180
765
|
|
|
1181
766
|
// src/ui/logger.ts
|
|
1182
767
|
import chalk from "chalk";
|
|
@@ -1203,7 +788,8 @@ function getIcons() {
|
|
|
1203
788
|
end: "\u25A0",
|
|
1204
789
|
notReached: "\u25CB",
|
|
1205
790
|
tool: "\u25B8",
|
|
1206
|
-
connector: "\u2502"
|
|
791
|
+
connector: "\u2502",
|
|
792
|
+
info: "\xB7"
|
|
1207
793
|
};
|
|
1208
794
|
}
|
|
1209
795
|
return {
|
|
@@ -1216,7 +802,8 @@ function getIcons() {
|
|
|
1216
802
|
end: "[END]",
|
|
1217
803
|
notReached: "[ ]",
|
|
1218
804
|
tool: ">",
|
|
1219
|
-
connector: "|"
|
|
805
|
+
connector: "|",
|
|
806
|
+
info: "-"
|
|
1220
807
|
};
|
|
1221
808
|
}
|
|
1222
809
|
function getTermWidth() {
|
|
@@ -1266,9 +853,9 @@ function printRetry(message) {
|
|
|
1266
853
|
function printInfo(message) {
|
|
1267
854
|
const icons = getIcons();
|
|
1268
855
|
if (useColor()) {
|
|
1269
|
-
emit(chalk.blue(`${icons.
|
|
856
|
+
emit(chalk.blue(`${icons.info} ${message}`));
|
|
1270
857
|
} else {
|
|
1271
|
-
emit(`${icons.
|
|
858
|
+
emit(`${icons.info} ${message}`);
|
|
1272
859
|
}
|
|
1273
860
|
}
|
|
1274
861
|
function createSpinner(message) {
|
|
@@ -1325,38 +912,13 @@ var ElapsedTimer = class {
|
|
|
1325
912
|
};
|
|
1326
913
|
|
|
1327
914
|
export {
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
pullRequestRefSchema,
|
|
1331
|
-
issueMetadataSchema,
|
|
1332
|
-
taskPlanSchema,
|
|
1333
|
-
sessionSnapshotSchema,
|
|
1334
|
-
webConfigSchema,
|
|
1335
|
-
issuesConfigSchema,
|
|
1336
|
-
prReviewConfigSchema,
|
|
915
|
+
createInitialSnapshot,
|
|
916
|
+
reduceSessionEvent,
|
|
1337
917
|
NullPublisher,
|
|
918
|
+
MemoryPublisher,
|
|
1338
919
|
FilePublisher,
|
|
1339
920
|
setSessionPublisher,
|
|
1340
921
|
getSessionPublisher,
|
|
1341
|
-
writeFileAtomic,
|
|
1342
|
-
parseUsage,
|
|
1343
|
-
sumUsage,
|
|
1344
|
-
divideUsage,
|
|
1345
|
-
formatTokens,
|
|
1346
|
-
hasUsageData,
|
|
1347
|
-
isoNow,
|
|
1348
|
-
loadTaskPlan,
|
|
1349
|
-
saveTaskPlan,
|
|
1350
|
-
initializeState,
|
|
1351
|
-
hasPendingCorrection,
|
|
1352
|
-
allStoriesPass,
|
|
1353
|
-
selectActiveStory,
|
|
1354
|
-
applyStoryMetrics,
|
|
1355
|
-
markIssueInProgress,
|
|
1356
|
-
markIssueCompleted,
|
|
1357
|
-
setLastError,
|
|
1358
|
-
clearLastError,
|
|
1359
|
-
trimErrorMessage,
|
|
1360
922
|
setVerbose,
|
|
1361
923
|
isVerbose,
|
|
1362
924
|
setOutputCallback,
|
|
@@ -1365,8 +927,12 @@ export {
|
|
|
1365
927
|
getStoryUpdateCallback,
|
|
1366
928
|
setStoryStageCallback,
|
|
1367
929
|
getStoryStageCallback,
|
|
930
|
+
setActivityCallback,
|
|
931
|
+
getActivityCallback,
|
|
1368
932
|
setGlobalTimeout,
|
|
1369
933
|
getGlobalTimeout,
|
|
934
|
+
setInactivityTimeout,
|
|
935
|
+
getInactivityTimeout,
|
|
1370
936
|
useUnicode,
|
|
1371
937
|
useColor,
|
|
1372
938
|
getIcons,
|
|
@@ -1380,4 +946,4 @@ export {
|
|
|
1380
946
|
formatDuration,
|
|
1381
947
|
ElapsedTimer
|
|
1382
948
|
};
|
|
1383
|
-
//# sourceMappingURL=chunk-
|
|
949
|
+
//# sourceMappingURL=chunk-IYV6KNVF.js.map
|