issue-flow 0.7.2 → 0.7.4
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/dist/{analyze-XMEULTT2.js → analyze-PJBY346H.js} +13 -8
- package/dist/analyze-PJBY346H.js.map +1 -0
- package/dist/{chunk-MWUF4LMF.js → chunk-3ISZ7T5M.js} +13 -8
- package/dist/chunk-3ISZ7T5M.js.map +1 -0
- package/dist/{chunk-EHVKXFFN.js → chunk-4M4EWFZZ.js} +2 -2
- package/dist/{chunk-JNEHVQH5.js → chunk-6HGZYTAT.js} +223 -11
- package/dist/chunk-6HGZYTAT.js.map +1 -0
- package/dist/chunk-7HX2RPFY.js +123 -0
- package/dist/chunk-7HX2RPFY.js.map +1 -0
- package/dist/{chunk-DKMBLNGO.js → chunk-7YS3J4A2.js} +3 -3
- package/dist/{chunk-WQ4SUZ4P.js → chunk-EBJM6G2D.js} +90 -23
- package/dist/chunk-EBJM6G2D.js.map +1 -0
- package/dist/{chunk-GOZT2YP5.js → chunk-IWBHBDRU.js} +5 -9
- package/dist/chunk-IWBHBDRU.js.map +1 -0
- package/dist/{chunk-6UBA7CSJ.js → chunk-NVSJYJ72.js} +14 -8
- package/dist/chunk-NVSJYJ72.js.map +1 -0
- package/dist/{chunk-G3TJHMAS.js → chunk-OCXHO7YP.js} +2 -2
- package/dist/{chunk-RGCU2KE6.js → chunk-R7X26MWK.js} +14 -9
- package/dist/chunk-R7X26MWK.js.map +1 -0
- package/dist/{chunk-YLXPLHEL.js → chunk-RKASM5FF.js} +2 -2
- package/dist/{chunk-WUITOU5B.js → chunk-SHG2PPN7.js} +14 -9
- package/dist/chunk-SHG2PPN7.js.map +1 -0
- package/dist/{chunk-CYU6RSDJ.js → chunk-WEXU4R3H.js} +14 -9
- package/dist/chunk-WEXU4R3H.js.map +1 -0
- package/dist/{chunk-PRVWJZV4.js → chunk-YPIIIDTT.js} +3 -3
- package/dist/cli.js +13 -13
- package/dist/{config-2NDV7Y72.js → config-7N7UJP32.js} +3 -3
- package/dist/execute-EZKQKKLO.js +13 -0
- package/dist/{generate-YEQRH36H.js → generate-KUQNDMMR.js} +13 -8
- package/dist/generate-KUQNDMMR.js.map +1 -0
- package/dist/init-GL6US653.js +9 -0
- package/dist/plan-XNXGWNGY.js +15 -0
- package/dist/pr-XILDNJLM.js +15 -0
- package/dist/pr-review-4WG2RPRP.js +15 -0
- package/dist/prd-BLJ2XBPL.js +15 -0
- package/dist/review-MRA7ZQQG.js +13 -0
- package/dist/{run-EFXDXSB4.js → run-X62QZCXN.js} +20 -16
- package/dist/run-X62QZCXN.js.map +1 -0
- package/package.json +2 -2
- package/web/CLAUDE.md +35 -0
- package/web/public/app.css +5 -0
- package/web/public/app.js +80 -7
- package/dist/analyze-XMEULTT2.js.map +0 -1
- package/dist/chunk-6UBA7CSJ.js.map +0 -1
- package/dist/chunk-CYU6RSDJ.js.map +0 -1
- package/dist/chunk-GOZT2YP5.js.map +0 -1
- package/dist/chunk-JNEHVQH5.js.map +0 -1
- package/dist/chunk-MWUF4LMF.js.map +0 -1
- package/dist/chunk-RGCU2KE6.js.map +0 -1
- package/dist/chunk-SLHZPB3C.js +0 -50
- package/dist/chunk-SLHZPB3C.js.map +0 -1
- package/dist/chunk-WQ4SUZ4P.js.map +0 -1
- package/dist/chunk-WUITOU5B.js.map +0 -1
- package/dist/execute-BOQPTRH4.js +0 -13
- package/dist/generate-YEQRH36H.js.map +0 -1
- package/dist/init-5KXCG36P.js +0 -9
- package/dist/plan-4I47CQM5.js +0 -15
- package/dist/pr-F672VPMM.js +0 -15
- package/dist/pr-review-GKP4TJRJ.js +0 -15
- package/dist/prd-3QME4DYX.js +0 -15
- package/dist/review-RG2UIPOB.js +0 -13
- package/dist/run-EFXDXSB4.js.map +0 -1
- /package/dist/{chunk-EHVKXFFN.js.map → chunk-4M4EWFZZ.js.map} +0 -0
- /package/dist/{chunk-DKMBLNGO.js.map → chunk-7YS3J4A2.js.map} +0 -0
- /package/dist/{chunk-G3TJHMAS.js.map → chunk-OCXHO7YP.js.map} +0 -0
- /package/dist/{chunk-YLXPLHEL.js.map → chunk-RKASM5FF.js.map} +0 -0
- /package/dist/{chunk-PRVWJZV4.js.map → chunk-YPIIIDTT.js.map} +0 -0
- /package/dist/{config-2NDV7Y72.js.map → config-7N7UJP32.js.map} +0 -0
- /package/dist/{execute-BOQPTRH4.js.map → execute-EZKQKKLO.js.map} +0 -0
- /package/dist/{init-5KXCG36P.js.map → init-GL6US653.js.map} +0 -0
- /package/dist/{plan-4I47CQM5.js.map → plan-XNXGWNGY.js.map} +0 -0
- /package/dist/{pr-F672VPMM.js.map → pr-XILDNJLM.js.map} +0 -0
- /package/dist/{pr-review-GKP4TJRJ.js.map → pr-review-4WG2RPRP.js.map} +0 -0
- /package/dist/{prd-3QME4DYX.js.map → prd-BLJ2XBPL.js.map} +0 -0
- /package/dist/{review-RG2UIPOB.js.map → review-MRA7ZQQG.js.map} +0 -0
|
@@ -2,17 +2,18 @@
|
|
|
2
2
|
import {
|
|
3
3
|
issuePlaceholders,
|
|
4
4
|
resolveCommandIssue
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-7YS3J4A2.js";
|
|
6
6
|
import {
|
|
7
7
|
runHeadless
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-IWBHBDRU.js";
|
|
9
9
|
import {
|
|
10
10
|
applyPlaceholders,
|
|
11
|
-
loadPrompt
|
|
12
|
-
|
|
11
|
+
loadPrompt,
|
|
12
|
+
publishPhaseMetrics
|
|
13
|
+
} from "./chunk-7HX2RPFY.js";
|
|
13
14
|
import {
|
|
14
15
|
resolveIssuePaths
|
|
15
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-OCXHO7YP.js";
|
|
16
17
|
import {
|
|
17
18
|
getGlobalTimeout,
|
|
18
19
|
loadTaskPlan,
|
|
@@ -20,7 +21,7 @@ import {
|
|
|
20
21
|
printInfo,
|
|
21
22
|
printSuccess,
|
|
22
23
|
saveTaskPlan
|
|
23
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-6HGZYTAT.js";
|
|
24
25
|
|
|
25
26
|
// src/commands/analyze.ts
|
|
26
27
|
import { mkdir, readFile, writeFile } from "fs/promises";
|
|
@@ -41,15 +42,19 @@ async function runAnalyze(issue, resolvedIssue) {
|
|
|
41
42
|
// body that happens to contain a placeholder is left untouched.
|
|
42
43
|
...issuePlaceholders(resolution.resolved)
|
|
43
44
|
});
|
|
45
|
+
const startedAtMs = Date.now();
|
|
44
46
|
const result = await runHeadless({
|
|
45
47
|
prompt,
|
|
46
48
|
maxTurns: 30,
|
|
47
49
|
timeout: getGlobalTimeout() ?? 3e5,
|
|
48
|
-
|
|
50
|
+
// json (not text) so the CLI reports usage: the envelope's `result` field
|
|
51
|
+
// carries the same assistant text this phase already consumed.
|
|
52
|
+
outputFormat: "json",
|
|
49
53
|
allowedTools: ["Bash", "Read", "Glob", "Grep", "Write"],
|
|
50
54
|
addDirs: [paths.issueDir],
|
|
51
55
|
statusMessage: `Analyzing issue #${issueNumber}...`
|
|
52
56
|
});
|
|
57
|
+
publishPhaseMetrics("analyze", result.cost, startedAtMs);
|
|
53
58
|
if (!result.success) {
|
|
54
59
|
printError(`Analysis failed: ${result.error}`);
|
|
55
60
|
return 1;
|
|
@@ -77,4 +82,4 @@ async function runAnalyze(issue, resolvedIssue) {
|
|
|
77
82
|
export {
|
|
78
83
|
runAnalyze
|
|
79
84
|
};
|
|
80
|
-
//# sourceMappingURL=analyze-
|
|
85
|
+
//# sourceMappingURL=analyze-PJBY346H.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/analyze.ts"],"sourcesContent":["import { mkdir, readFile, writeFile } from 'node:fs/promises';\nimport { runHeadless } from '../core/headless.js';\nimport { applyPlaceholders, loadPrompt } from '../core/prompt-resolver.js';\nimport { publishPhaseMetrics } from '../core/session-metrics.js';\nimport { loadTaskPlan, saveTaskPlan } from '../core/state-manager.js';\nimport { getGlobalTimeout } from '../core/verbose.js';\nimport { issuePlaceholders, resolveCommandIssue } from '../issues/context.js';\nimport type { ResolvedIssue } from '../issues/types.js';\nimport { resolveIssuePaths } from '../storage/resolve.js';\nimport { printError, printInfo, printSuccess } from '../ui/logger.js';\n\nexport async function runAnalyze(issue: string, resolvedIssue?: ResolvedIssue): Promise<number> {\n const issueNumber = issue.replace(/^#/, '');\n const paths = await resolveIssuePaths(issueNumber);\n const analysisPath = paths.analysisFile;\n\n const resolution = await resolveCommandIssue(issueNumber, resolvedIssue);\n if (!resolution.ok) {\n return resolution.code;\n }\n\n await mkdir(paths.issueDir, { recursive: true });\n\n const template = await loadPrompt('analyze');\n const prompt = applyPlaceholders(template, {\n __ISSUE_NUMBER__: issueNumber,\n __ANALYSIS_PATH__: analysisPath,\n // Last: the Issue content is substituted in but never scanned again, so a\n // body that happens to contain a placeholder is left untouched.\n ...issuePlaceholders(resolution.resolved),\n });\n\n const startedAtMs = Date.now();\n const result = await runHeadless({\n prompt,\n maxTurns: 30,\n timeout: getGlobalTimeout() ?? 300_000,\n // json (not text) so the CLI reports usage: the envelope's `result` field\n // carries the same assistant text this phase already consumed.\n outputFormat: 'json',\n allowedTools: ['Bash', 'Read', 'Glob', 'Grep', 'Write'],\n addDirs: [paths.issueDir],\n statusMessage: `Analyzing issue #${issueNumber}...`,\n });\n // Before the success check: the tokens were spent either way.\n publishPhaseMetrics('analyze', result.cost, startedAtMs);\n\n if (!result.success) {\n printError(`Analysis failed: ${result.error}`);\n return 1;\n }\n\n // Verify the file was created\n try {\n const content = await readFile(analysisPath, 'utf-8');\n if (content.length < 10) {\n printError('Analysis file was created but appears empty');\n return 1;\n }\n } catch {\n // File wasn't created by headless — save the result as analysis\n printInfo('Headless did not create analysis file; saving output directly');\n await writeFile(analysisPath, result.result, 'utf-8');\n }\n\n // Update pipeline state\n const tasksPath = paths.tasksFile;\n try {\n const plan = await loadTaskPlan(tasksPath);\n plan.pipeline.analyzeCompleted = true;\n await saveTaskPlan(tasksPath, plan);\n } catch {\n // tasks.json may not exist yet — that's OK for standalone analyze\n }\n\n printSuccess(`Analysis saved to ${analysisPath}`);\n return 0;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,OAAO,UAAU,iBAAiB;AAW3C,eAAsB,WAAW,OAAe,eAAgD;AAC9F,QAAM,cAAc,MAAM,QAAQ,MAAM,EAAE;AAC1C,QAAM,QAAQ,MAAM,kBAAkB,WAAW;AACjD,QAAM,eAAe,MAAM;AAE3B,QAAM,aAAa,MAAM,oBAAoB,aAAa,aAAa;AACvE,MAAI,CAAC,WAAW,IAAI;AAClB,WAAO,WAAW;AAAA,EACpB;AAEA,QAAM,MAAM,MAAM,UAAU,EAAE,WAAW,KAAK,CAAC;AAE/C,QAAM,WAAW,MAAM,WAAW,SAAS;AAC3C,QAAM,SAAS,kBAAkB,UAAU;AAAA,IACzC,kBAAkB;AAAA,IAClB,mBAAmB;AAAA;AAAA;AAAA,IAGnB,GAAG,kBAAkB,WAAW,QAAQ;AAAA,EAC1C,CAAC;AAED,QAAM,cAAc,KAAK,IAAI;AAC7B,QAAM,SAAS,MAAM,YAAY;AAAA,IAC/B;AAAA,IACA,UAAU;AAAA,IACV,SAAS,iBAAiB,KAAK;AAAA;AAAA;AAAA,IAG/B,cAAc;AAAA,IACd,cAAc,CAAC,QAAQ,QAAQ,QAAQ,QAAQ,OAAO;AAAA,IACtD,SAAS,CAAC,MAAM,QAAQ;AAAA,IACxB,eAAe,oBAAoB,WAAW;AAAA,EAChD,CAAC;AAED,sBAAoB,WAAW,OAAO,MAAM,WAAW;AAEvD,MAAI,CAAC,OAAO,SAAS;AACnB,eAAW,oBAAoB,OAAO,KAAK,EAAE;AAC7C,WAAO;AAAA,EACT;AAGA,MAAI;AACF,UAAM,UAAU,MAAM,SAAS,cAAc,OAAO;AACpD,QAAI,QAAQ,SAAS,IAAI;AACvB,iBAAW,6CAA6C;AACxD,aAAO;AAAA,IACT;AAAA,EACF,QAAQ;AAEN,cAAU,+DAA+D;AACzE,UAAM,UAAU,cAAc,OAAO,QAAQ,OAAO;AAAA,EACtD;AAGA,QAAM,YAAY,MAAM;AACxB,MAAI;AACF,UAAM,OAAO,MAAM,aAAa,SAAS;AACzC,SAAK,SAAS,mBAAmB;AACjC,UAAM,aAAa,WAAW,IAAI;AAAA,EACpC,QAAQ;AAAA,EAER;AAEA,eAAa,qBAAqB,YAAY,EAAE;AAChD,SAAO;AACT;","names":[]}
|
|
@@ -2,24 +2,25 @@
|
|
|
2
2
|
import {
|
|
3
3
|
issuePlaceholders,
|
|
4
4
|
resolveCommandIssue
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-7YS3J4A2.js";
|
|
6
6
|
import {
|
|
7
7
|
runHeadless
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-IWBHBDRU.js";
|
|
9
9
|
import {
|
|
10
10
|
applyPlaceholders,
|
|
11
|
-
loadPrompt
|
|
12
|
-
|
|
11
|
+
loadPrompt,
|
|
12
|
+
publishPhaseMetrics
|
|
13
|
+
} from "./chunk-7HX2RPFY.js";
|
|
13
14
|
import {
|
|
14
15
|
resolveIssuePaths
|
|
15
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-OCXHO7YP.js";
|
|
16
17
|
import {
|
|
17
18
|
getGlobalTimeout,
|
|
18
19
|
loadTaskPlan,
|
|
19
20
|
printError,
|
|
20
21
|
printSuccess,
|
|
21
22
|
saveTaskPlan
|
|
22
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-6HGZYTAT.js";
|
|
23
24
|
|
|
24
25
|
// src/commands/review.ts
|
|
25
26
|
function parseReviewResult(output) {
|
|
@@ -58,15 +59,19 @@ async function runReview(issue, resolvedIssue) {
|
|
|
58
59
|
__TASKS_PATH__: tasksPath,
|
|
59
60
|
...issuePlaceholders(resolution.resolved)
|
|
60
61
|
});
|
|
62
|
+
const startedAtMs = Date.now();
|
|
61
63
|
const result = await runHeadless({
|
|
62
64
|
prompt,
|
|
63
65
|
maxTurns: 25,
|
|
64
66
|
timeout: getGlobalTimeout() ?? 3e5,
|
|
65
|
-
|
|
67
|
+
// json (not text) so the CLI reports usage: the envelope's `result` field
|
|
68
|
+
// carries the same assistant text parseReviewResult() already consumed.
|
|
69
|
+
outputFormat: "json",
|
|
66
70
|
allowedTools: ["Bash", "Read", "Glob", "Grep"],
|
|
67
71
|
addDirs: [paths.issueDir],
|
|
68
72
|
statusMessage: `Reviewing issue #${issueNumber} resolution...`
|
|
69
73
|
});
|
|
74
|
+
publishPhaseMetrics("review", result.cost, startedAtMs);
|
|
70
75
|
if (!result.success) {
|
|
71
76
|
printError(`Review failed: ${result.error}`);
|
|
72
77
|
return 1;
|
|
@@ -100,4 +105,4 @@ async function runReview(issue, resolvedIssue) {
|
|
|
100
105
|
export {
|
|
101
106
|
runReview
|
|
102
107
|
};
|
|
103
|
-
//# sourceMappingURL=chunk-
|
|
108
|
+
//# sourceMappingURL=chunk-3ISZ7T5M.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/review.ts"],"sourcesContent":["import { runHeadless } from '../core/headless.js';\nimport { applyPlaceholders, loadPrompt } from '../core/prompt-resolver.js';\nimport { publishPhaseMetrics } from '../core/session-metrics.js';\nimport { loadTaskPlan, saveTaskPlan } from '../core/state-manager.js';\nimport { getGlobalTimeout } from '../core/verbose.js';\nimport { issuePlaceholders, resolveCommandIssue } from '../issues/context.js';\nimport type { ResolvedIssue } from '../issues/types.js';\nimport { resolveIssuePaths } from '../storage/resolve.js';\nimport { printError, printSuccess } from '../ui/logger.js';\n\nexport interface ReviewResult {\n status: 'PASS' | 'FAIL';\n findings?: string;\n}\n\n/**\n * Parse the <review-result> block from headless output.\n */\nfunction parseReviewResult(output: string): ReviewResult {\n const match = output.match(/<review-result>([\\s\\S]*?)<\\/review-result>/);\n if (!match) {\n // Try to detect PASS/FAIL from the raw output\n if (/STATUS:\\s*PASS/i.test(output)) {\n return { status: 'PASS' };\n }\n if (/STATUS:\\s*FAIL/i.test(output)) {\n const findingsMatch = output.match(/FINDINGS:([\\s\\S]*?)(?:$|<\\/)/);\n return { status: 'FAIL', findings: findingsMatch?.[1]?.trim() ?? 'Unknown findings' };\n }\n // Default to PASS if no explicit status found and no errors\n return { status: 'PASS' };\n }\n\n const block = match[1];\n if (/STATUS:\\s*PASS/i.test(block)) {\n return { status: 'PASS' };\n }\n\n const findingsMatch = block.match(/FINDINGS:([\\s\\S]*)/);\n return {\n status: 'FAIL',\n findings: findingsMatch?.[1]?.trim() ?? 'Unknown findings',\n };\n}\n\nexport async function runReview(issue: string, resolvedIssue?: ResolvedIssue): Promise<number> {\n const issueNumber = issue.replace(/^#/, '');\n const paths = await resolveIssuePaths(issueNumber);\n const tasksPath = paths.tasksFile;\n\n const resolution = await resolveCommandIssue(issueNumber, resolvedIssue);\n if (!resolution.ok) {\n return resolution.code;\n }\n\n const template = await loadPrompt('review');\n const prompt = applyPlaceholders(template, {\n __ISSUE_NUMBER__: issueNumber,\n __TASKS_PATH__: tasksPath,\n ...issuePlaceholders(resolution.resolved),\n });\n\n const startedAtMs = Date.now();\n const result = await runHeadless({\n prompt,\n maxTurns: 25,\n timeout: getGlobalTimeout() ?? 300_000,\n // json (not text) so the CLI reports usage: the envelope's `result` field\n // carries the same assistant text parseReviewResult() already consumed.\n outputFormat: 'json',\n allowedTools: ['Bash', 'Read', 'Glob', 'Grep'],\n addDirs: [paths.issueDir],\n statusMessage: `Reviewing issue #${issueNumber} resolution...`,\n });\n // Before the success check: the tokens were spent either way. A correction\n // cycle calls runReview() again and the reducer sums both invocations.\n publishPhaseMetrics('review', result.cost, startedAtMs);\n\n if (!result.success) {\n printError(`Review failed: ${result.error}`);\n return 1;\n }\n\n const review = parseReviewResult(result.result);\n\n if (review.status === 'PASS') {\n // Update pipeline state\n try {\n const plan = await loadTaskPlan(tasksPath);\n plan.pipeline.reviewCompleted = true;\n plan.lastReviewFindings = null;\n await saveTaskPlan(tasksPath, plan);\n } catch {\n // tasks.json may not exist\n }\n\n printSuccess('Review PASSED — implementation meets acceptance criteria');\n return 0;\n }\n\n printError('Review FAILED — issues found:');\n if (review.findings) {\n console.log(review.findings);\n }\n\n // Persist the findings so a correction cycle can act on them: without this,\n // a re-run of execute sees every userStories[].passes already true and\n // exits immediately without attempting any fix (see engine.ts's\n // \"already complete\" guards).\n try {\n const plan = await loadTaskPlan(tasksPath);\n plan.pipeline.reviewCompleted = false;\n plan.lastReviewFindings = review.findings ?? 'Unknown findings';\n await saveTaskPlan(tasksPath, plan);\n } catch {\n // tasks.json may not exist\n }\n\n return 1;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAkBA,SAAS,kBAAkB,QAA8B;AACvD,QAAM,QAAQ,OAAO,MAAM,4CAA4C;AACvE,MAAI,CAAC,OAAO;AAEV,QAAI,kBAAkB,KAAK,MAAM,GAAG;AAClC,aAAO,EAAE,QAAQ,OAAO;AAAA,IAC1B;AACA,QAAI,kBAAkB,KAAK,MAAM,GAAG;AAClC,YAAMA,iBAAgB,OAAO,MAAM,8BAA8B;AACjE,aAAO,EAAE,QAAQ,QAAQ,UAAUA,iBAAgB,CAAC,GAAG,KAAK,KAAK,mBAAmB;AAAA,IACtF;AAEA,WAAO,EAAE,QAAQ,OAAO;AAAA,EAC1B;AAEA,QAAM,QAAQ,MAAM,CAAC;AACrB,MAAI,kBAAkB,KAAK,KAAK,GAAG;AACjC,WAAO,EAAE,QAAQ,OAAO;AAAA,EAC1B;AAEA,QAAM,gBAAgB,MAAM,MAAM,oBAAoB;AACtD,SAAO;AAAA,IACL,QAAQ;AAAA,IACR,UAAU,gBAAgB,CAAC,GAAG,KAAK,KAAK;AAAA,EAC1C;AACF;AAEA,eAAsB,UAAU,OAAe,eAAgD;AAC7F,QAAM,cAAc,MAAM,QAAQ,MAAM,EAAE;AAC1C,QAAM,QAAQ,MAAM,kBAAkB,WAAW;AACjD,QAAM,YAAY,MAAM;AAExB,QAAM,aAAa,MAAM,oBAAoB,aAAa,aAAa;AACvE,MAAI,CAAC,WAAW,IAAI;AAClB,WAAO,WAAW;AAAA,EACpB;AAEA,QAAM,WAAW,MAAM,WAAW,QAAQ;AAC1C,QAAM,SAAS,kBAAkB,UAAU;AAAA,IACzC,kBAAkB;AAAA,IAClB,gBAAgB;AAAA,IAChB,GAAG,kBAAkB,WAAW,QAAQ;AAAA,EAC1C,CAAC;AAED,QAAM,cAAc,KAAK,IAAI;AAC7B,QAAM,SAAS,MAAM,YAAY;AAAA,IAC/B;AAAA,IACA,UAAU;AAAA,IACV,SAAS,iBAAiB,KAAK;AAAA;AAAA;AAAA,IAG/B,cAAc;AAAA,IACd,cAAc,CAAC,QAAQ,QAAQ,QAAQ,MAAM;AAAA,IAC7C,SAAS,CAAC,MAAM,QAAQ;AAAA,IACxB,eAAe,oBAAoB,WAAW;AAAA,EAChD,CAAC;AAGD,sBAAoB,UAAU,OAAO,MAAM,WAAW;AAEtD,MAAI,CAAC,OAAO,SAAS;AACnB,eAAW,kBAAkB,OAAO,KAAK,EAAE;AAC3C,WAAO;AAAA,EACT;AAEA,QAAM,SAAS,kBAAkB,OAAO,MAAM;AAE9C,MAAI,OAAO,WAAW,QAAQ;AAE5B,QAAI;AACF,YAAM,OAAO,MAAM,aAAa,SAAS;AACzC,WAAK,SAAS,kBAAkB;AAChC,WAAK,qBAAqB;AAC1B,YAAM,aAAa,WAAW,IAAI;AAAA,IACpC,QAAQ;AAAA,IAER;AAEA,iBAAa,+DAA0D;AACvE,WAAO;AAAA,EACT;AAEA,aAAW,oCAA+B;AAC1C,MAAI,OAAO,UAAU;AACnB,YAAQ,IAAI,OAAO,QAAQ;AAAA,EAC7B;AAMA,MAAI;AACF,UAAM,OAAO,MAAM,aAAa,SAAS;AACzC,SAAK,SAAS,kBAAkB;AAChC,SAAK,qBAAqB,OAAO,YAAY;AAC7C,UAAM,aAAa,WAAW,IAAI;AAAA,EACpC,QAAQ;AAAA,EAER;AAEA,SAAO;AACT;","names":["findingsMatch"]}
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
getSessionPublisher,
|
|
8
8
|
isoNow,
|
|
9
9
|
printRetry
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-6HGZYTAT.js";
|
|
11
11
|
|
|
12
12
|
// src/core/phase-runner.ts
|
|
13
13
|
import { readFile } from "fs/promises";
|
|
@@ -55,4 +55,4 @@ export {
|
|
|
55
55
|
runPhaseWithRetry,
|
|
56
56
|
readFileWithGrace
|
|
57
57
|
};
|
|
58
|
-
//# sourceMappingURL=chunk-
|
|
58
|
+
//# sourceMappingURL=chunk-4M4EWFZZ.js.map
|
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
// src/schemas.ts
|
|
4
4
|
import { z } from "zod";
|
|
5
|
+
var claudeUsageSchema = z.object({
|
|
6
|
+
inputTokens: z.number().optional(),
|
|
7
|
+
outputTokens: z.number().optional(),
|
|
8
|
+
cacheReadTokens: z.number().optional(),
|
|
9
|
+
cacheCreationTokens: z.number().optional(),
|
|
10
|
+
costUsd: z.number().optional()
|
|
11
|
+
});
|
|
5
12
|
var userStorySchema = z.object({
|
|
6
13
|
id: z.string(),
|
|
7
14
|
title: z.string(),
|
|
@@ -9,7 +16,9 @@ var userStorySchema = z.object({
|
|
|
9
16
|
acceptanceCriteria: z.array(z.string()),
|
|
10
17
|
priority: z.number().int().positive(),
|
|
11
18
|
passes: z.boolean(),
|
|
12
|
-
notes: z.string()
|
|
19
|
+
notes: z.string(),
|
|
20
|
+
...claudeUsageSchema.shape,
|
|
21
|
+
durationSeconds: z.number().optional()
|
|
13
22
|
});
|
|
14
23
|
var pipelineStateSchema = z.object({
|
|
15
24
|
analyzeCompleted: z.boolean().optional(),
|
|
@@ -89,10 +98,7 @@ var taskPlanSchema = z.object({
|
|
|
89
98
|
var headlessResultSchema = z.object({
|
|
90
99
|
success: z.boolean(),
|
|
91
100
|
result: z.string(),
|
|
92
|
-
cost:
|
|
93
|
-
inputTokens: z.number().optional(),
|
|
94
|
-
outputTokens: z.number().optional()
|
|
95
|
-
}).nullable(),
|
|
101
|
+
cost: claudeUsageSchema.nullable(),
|
|
96
102
|
error: z.string().nullable()
|
|
97
103
|
});
|
|
98
104
|
var sessionLogEntrySchema = z.object({
|
|
@@ -100,20 +106,31 @@ var sessionLogEntrySchema = z.object({
|
|
|
100
106
|
level: z.enum(["info", "warn", "error"]),
|
|
101
107
|
message: z.string()
|
|
102
108
|
});
|
|
109
|
+
var sessionUsageShape = {
|
|
110
|
+
inputTokens: z.number().nullable().default(null),
|
|
111
|
+
outputTokens: z.number().nullable().default(null),
|
|
112
|
+
cacheReadTokens: z.number().nullable().default(null),
|
|
113
|
+
cacheCreationTokens: z.number().nullable().default(null),
|
|
114
|
+
costUsd: z.number().nullable().default(null)
|
|
115
|
+
};
|
|
103
116
|
var sessionPhaseSchema = z.object({
|
|
104
117
|
name: z.string(),
|
|
105
118
|
status: z.enum(["pending", "running", "completed", "failed"]),
|
|
106
119
|
startedAt: z.string().nullable(),
|
|
107
120
|
endedAt: z.string().nullable(),
|
|
108
121
|
durationSeconds: z.number().nullable(),
|
|
109
|
-
error: z.string().nullable()
|
|
122
|
+
error: z.string().nullable(),
|
|
123
|
+
...sessionUsageShape
|
|
110
124
|
});
|
|
111
125
|
var sessionStorySchema = z.object({
|
|
112
126
|
id: z.string(),
|
|
113
127
|
title: z.string(),
|
|
114
128
|
priority: z.number(),
|
|
115
129
|
passes: z.boolean(),
|
|
116
|
-
completedAt: z.string().nullable()
|
|
130
|
+
completedAt: z.string().nullable(),
|
|
131
|
+
// Also introduced with the metrics, hence the same tolerant default.
|
|
132
|
+
durationSeconds: z.number().nullable().default(null),
|
|
133
|
+
...sessionUsageShape
|
|
117
134
|
});
|
|
118
135
|
var sessionSnapshotSchema = z.object({
|
|
119
136
|
schemaVersion: z.literal(1),
|
|
@@ -143,6 +160,21 @@ var sessionSnapshotSchema = z.object({
|
|
|
143
160
|
}).nullable(),
|
|
144
161
|
phases: z.array(sessionPhaseSchema),
|
|
145
162
|
stories: z.array(sessionStorySchema),
|
|
163
|
+
// The whole aggregate is additive: a snapshot from before it existed parses
|
|
164
|
+
// into the same "nothing reported" object the reducer starts from.
|
|
165
|
+
metrics: z.object({
|
|
166
|
+
totalInputTokens: z.number().nullable().default(null),
|
|
167
|
+
totalOutputTokens: z.number().nullable().default(null),
|
|
168
|
+
totalCacheReadTokens: z.number().nullable().default(null),
|
|
169
|
+
totalCacheCreationTokens: z.number().nullable().default(null),
|
|
170
|
+
totalCostUsd: z.number().nullable().default(null)
|
|
171
|
+
}).default({
|
|
172
|
+
totalInputTokens: null,
|
|
173
|
+
totalOutputTokens: null,
|
|
174
|
+
totalCacheReadTokens: null,
|
|
175
|
+
totalCacheCreationTokens: null,
|
|
176
|
+
totalCostUsd: null
|
|
177
|
+
}),
|
|
146
178
|
execution: z.object({
|
|
147
179
|
iteration: z.number(),
|
|
148
180
|
retries: z.number(),
|
|
@@ -186,6 +218,24 @@ import { dirname } from "path";
|
|
|
186
218
|
import { stripVTControlCharacters } from "util";
|
|
187
219
|
var DEFAULT_LOG_LIMIT = 200;
|
|
188
220
|
var DEFAULT_THROTTLE_MS = 1e3;
|
|
221
|
+
function emptyUsage() {
|
|
222
|
+
return {
|
|
223
|
+
inputTokens: null,
|
|
224
|
+
outputTokens: null,
|
|
225
|
+
cacheReadTokens: null,
|
|
226
|
+
cacheCreationTokens: null,
|
|
227
|
+
costUsd: null
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
function emptyMetrics() {
|
|
231
|
+
return {
|
|
232
|
+
totalInputTokens: null,
|
|
233
|
+
totalOutputTokens: null,
|
|
234
|
+
totalCacheReadTokens: null,
|
|
235
|
+
totalCacheCreationTokens: null,
|
|
236
|
+
totalCostUsd: null
|
|
237
|
+
};
|
|
238
|
+
}
|
|
189
239
|
function createInitialSnapshot() {
|
|
190
240
|
return {
|
|
191
241
|
schemaVersion: 1,
|
|
@@ -210,6 +260,7 @@ function createInitialSnapshot() {
|
|
|
210
260
|
currentActivity: null,
|
|
211
261
|
phases: [],
|
|
212
262
|
stories: [],
|
|
263
|
+
metrics: emptyMetrics(),
|
|
213
264
|
execution: { iteration: 0, retries: 0, correctionCycle: 0, maxCorrectionCycles: null },
|
|
214
265
|
git: { branch: null, baseBranch: null, commits: [] },
|
|
215
266
|
pullRequests: [],
|
|
@@ -221,6 +272,19 @@ function createInitialSnapshot() {
|
|
|
221
272
|
environment: null
|
|
222
273
|
};
|
|
223
274
|
}
|
|
275
|
+
function accumulate(current, delta) {
|
|
276
|
+
return delta === void 0 ? current : (current ?? 0) + delta;
|
|
277
|
+
}
|
|
278
|
+
function accumulateUsage(target, event) {
|
|
279
|
+
return {
|
|
280
|
+
...target,
|
|
281
|
+
inputTokens: accumulate(target.inputTokens, event.inputTokens),
|
|
282
|
+
outputTokens: accumulate(target.outputTokens, event.outputTokens),
|
|
283
|
+
cacheReadTokens: accumulate(target.cacheReadTokens, event.cacheReadTokens),
|
|
284
|
+
cacheCreationTokens: accumulate(target.cacheCreationTokens, event.cacheCreationTokens),
|
|
285
|
+
costUsd: accumulate(target.costUsd, event.costUsd)
|
|
286
|
+
};
|
|
287
|
+
}
|
|
224
288
|
function secondsBetween(from, to) {
|
|
225
289
|
if (from === null) return null;
|
|
226
290
|
const fromMs = Date.parse(from);
|
|
@@ -284,7 +348,8 @@ function applyEvent(snapshot, event, options) {
|
|
|
284
348
|
startedAt: null,
|
|
285
349
|
endedAt: null,
|
|
286
350
|
durationSeconds: null,
|
|
287
|
-
error: null
|
|
351
|
+
error: null,
|
|
352
|
+
...emptyUsage()
|
|
288
353
|
})),
|
|
289
354
|
git: { branch: event.branch ?? null, baseBranch: event.baseBranch ?? null, commits: [] },
|
|
290
355
|
environment: event.environment ?? null
|
|
@@ -308,7 +373,8 @@ function applyEvent(snapshot, event, options) {
|
|
|
308
373
|
startedAt: event.at,
|
|
309
374
|
endedAt: null,
|
|
310
375
|
durationSeconds: null,
|
|
311
|
-
error: null
|
|
376
|
+
error: null,
|
|
377
|
+
...emptyUsage()
|
|
312
378
|
}
|
|
313
379
|
];
|
|
314
380
|
return {
|
|
@@ -363,7 +429,13 @@ function applyEvent(snapshot, event, options) {
|
|
|
363
429
|
title: story.title,
|
|
364
430
|
priority: story.priority,
|
|
365
431
|
passes: story.passes,
|
|
366
|
-
completedAt
|
|
432
|
+
completedAt,
|
|
433
|
+
durationSeconds: before?.durationSeconds ?? null,
|
|
434
|
+
inputTokens: before?.inputTokens ?? null,
|
|
435
|
+
outputTokens: before?.outputTokens ?? null,
|
|
436
|
+
cacheReadTokens: before?.cacheReadTokens ?? null,
|
|
437
|
+
cacheCreationTokens: before?.cacheCreationTokens ?? null,
|
|
438
|
+
costUsd: before?.costUsd ?? null
|
|
367
439
|
};
|
|
368
440
|
});
|
|
369
441
|
return {
|
|
@@ -413,6 +485,44 @@ function applyEvent(snapshot, event, options) {
|
|
|
413
485
|
maxCorrectionCycles: event.maxCycles
|
|
414
486
|
}
|
|
415
487
|
};
|
|
488
|
+
case "metrics:update": {
|
|
489
|
+
if (event.scope === "story") {
|
|
490
|
+
if (event.storyId === void 0) return snapshot;
|
|
491
|
+
if (!snapshot.stories.some((s) => s.id === event.storyId)) return snapshot;
|
|
492
|
+
return {
|
|
493
|
+
...snapshot,
|
|
494
|
+
stories: snapshot.stories.map(
|
|
495
|
+
(story) => story.id === event.storyId ? {
|
|
496
|
+
...accumulateUsage(story, event),
|
|
497
|
+
durationSeconds: accumulate(story.durationSeconds, event.durationSeconds)
|
|
498
|
+
} : story
|
|
499
|
+
)
|
|
500
|
+
};
|
|
501
|
+
}
|
|
502
|
+
if (event.phase === void 0) return snapshot;
|
|
503
|
+
if (!snapshot.phases.some((p) => p.name === event.phase)) return snapshot;
|
|
504
|
+
return {
|
|
505
|
+
...snapshot,
|
|
506
|
+
// durationSeconds is deliberately untouched here: phase:start and
|
|
507
|
+
// phase:end remain the single source of a phase's wall-clock time.
|
|
508
|
+
phases: snapshot.phases.map(
|
|
509
|
+
(phase) => phase.name === event.phase ? accumulateUsage(phase, event) : phase
|
|
510
|
+
),
|
|
511
|
+
metrics: {
|
|
512
|
+
totalInputTokens: accumulate(snapshot.metrics.totalInputTokens, event.inputTokens),
|
|
513
|
+
totalOutputTokens: accumulate(snapshot.metrics.totalOutputTokens, event.outputTokens),
|
|
514
|
+
totalCacheReadTokens: accumulate(
|
|
515
|
+
snapshot.metrics.totalCacheReadTokens,
|
|
516
|
+
event.cacheReadTokens
|
|
517
|
+
),
|
|
518
|
+
totalCacheCreationTokens: accumulate(
|
|
519
|
+
snapshot.metrics.totalCacheCreationTokens,
|
|
520
|
+
event.cacheCreationTokens
|
|
521
|
+
),
|
|
522
|
+
totalCostUsd: accumulate(snapshot.metrics.totalCostUsd, event.costUsd)
|
|
523
|
+
}
|
|
524
|
+
};
|
|
525
|
+
}
|
|
416
526
|
case "session:end":
|
|
417
527
|
return {
|
|
418
528
|
...snapshot,
|
|
@@ -599,6 +709,86 @@ async function writeFileAtomic(path, content) {
|
|
|
599
709
|
}
|
|
600
710
|
}
|
|
601
711
|
|
|
712
|
+
// src/core/metrics.ts
|
|
713
|
+
var USAGE_FIELDS = [
|
|
714
|
+
"inputTokens",
|
|
715
|
+
"outputTokens",
|
|
716
|
+
"cacheReadTokens",
|
|
717
|
+
"cacheCreationTokens",
|
|
718
|
+
"costUsd"
|
|
719
|
+
];
|
|
720
|
+
function num(value) {
|
|
721
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
722
|
+
}
|
|
723
|
+
function isRecord(value) {
|
|
724
|
+
return typeof value === "object" && value !== null;
|
|
725
|
+
}
|
|
726
|
+
function parseUsage(payload) {
|
|
727
|
+
if (!isRecord(payload)) return null;
|
|
728
|
+
const usageRaw = isRecord(payload.usage) ? payload.usage : void 0;
|
|
729
|
+
const usage = {};
|
|
730
|
+
const inputTokens = usageRaw ? num(usageRaw.input_tokens) : void 0;
|
|
731
|
+
const outputTokens = usageRaw ? num(usageRaw.output_tokens) : void 0;
|
|
732
|
+
const cacheReadTokens = usageRaw ? num(usageRaw.cache_read_input_tokens) : void 0;
|
|
733
|
+
const cacheCreationTokens = usageRaw ? num(usageRaw.cache_creation_input_tokens) : void 0;
|
|
734
|
+
const costUsd = num(payload.total_cost_usd);
|
|
735
|
+
const legacyInput = num(payload.num_input_tokens);
|
|
736
|
+
const legacyOutput = num(payload.num_output_tokens);
|
|
737
|
+
const legacyCost = num(payload.cost_usd);
|
|
738
|
+
const resolvedInput = inputTokens ?? legacyInput;
|
|
739
|
+
const resolvedOutput = outputTokens ?? legacyOutput;
|
|
740
|
+
const resolvedCost = costUsd ?? legacyCost;
|
|
741
|
+
if (resolvedInput !== void 0) usage.inputTokens = resolvedInput;
|
|
742
|
+
if (resolvedOutput !== void 0) usage.outputTokens = resolvedOutput;
|
|
743
|
+
if (cacheReadTokens !== void 0) usage.cacheReadTokens = cacheReadTokens;
|
|
744
|
+
if (cacheCreationTokens !== void 0) usage.cacheCreationTokens = cacheCreationTokens;
|
|
745
|
+
if (resolvedCost !== void 0) usage.costUsd = resolvedCost;
|
|
746
|
+
return Object.keys(usage).length > 0 ? usage : null;
|
|
747
|
+
}
|
|
748
|
+
function sumUsage(a, b) {
|
|
749
|
+
const result = {};
|
|
750
|
+
for (const field of USAGE_FIELDS) {
|
|
751
|
+
const left = a?.[field];
|
|
752
|
+
const right = b?.[field];
|
|
753
|
+
if (left === void 0 && right === void 0) continue;
|
|
754
|
+
result[field] = (left ?? 0) + (right ?? 0);
|
|
755
|
+
}
|
|
756
|
+
return result;
|
|
757
|
+
}
|
|
758
|
+
function divideUsage(usage, parts) {
|
|
759
|
+
const result = {};
|
|
760
|
+
if (!usage) return result;
|
|
761
|
+
const divisor = Number.isFinite(parts) && parts > 1 ? parts : 1;
|
|
762
|
+
for (const field of USAGE_FIELDS) {
|
|
763
|
+
const value = usage[field];
|
|
764
|
+
if (value === void 0) continue;
|
|
765
|
+
result[field] = field === "costUsd" ? value / divisor : Math.round(value / divisor);
|
|
766
|
+
}
|
|
767
|
+
return result;
|
|
768
|
+
}
|
|
769
|
+
function compactTokens(value) {
|
|
770
|
+
const abs = Math.abs(value);
|
|
771
|
+
if (abs >= 1e6) return `${(value / 1e6).toFixed(1)}M`;
|
|
772
|
+
if (abs >= 1e3) return `${(value / 1e3).toFixed(1)}k`;
|
|
773
|
+
return String(Math.round(value));
|
|
774
|
+
}
|
|
775
|
+
function formatTokens(usage) {
|
|
776
|
+
if (!usage) return "";
|
|
777
|
+
const segments = [];
|
|
778
|
+
const io = [];
|
|
779
|
+
if (usage.inputTokens !== void 0) io.push(`${compactTokens(usage.inputTokens)} in`);
|
|
780
|
+
if (usage.outputTokens !== void 0) io.push(`${compactTokens(usage.outputTokens)} out`);
|
|
781
|
+
if (io.length > 0) segments.push(io.join(" / "));
|
|
782
|
+
const cache = usage.cacheReadTokens !== void 0 || usage.cacheCreationTokens !== void 0 ? (usage.cacheReadTokens ?? 0) + (usage.cacheCreationTokens ?? 0) : void 0;
|
|
783
|
+
if (cache !== void 0) segments.push(`${compactTokens(cache)} cache`);
|
|
784
|
+
if (usage.costUsd !== void 0) segments.push(`~$${usage.costUsd.toFixed(4)}`);
|
|
785
|
+
return segments.join(" \xB7 ");
|
|
786
|
+
}
|
|
787
|
+
function hasUsageData(usage) {
|
|
788
|
+
if (!usage) return false;
|
|
789
|
+
return USAGE_FIELDS.some((field) => usage[field] !== void 0);
|
|
790
|
+
}
|
|
791
|
+
|
|
602
792
|
// src/core/state-manager.ts
|
|
603
793
|
function isoNow() {
|
|
604
794
|
return (/* @__PURE__ */ new Date()).toISOString().replace(/\.\d{3}Z$/, "Z");
|
|
@@ -650,6 +840,21 @@ function allStoriesPass(plan) {
|
|
|
650
840
|
}
|
|
651
841
|
return plan.userStories.every((story) => story.passes === true);
|
|
652
842
|
}
|
|
843
|
+
function applyStoryMetrics(plan, storyIds, share, durationSeconds) {
|
|
844
|
+
if (storyIds.length === 0) return plan;
|
|
845
|
+
const targets = new Set(storyIds);
|
|
846
|
+
return {
|
|
847
|
+
...plan,
|
|
848
|
+
userStories: plan.userStories.map((story) => {
|
|
849
|
+
if (!targets.has(story.id)) return story;
|
|
850
|
+
const updated = { ...story, ...sumUsage(story, share) };
|
|
851
|
+
if (story.durationSeconds !== void 0 || durationSeconds !== void 0) {
|
|
852
|
+
updated.durationSeconds = (story.durationSeconds ?? 0) + (durationSeconds ?? 0);
|
|
853
|
+
}
|
|
854
|
+
return updated;
|
|
855
|
+
})
|
|
856
|
+
};
|
|
857
|
+
}
|
|
653
858
|
function markIssueInProgress(plan, timestamp) {
|
|
654
859
|
const ts = timestamp ?? isoNow();
|
|
655
860
|
return {
|
|
@@ -848,6 +1053,7 @@ var ElapsedTimer = class {
|
|
|
848
1053
|
this.onTick = onTick;
|
|
849
1054
|
this.startTime = Date.now();
|
|
850
1055
|
}
|
|
1056
|
+
onTick;
|
|
851
1057
|
startTime;
|
|
852
1058
|
intervalId = null;
|
|
853
1059
|
cleanup = () => this.stop();
|
|
@@ -887,12 +1093,18 @@ export {
|
|
|
887
1093
|
setSessionPublisher,
|
|
888
1094
|
getSessionPublisher,
|
|
889
1095
|
writeFileAtomic,
|
|
1096
|
+
parseUsage,
|
|
1097
|
+
sumUsage,
|
|
1098
|
+
divideUsage,
|
|
1099
|
+
formatTokens,
|
|
1100
|
+
hasUsageData,
|
|
890
1101
|
isoNow,
|
|
891
1102
|
loadTaskPlan,
|
|
892
1103
|
saveTaskPlan,
|
|
893
1104
|
initializeState,
|
|
894
1105
|
hasPendingCorrection,
|
|
895
1106
|
allStoriesPass,
|
|
1107
|
+
applyStoryMetrics,
|
|
896
1108
|
markIssueInProgress,
|
|
897
1109
|
markIssueCompleted,
|
|
898
1110
|
setLastError,
|
|
@@ -919,4 +1131,4 @@ export {
|
|
|
919
1131
|
formatDuration,
|
|
920
1132
|
ElapsedTimer
|
|
921
1133
|
};
|
|
922
|
-
//# sourceMappingURL=chunk-
|
|
1134
|
+
//# sourceMappingURL=chunk-6HGZYTAT.js.map
|