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
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
getSessionPublisher
|
|
4
|
+
} from "./chunk-6QYMSNVA.js";
|
|
5
|
+
import {
|
|
6
|
+
writeDiagnostic
|
|
7
|
+
} from "./chunk-3WFZETIM.js";
|
|
8
|
+
import {
|
|
9
|
+
isoNow
|
|
10
|
+
} from "./chunk-J3SOTUVI.js";
|
|
11
|
+
|
|
12
|
+
// src/core/verbose.ts
|
|
13
|
+
var _verbose = false;
|
|
14
|
+
function setVerbose(enabled) {
|
|
15
|
+
_verbose = enabled;
|
|
16
|
+
}
|
|
17
|
+
function isVerbose() {
|
|
18
|
+
return _verbose;
|
|
19
|
+
}
|
|
20
|
+
var _onOutput;
|
|
21
|
+
function setOutputCallback(callback) {
|
|
22
|
+
_onOutput = callback;
|
|
23
|
+
}
|
|
24
|
+
function getOutputCallback() {
|
|
25
|
+
return _onOutput;
|
|
26
|
+
}
|
|
27
|
+
var _onStoryUpdate;
|
|
28
|
+
function setStoryUpdateCallback(callback) {
|
|
29
|
+
_onStoryUpdate = callback;
|
|
30
|
+
}
|
|
31
|
+
function getStoryUpdateCallback() {
|
|
32
|
+
return _onStoryUpdate;
|
|
33
|
+
}
|
|
34
|
+
var _onStoryStage;
|
|
35
|
+
function setStoryStageCallback(callback) {
|
|
36
|
+
_onStoryStage = callback;
|
|
37
|
+
}
|
|
38
|
+
function getStoryStageCallback() {
|
|
39
|
+
return _onStoryStage;
|
|
40
|
+
}
|
|
41
|
+
var _onActivity;
|
|
42
|
+
function setActivityCallback(callback) {
|
|
43
|
+
_onActivity = callback;
|
|
44
|
+
}
|
|
45
|
+
function getActivityCallback() {
|
|
46
|
+
return _onActivity;
|
|
47
|
+
}
|
|
48
|
+
var _globalTimeout;
|
|
49
|
+
function setGlobalTimeout(ms) {
|
|
50
|
+
_globalTimeout = ms;
|
|
51
|
+
}
|
|
52
|
+
function getGlobalTimeout() {
|
|
53
|
+
return _globalTimeout;
|
|
54
|
+
}
|
|
55
|
+
var _inactivityTimeout;
|
|
56
|
+
function setInactivityTimeout(ms) {
|
|
57
|
+
_inactivityTimeout = ms;
|
|
58
|
+
}
|
|
59
|
+
function getInactivityTimeout() {
|
|
60
|
+
return _inactivityTimeout;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// src/ui/logger.ts
|
|
64
|
+
import chalk from "chalk";
|
|
65
|
+
import ora from "ora";
|
|
66
|
+
function useUnicode() {
|
|
67
|
+
if (process.env.NO_COLOR != null && process.env.NO_COLOR !== "") return false;
|
|
68
|
+
if (!process.stdout.isTTY) return false;
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
function useColor() {
|
|
72
|
+
if (process.env.NO_COLOR != null && process.env.NO_COLOR !== "") return false;
|
|
73
|
+
if (!process.stdout.isTTY) return false;
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
function getIcons() {
|
|
77
|
+
if (useUnicode()) {
|
|
78
|
+
return {
|
|
79
|
+
success: "\u2713",
|
|
80
|
+
fail: "\u2717",
|
|
81
|
+
pending: "\u23F3",
|
|
82
|
+
retry: "\u21BB",
|
|
83
|
+
warn: "\u26A0",
|
|
84
|
+
start: "\u25B6",
|
|
85
|
+
end: "\u25A0",
|
|
86
|
+
notReached: "\u25CB",
|
|
87
|
+
tool: "\u25B8",
|
|
88
|
+
connector: "\u2502",
|
|
89
|
+
info: "\xB7"
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
return {
|
|
93
|
+
success: "[OK]",
|
|
94
|
+
fail: "[FAIL]",
|
|
95
|
+
pending: "[...]",
|
|
96
|
+
retry: "[RETRY]",
|
|
97
|
+
warn: "[WARN]",
|
|
98
|
+
start: "[START]",
|
|
99
|
+
end: "[END]",
|
|
100
|
+
notReached: "[ ]",
|
|
101
|
+
tool: ">",
|
|
102
|
+
connector: "|",
|
|
103
|
+
info: "-"
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
function getTermWidth() {
|
|
107
|
+
return process.stdout.columns ?? 80;
|
|
108
|
+
}
|
|
109
|
+
function emit(line, level = "info") {
|
|
110
|
+
getSessionPublisher().publish({ type: "log", at: isoNow(), level, message: line });
|
|
111
|
+
writeDiagnostic({
|
|
112
|
+
level: level === "warn" ? "warning" : level,
|
|
113
|
+
message: line
|
|
114
|
+
});
|
|
115
|
+
const cb = getOutputCallback();
|
|
116
|
+
if (cb) {
|
|
117
|
+
cb(line);
|
|
118
|
+
} else {
|
|
119
|
+
console.log(line);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
function printSuccess(message) {
|
|
123
|
+
const icons = getIcons();
|
|
124
|
+
if (useColor()) {
|
|
125
|
+
emit(chalk.green(`${icons.success} ${message}`));
|
|
126
|
+
} else {
|
|
127
|
+
emit(`${icons.success} ${message}`);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
function printError(message) {
|
|
131
|
+
const icons = getIcons();
|
|
132
|
+
if (useColor()) {
|
|
133
|
+
emit(chalk.red(`${icons.fail} ${message}`), "error");
|
|
134
|
+
} else {
|
|
135
|
+
emit(`${icons.fail} ${message}`, "error");
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
function printWarning(message) {
|
|
139
|
+
const icons = getIcons();
|
|
140
|
+
if (useColor()) {
|
|
141
|
+
emit(chalk.yellow(`${icons.warn} ${message}`), "warn");
|
|
142
|
+
} else {
|
|
143
|
+
emit(`${icons.warn} ${message}`, "warn");
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
function printRetry(message) {
|
|
147
|
+
const icons = getIcons();
|
|
148
|
+
if (useColor()) {
|
|
149
|
+
emit(chalk.yellow(`${icons.retry} ${message}`), "warn");
|
|
150
|
+
} else {
|
|
151
|
+
emit(`${icons.retry} ${message}`, "warn");
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
function printInfo(message) {
|
|
155
|
+
const icons = getIcons();
|
|
156
|
+
if (useColor()) {
|
|
157
|
+
emit(chalk.blue(`${icons.info} ${message}`));
|
|
158
|
+
} else {
|
|
159
|
+
emit(`${icons.info} ${message}`);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
function createSpinner(message) {
|
|
163
|
+
return ora({
|
|
164
|
+
text: message,
|
|
165
|
+
color: "blue",
|
|
166
|
+
spinner: "dots"
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
function formatDuration(totalSeconds) {
|
|
170
|
+
const hours = Math.floor(totalSeconds / 3600);
|
|
171
|
+
const mins = Math.floor(totalSeconds % 3600 / 60);
|
|
172
|
+
const secs = totalSeconds % 60;
|
|
173
|
+
if (hours > 0) {
|
|
174
|
+
return `${hours}h ${mins}m ${secs}s`;
|
|
175
|
+
}
|
|
176
|
+
if (mins > 0) {
|
|
177
|
+
return `${mins}m ${secs}s`;
|
|
178
|
+
}
|
|
179
|
+
return `${secs}s`;
|
|
180
|
+
}
|
|
181
|
+
var ElapsedTimer = class {
|
|
182
|
+
constructor(onTick) {
|
|
183
|
+
this.onTick = onTick;
|
|
184
|
+
this.startTime = Date.now();
|
|
185
|
+
}
|
|
186
|
+
onTick;
|
|
187
|
+
startTime;
|
|
188
|
+
intervalId = null;
|
|
189
|
+
cleanup = () => this.stop();
|
|
190
|
+
start() {
|
|
191
|
+
this.startTime = Date.now();
|
|
192
|
+
this.intervalId = setInterval(() => {
|
|
193
|
+
const seconds = Math.floor((Date.now() - this.startTime) / 1e3);
|
|
194
|
+
this.onTick(formatDuration(seconds));
|
|
195
|
+
}, 1e3);
|
|
196
|
+
if (this.intervalId && typeof this.intervalId === "object" && "unref" in this.intervalId) {
|
|
197
|
+
this.intervalId.unref();
|
|
198
|
+
}
|
|
199
|
+
process.on("exit", this.cleanup);
|
|
200
|
+
return this;
|
|
201
|
+
}
|
|
202
|
+
getElapsedSeconds() {
|
|
203
|
+
return Math.floor((Date.now() - this.startTime) / 1e3);
|
|
204
|
+
}
|
|
205
|
+
stop() {
|
|
206
|
+
if (this.intervalId) {
|
|
207
|
+
clearInterval(this.intervalId);
|
|
208
|
+
this.intervalId = null;
|
|
209
|
+
}
|
|
210
|
+
process.removeListener("exit", this.cleanup);
|
|
211
|
+
return this.getElapsedSeconds();
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
export {
|
|
216
|
+
setVerbose,
|
|
217
|
+
isVerbose,
|
|
218
|
+
setOutputCallback,
|
|
219
|
+
getOutputCallback,
|
|
220
|
+
setStoryUpdateCallback,
|
|
221
|
+
getStoryUpdateCallback,
|
|
222
|
+
setStoryStageCallback,
|
|
223
|
+
getStoryStageCallback,
|
|
224
|
+
setActivityCallback,
|
|
225
|
+
getActivityCallback,
|
|
226
|
+
setGlobalTimeout,
|
|
227
|
+
getGlobalTimeout,
|
|
228
|
+
setInactivityTimeout,
|
|
229
|
+
getInactivityTimeout,
|
|
230
|
+
useUnicode,
|
|
231
|
+
useColor,
|
|
232
|
+
getIcons,
|
|
233
|
+
getTermWidth,
|
|
234
|
+
printSuccess,
|
|
235
|
+
printError,
|
|
236
|
+
printWarning,
|
|
237
|
+
printRetry,
|
|
238
|
+
printInfo,
|
|
239
|
+
createSpinner,
|
|
240
|
+
formatDuration,
|
|
241
|
+
ElapsedTimer
|
|
242
|
+
};
|
|
243
|
+
//# sourceMappingURL=chunk-TYRNTSPJ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/verbose.ts","../src/ui/logger.ts"],"sourcesContent":["let _verbose = false;\n\nexport function setVerbose(enabled: boolean): void {\n _verbose = enabled;\n}\n\nexport function isVerbose(): boolean {\n return _verbose;\n}\n\nlet _onOutput: ((line: string) => void) | undefined;\n\n/**\n * Set a global output callback for routing verbose output (e.g., through listr2 task.output).\n * Pass undefined to clear and fall back to direct stderr writes.\n */\nexport function setOutputCallback(callback: ((line: string) => void) | undefined): void {\n _onOutput = callback;\n}\n\nexport function getOutputCallback(): ((line: string) => void) | undefined {\n return _onOutput;\n}\n\nlet _onStoryUpdate: ((stories: import('../types.js').UserStory[]) => void) | undefined;\n\n/**\n * Set a global callback for story progress updates during engine execution.\n * Called after each iteration with the latest user stories state.\n * Pass undefined to clear.\n */\nexport function setStoryUpdateCallback(\n callback: ((stories: import('../types.js').UserStory[]) => void) | undefined,\n): void {\n _onStoryUpdate = callback;\n}\n\nexport function getStoryUpdateCallback():\n | ((stories: import('../types.js').UserStory[]) => void)\n | undefined {\n return _onStoryUpdate;\n}\n\nlet _onStoryStage: ((storyId: string | undefined) => void) | undefined;\n\n/**\n * Set a global callback for the active story of the current `execute`\n * iteration. Called by `core/engine.ts` alongside every `iteration:start`\n * publication, with the same `storyId` (or `undefined` once every story\n * already passes) — the terminal renderer's only source for \"who is\n * executing right now\", never a second, independently computed heuristic.\n * Pass `undefined` to clear.\n */\nexport function setStoryStageCallback(\n callback: ((storyId: string | undefined) => void) | undefined,\n): void {\n _onStoryStage = callback;\n}\n\nexport function getStoryStageCallback(): ((storyId: string | undefined) => void) | undefined {\n return _onStoryStage;\n}\n\nexport interface ActivityNotice {\n tool: string;\n detail?: string;\n}\n\nlet _onActivity: ((notice: ActivityNotice) => void) | undefined;\n\n/**\n * Live tool activity for the clean terminal view. Published in every mode,\n * including non-verbose — the snapshot's `currentActivity` and the dashboard\n * both read the same event.\n */\nexport function setActivityCallback(\n callback: ((notice: ActivityNotice) => void) | undefined,\n): void {\n _onActivity = callback;\n}\n\nexport function getActivityCallback(): ((notice: ActivityNotice) => void) | undefined {\n return _onActivity;\n}\n\nlet _globalTimeout: number | undefined;\n\nexport function setGlobalTimeout(ms: number): void {\n _globalTimeout = ms;\n}\n\nexport function getGlobalTimeout(): number | undefined {\n return _globalTimeout;\n}\n\n/**\n * Silence tolerated before an agent is considered stuck, in milliseconds.\n *\n * Global for the same reason the timeout is: every phase invokes the CLI\n * through the same two functions, and threading it through each one of them\n * would be a parameter with a single value per process. `undefined` leaves the\n * default; `0` turns the watchdog off.\n */\nlet _inactivityTimeout: number | undefined;\n\nexport function setInactivityTimeout(ms: number): void {\n _inactivityTimeout = ms;\n}\n\nexport function getInactivityTimeout(): number | undefined {\n return _inactivityTimeout;\n}\n","import chalk from 'chalk';\nimport ora, { type Ora } from 'ora';\nimport { getSessionPublisher } from '../core/session-publisher.js';\nimport type { SessionLogLevel } from '../core/session-state.js';\nimport { isoNow } from '../core/state-manager.js';\nimport { getOutputCallback } from '../core/verbose.js';\nimport { writeDiagnostic } from '../storage/diagnostics.js';\n\n/**\n * Detect if unicode output is supported.\n */\nexport function useUnicode(): boolean {\n if (process.env.NO_COLOR != null && process.env.NO_COLOR !== '') return false;\n if (!process.stdout.isTTY) return false;\n return true;\n}\n\n/**\n * Detect if color output is supported.\n */\nexport function useColor(): boolean {\n if (process.env.NO_COLOR != null && process.env.NO_COLOR !== '') return false;\n if (!process.stdout.isTTY) return false;\n return true;\n}\n\nexport interface Icons {\n success: string;\n fail: string;\n pending: string;\n retry: string;\n warn: string;\n start: string;\n end: string;\n notReached: string;\n tool: string;\n connector: string;\n info: string;\n}\n\nexport function getIcons(): Icons {\n if (useUnicode()) {\n return {\n success: '\\u2713',\n fail: '\\u2717',\n pending: '\\u23F3',\n retry: '\\u21BB',\n warn: '\\u26A0',\n start: '\\u25B6',\n end: '\\u25A0',\n notReached: '\\u25CB',\n tool: '\\u25B8',\n connector: '\\u2502',\n info: '\\u00B7',\n };\n }\n return {\n success: '[OK]',\n fail: '[FAIL]',\n pending: '[...]',\n retry: '[RETRY]',\n warn: '[WARN]',\n start: '[START]',\n end: '[END]',\n notReached: '[ ]',\n tool: '>',\n connector: '|',\n info: '-',\n };\n}\n\n/**\n * Get the terminal width.\n */\nexport function getTermWidth(): number {\n return process.stdout.columns ?? 80;\n}\n\n/**\n * Emit a line of output. Routes through the global output callback when\n * running inside a listr2 task context, otherwise falls back to console.log.\n *\n * Also forwards the line to the session publisher with its structured level;\n * ANSI codes are stripped by the reducer, so terminal output stays untouched.\n */\nfunction emit(line: string, level: SessionLogLevel = 'info'): void {\n getSessionPublisher().publish({ type: 'log', at: isoNow(), level, message: line });\n writeDiagnostic({\n level: level === 'warn' ? 'warning' : level,\n message: line,\n });\n const cb = getOutputCallback();\n if (cb) {\n cb(line);\n } else {\n console.log(line);\n }\n}\n\nexport function printSuccess(message: string): void {\n const icons = getIcons();\n if (useColor()) {\n emit(chalk.green(`${icons.success} ${message}`));\n } else {\n emit(`${icons.success} ${message}`);\n }\n}\n\nexport function printError(message: string): void {\n const icons = getIcons();\n if (useColor()) {\n emit(chalk.red(`${icons.fail} ${message}`), 'error');\n } else {\n emit(`${icons.fail} ${message}`, 'error');\n }\n}\n\nexport function printWarning(message: string): void {\n const icons = getIcons();\n if (useColor()) {\n emit(chalk.yellow(`${icons.warn} ${message}`), 'warn');\n } else {\n emit(`${icons.warn} ${message}`, 'warn');\n }\n}\n\nexport function printRetry(message: string): void {\n const icons = getIcons();\n if (useColor()) {\n emit(chalk.yellow(`${icons.retry} ${message}`), 'warn');\n } else {\n emit(`${icons.retry} ${message}`, 'warn');\n }\n}\n\nexport function printInfo(message: string): void {\n const icons = getIcons();\n if (useColor()) {\n emit(chalk.blue(`${icons.info} ${message}`));\n } else {\n emit(`${icons.info} ${message}`);\n }\n}\n\n/**\n * Create an ora spinner with consistent styling.\n */\nexport function createSpinner(message: string): Ora {\n return ora({\n text: message,\n color: 'blue',\n spinner: 'dots',\n });\n}\n\n/**\n * Format a duration in seconds to a human-readable string.\n */\nexport function formatDuration(totalSeconds: number): string {\n const hours = Math.floor(totalSeconds / 3600);\n const mins = Math.floor((totalSeconds % 3600) / 60);\n const secs = totalSeconds % 60;\n\n if (hours > 0) {\n return `${hours}h ${mins}m ${secs}s`;\n }\n if (mins > 0) {\n return `${mins}m ${secs}s`;\n }\n return `${secs}s`;\n}\n\n/**\n * Timer that calls a callback every second with the formatted elapsed time.\n */\nexport class ElapsedTimer {\n private startTime: number;\n private intervalId: ReturnType<typeof setInterval> | null = null;\n private cleanup = () => this.stop();\n\n constructor(private onTick: (elapsed: string) => void) {\n this.startTime = Date.now();\n }\n\n start(): this {\n this.startTime = Date.now();\n this.intervalId = setInterval(() => {\n const seconds = Math.floor((Date.now() - this.startTime) / 1000);\n this.onTick(formatDuration(seconds));\n }, 1_000);\n // Prevent the timer from keeping the process alive\n if (this.intervalId && typeof this.intervalId === 'object' && 'unref' in this.intervalId) {\n this.intervalId.unref();\n }\n process.on('exit', this.cleanup);\n return this;\n }\n\n getElapsedSeconds(): number {\n return Math.floor((Date.now() - this.startTime) / 1000);\n }\n\n stop(): number {\n if (this.intervalId) {\n clearInterval(this.intervalId);\n this.intervalId = null;\n }\n process.removeListener('exit', this.cleanup);\n return this.getElapsedSeconds();\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
GLOBAL_CONFIG_FILENAME,
|
|
4
|
+
PROJECT_CONFIG_FILENAME,
|
|
5
|
+
describeRunAgents,
|
|
6
|
+
loadAgentConfig,
|
|
7
|
+
probeAgent
|
|
8
|
+
} from "./chunk-QJ5UZAH5.js";
|
|
9
|
+
import {
|
|
10
|
+
printError,
|
|
11
|
+
printSuccess
|
|
12
|
+
} from "./chunk-TYRNTSPJ.js";
|
|
13
|
+
import {
|
|
14
|
+
getGlobalRoot
|
|
15
|
+
} from "./chunk-HAKDLR6N.js";
|
|
16
|
+
import {
|
|
17
|
+
getProjectRoot
|
|
18
|
+
} from "./chunk-BEZ5BA5U.js";
|
|
19
|
+
import {
|
|
20
|
+
AGENT_PHASES,
|
|
21
|
+
AGENT_SCHEMA_VERSION,
|
|
22
|
+
isAgentPhase,
|
|
23
|
+
isAgentProviderId
|
|
24
|
+
} from "./chunk-LBGHI4S2.js";
|
|
25
|
+
import {
|
|
26
|
+
writeFileAtomic
|
|
27
|
+
} from "./chunk-7Z4Y3VKM.js";
|
|
28
|
+
|
|
29
|
+
// src/commands/agent.ts
|
|
30
|
+
import { mkdir, readFile } from "fs/promises";
|
|
31
|
+
import { dirname, join } from "path";
|
|
32
|
+
var AGENT_COMMAND_SCHEMA_VERSION = AGENT_SCHEMA_VERSION;
|
|
33
|
+
function originLabel(origin) {
|
|
34
|
+
switch (origin) {
|
|
35
|
+
case "default":
|
|
36
|
+
return "default";
|
|
37
|
+
case "global":
|
|
38
|
+
return "~/.issue-flow/config.json";
|
|
39
|
+
case "project":
|
|
40
|
+
return ".issue-flow.json";
|
|
41
|
+
case "env":
|
|
42
|
+
return "ISSUE_FLOW_*";
|
|
43
|
+
case "cli":
|
|
44
|
+
return "CLI";
|
|
45
|
+
default:
|
|
46
|
+
return origin;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
function formatPhaseLine(phase, provider, model, origin, inherited) {
|
|
50
|
+
const modelBit = model ? ` \xB7 ${model}` : "";
|
|
51
|
+
const source = inherited ? "herdado do padr\xE3o" : originLabel(origin);
|
|
52
|
+
return `${` ${phase.padEnd(12)} ${provider}${modelBit}`.padEnd(40)}(${source})`;
|
|
53
|
+
}
|
|
54
|
+
async function runAgent(options = {}) {
|
|
55
|
+
const config = await loadAgentConfig();
|
|
56
|
+
const summary = await describeRunAgents();
|
|
57
|
+
const [claude, codex, cursor, antigravity] = await Promise.all([
|
|
58
|
+
probeAgent("claude"),
|
|
59
|
+
probeAgent("codex"),
|
|
60
|
+
probeAgent("cursor"),
|
|
61
|
+
probeAgent("antigravity")
|
|
62
|
+
]);
|
|
63
|
+
if (options.json === true) {
|
|
64
|
+
const phases = {};
|
|
65
|
+
for (const phase of AGENT_PHASES) {
|
|
66
|
+
const resolved = summary.byPhase[phase];
|
|
67
|
+
const inherited = config.phases[phase] === void 0;
|
|
68
|
+
phases[phase] = {
|
|
69
|
+
provider: resolved.provider,
|
|
70
|
+
model: resolved.model,
|
|
71
|
+
origin: resolved.origin,
|
|
72
|
+
inherited
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
console.log(
|
|
76
|
+
JSON.stringify(
|
|
77
|
+
{
|
|
78
|
+
schemaVersion: AGENT_COMMAND_SCHEMA_VERSION,
|
|
79
|
+
default: {
|
|
80
|
+
provider: summary.defaultProvider,
|
|
81
|
+
model: summary.defaultModel,
|
|
82
|
+
origin: summary.defaultOrigin
|
|
83
|
+
},
|
|
84
|
+
phases,
|
|
85
|
+
availability: [
|
|
86
|
+
{
|
|
87
|
+
id: "claude",
|
|
88
|
+
installed: claude.installed,
|
|
89
|
+
version: claude.version,
|
|
90
|
+
authenticated: claude.authenticated
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
id: "codex",
|
|
94
|
+
installed: codex.installed,
|
|
95
|
+
version: codex.version,
|
|
96
|
+
authenticated: codex.authenticated
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
id: "cursor",
|
|
100
|
+
installed: cursor.installed,
|
|
101
|
+
version: cursor.version,
|
|
102
|
+
authenticated: cursor.authenticated
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
id: "antigravity",
|
|
106
|
+
installed: antigravity.installed,
|
|
107
|
+
version: antigravity.version,
|
|
108
|
+
authenticated: antigravity.authenticated,
|
|
109
|
+
authProbe: "none"
|
|
110
|
+
}
|
|
111
|
+
]
|
|
112
|
+
},
|
|
113
|
+
null,
|
|
114
|
+
2
|
|
115
|
+
)
|
|
116
|
+
);
|
|
117
|
+
return 0;
|
|
118
|
+
}
|
|
119
|
+
const modelLabel = summary.defaultModel ?? "(default do provider)";
|
|
120
|
+
console.log(
|
|
121
|
+
`Agente padr\xE3o ${summary.defaultProvider.padEnd(22)} (${originLabel(summary.defaultOrigin.provider)})`
|
|
122
|
+
);
|
|
123
|
+
console.log(`Modelo ${modelLabel} (${originLabel(summary.defaultOrigin.model)})`);
|
|
124
|
+
console.log("");
|
|
125
|
+
console.log("Por fase");
|
|
126
|
+
for (const phase of AGENT_PHASES) {
|
|
127
|
+
const resolved = summary.byPhase[phase];
|
|
128
|
+
const inherited = config.phases[phase] === void 0;
|
|
129
|
+
console.log(
|
|
130
|
+
formatPhaseLine(
|
|
131
|
+
phase,
|
|
132
|
+
resolved.provider,
|
|
133
|
+
resolved.model,
|
|
134
|
+
resolved.origin.provider,
|
|
135
|
+
inherited
|
|
136
|
+
)
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
console.log("");
|
|
140
|
+
console.log("Disponibilidade");
|
|
141
|
+
console.log(` claude ${(claude.version ?? "\u2014").padEnd(16)} ${claude.detail}`);
|
|
142
|
+
console.log(` codex ${(codex.version ?? "\u2014").padEnd(16)} ${codex.detail}`);
|
|
143
|
+
console.log(` cursor ${(cursor.version ?? "\u2014").padEnd(16)} ${cursor.detail}`);
|
|
144
|
+
console.log(
|
|
145
|
+
` antigravity ${(antigravity.version ?? "\u2014").padEnd(16)} ${antigravity.detail} (no auth probe)`
|
|
146
|
+
);
|
|
147
|
+
if (antigravity.installed) {
|
|
148
|
+
console.log(
|
|
149
|
+
" Warning: every Antigravity invocation passes --dangerously-skip-permissions. --mode plan is the write containment."
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
return 0;
|
|
153
|
+
}
|
|
154
|
+
async function runAgentUse(providerRaw, options = {}) {
|
|
155
|
+
if (!isAgentProviderId(providerRaw)) {
|
|
156
|
+
printError(
|
|
157
|
+
`Unknown agent provider '${providerRaw}'. Valid providers: claude, codex, cursor, antigravity.`
|
|
158
|
+
);
|
|
159
|
+
return 1;
|
|
160
|
+
}
|
|
161
|
+
const provider = providerRaw;
|
|
162
|
+
let phase;
|
|
163
|
+
if (options.phase !== void 0) {
|
|
164
|
+
if (!isAgentPhase(options.phase)) {
|
|
165
|
+
printError(
|
|
166
|
+
`Unknown agent phase '${options.phase}'. Valid phases: ${AGENT_PHASES.join(", ")}.`
|
|
167
|
+
);
|
|
168
|
+
return 1;
|
|
169
|
+
}
|
|
170
|
+
phase = options.phase;
|
|
171
|
+
}
|
|
172
|
+
const target = options.project === true ? "project" : "global";
|
|
173
|
+
try {
|
|
174
|
+
const path = await writeAgentPreference({
|
|
175
|
+
target,
|
|
176
|
+
provider,
|
|
177
|
+
model: options.model,
|
|
178
|
+
phase
|
|
179
|
+
});
|
|
180
|
+
printSuccess(`Wrote agent preference to ${path}`);
|
|
181
|
+
return 0;
|
|
182
|
+
} catch (err) {
|
|
183
|
+
printError(err instanceof Error ? err.message : String(err));
|
|
184
|
+
return 1;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
async function writeAgentPreference(input) {
|
|
188
|
+
const path = input.target === "global" ? join(getGlobalRoot(), GLOBAL_CONFIG_FILENAME) : join(input.projectRoot ?? await getProjectRoot(), PROJECT_CONFIG_FILENAME);
|
|
189
|
+
let existing = {};
|
|
190
|
+
try {
|
|
191
|
+
const raw = await readFile(path, "utf-8");
|
|
192
|
+
const parsed = JSON.parse(raw);
|
|
193
|
+
if (parsed !== null && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
194
|
+
existing = parsed;
|
|
195
|
+
}
|
|
196
|
+
} catch (err) {
|
|
197
|
+
if (err.code !== "ENOENT") {
|
|
198
|
+
throw new Error(`Could not read ${path}: ${err.message}`);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
const currentAgent = existing.agent !== null && typeof existing.agent === "object" && !Array.isArray(existing.agent) ? { ...existing.agent } : {};
|
|
202
|
+
if (input.phase) {
|
|
203
|
+
const phases = currentAgent.phases !== null && typeof currentAgent.phases === "object" && !Array.isArray(currentAgent.phases) ? { ...currentAgent.phases } : {};
|
|
204
|
+
phases[input.phase] = {
|
|
205
|
+
provider: input.provider,
|
|
206
|
+
...input.model ? { model: input.model } : {}
|
|
207
|
+
};
|
|
208
|
+
currentAgent.phases = phases;
|
|
209
|
+
} else {
|
|
210
|
+
currentAgent.provider = input.provider;
|
|
211
|
+
if (input.model) currentAgent.model = input.model;
|
|
212
|
+
else delete currentAgent.model;
|
|
213
|
+
}
|
|
214
|
+
existing.agent = currentAgent;
|
|
215
|
+
await mkdir(dirname(path), { recursive: true });
|
|
216
|
+
await writeFileAtomic(path, `${JSON.stringify(existing, null, 2)}
|
|
217
|
+
`);
|
|
218
|
+
if (input.provider === "cursor") {
|
|
219
|
+
const { ensureCursorStorageGrant } = await import("./permissions-4AKNQZHK.js");
|
|
220
|
+
await ensureCursorStorageGrant({
|
|
221
|
+
mode: input.target === "project" ? "project" : "global",
|
|
222
|
+
...input.projectRoot === void 0 ? {} : { projectRoot: input.projectRoot }
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
return path;
|
|
226
|
+
}
|
|
227
|
+
async function persistFirstAgentChoice(provider) {
|
|
228
|
+
return writeAgentPreference({ target: "global", provider });
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
export {
|
|
232
|
+
AGENT_COMMAND_SCHEMA_VERSION,
|
|
233
|
+
runAgent,
|
|
234
|
+
runAgentUse,
|
|
235
|
+
writeAgentPreference,
|
|
236
|
+
persistFirstAgentChoice
|
|
237
|
+
};
|
|
238
|
+
//# sourceMappingURL=chunk-UJ3L2MS7.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/agent.ts"],"sourcesContent":["import { mkdir, readFile } from 'node:fs/promises';\nimport { dirname, join } from 'node:path';\nimport { probeAgent } from '../agents/availability.js';\nimport { describeRunAgents } from '../agents/resolve.js';\nimport {\n AGENT_PHASES,\n AGENT_SCHEMA_VERSION,\n type AgentPhase,\n type AgentProviderId,\n isAgentPhase,\n isAgentProviderId,\n} from '../agents/types.js';\nimport { GLOBAL_CONFIG_FILENAME, loadAgentConfig, PROJECT_CONFIG_FILENAME } from '../config.js';\nimport { getGlobalRoot } from '../storage/paths.js';\nimport { printError, printSuccess } from '../ui/logger.js';\nimport { writeFileAtomic } from '../utils/fs.js';\nimport { getProjectRoot } from '../utils/git.js';\n\nexport const AGENT_COMMAND_SCHEMA_VERSION = AGENT_SCHEMA_VERSION;\n\nexport interface AgentCommandOptions {\n json?: boolean;\n}\n\nexport interface AgentUseOptions {\n model?: string;\n global?: boolean;\n project?: boolean;\n phase?: string;\n}\n\nfunction originLabel(origin: string): string {\n switch (origin) {\n case 'default':\n return 'default';\n case 'global':\n return '~/.issue-flow/config.json';\n case 'project':\n return '.issue-flow.json';\n case 'env':\n return 'ISSUE_FLOW_*';\n case 'cli':\n return 'CLI';\n default:\n return origin;\n }\n}\n\nfunction formatPhaseLine(\n phase: AgentPhase,\n provider: string,\n model: string | null,\n origin: string,\n inherited: boolean,\n): string {\n const modelBit = model ? ` · ${model}` : '';\n const source = inherited ? 'herdado do padrão' : originLabel(origin);\n return `${` ${phase.padEnd(12)} ${provider}${modelBit}`.padEnd(40)}(${source})`;\n}\n\nexport async function runAgent(options: AgentCommandOptions = {}): Promise<number> {\n const config = await loadAgentConfig();\n const summary = await describeRunAgents();\n const [claude, codex, cursor, antigravity] = await Promise.all([\n probeAgent('claude'),\n probeAgent('codex'),\n probeAgent('cursor'),\n probeAgent('antigravity'),\n ]);\n\n if (options.json === true) {\n const phases: Record<string, unknown> = {};\n for (const phase of AGENT_PHASES) {\n const resolved = summary.byPhase[phase];\n const inherited = config.phases[phase] === undefined;\n phases[phase] = {\n provider: resolved.provider,\n model: resolved.model,\n origin: resolved.origin,\n inherited,\n };\n }\n console.log(\n JSON.stringify(\n {\n schemaVersion: AGENT_COMMAND_SCHEMA_VERSION,\n default: {\n provider: summary.defaultProvider,\n model: summary.defaultModel,\n origin: summary.defaultOrigin,\n },\n phases,\n availability: [\n {\n id: 'claude',\n installed: claude.installed,\n version: claude.version,\n authenticated: claude.authenticated,\n },\n {\n id: 'codex',\n installed: codex.installed,\n version: codex.version,\n authenticated: codex.authenticated,\n },\n {\n id: 'cursor',\n installed: cursor.installed,\n version: cursor.version,\n authenticated: cursor.authenticated,\n },\n {\n id: 'antigravity',\n installed: antigravity.installed,\n version: antigravity.version,\n authenticated: antigravity.authenticated,\n authProbe: 'none',\n },\n ],\n },\n null,\n 2,\n ),\n );\n return 0;\n }\n\n const modelLabel = summary.defaultModel ?? '(default do provider)';\n console.log(\n `Agente padrão ${summary.defaultProvider.padEnd(22)} (${originLabel(summary.defaultOrigin.provider)})`,\n );\n console.log(`Modelo ${modelLabel} (${originLabel(summary.defaultOrigin.model)})`);\n console.log('');\n console.log('Por fase');\n for (const phase of AGENT_PHASES) {\n const resolved = summary.byPhase[phase];\n const inherited = config.phases[phase] === undefined;\n console.log(\n formatPhaseLine(\n phase,\n resolved.provider,\n resolved.model,\n resolved.origin.provider,\n inherited,\n ),\n );\n }\n console.log('');\n console.log('Disponibilidade');\n console.log(` claude ${(claude.version ?? '—').padEnd(16)} ${claude.detail}`);\n console.log(` codex ${(codex.version ?? '—').padEnd(16)} ${codex.detail}`);\n console.log(` cursor ${(cursor.version ?? '—').padEnd(16)} ${cursor.detail}`);\n console.log(\n ` antigravity ${(antigravity.version ?? '—').padEnd(16)} ${antigravity.detail} (no auth probe)`,\n );\n if (antigravity.installed) {\n console.log(\n ' Warning: every Antigravity invocation passes --dangerously-skip-permissions. --mode plan is the write containment.',\n );\n }\n return 0;\n}\n\nexport async function runAgentUse(\n providerRaw: string,\n options: AgentUseOptions = {},\n): Promise<number> {\n if (!isAgentProviderId(providerRaw)) {\n printError(\n `Unknown agent provider '${providerRaw}'. Valid providers: claude, codex, cursor, antigravity.`,\n );\n return 1;\n }\n const provider = providerRaw as AgentProviderId;\n\n let phase: AgentPhase | undefined;\n if (options.phase !== undefined) {\n if (!isAgentPhase(options.phase)) {\n printError(\n `Unknown agent phase '${options.phase}'. Valid phases: ${AGENT_PHASES.join(', ')}.`,\n );\n return 1;\n }\n phase = options.phase;\n }\n\n const target: 'global' | 'project' = options.project === true ? 'project' : 'global';\n try {\n const path = await writeAgentPreference({\n target,\n provider,\n model: options.model,\n phase,\n });\n printSuccess(`Wrote agent preference to ${path}`);\n return 0;\n } catch (err) {\n printError(err instanceof Error ? err.message : String(err));\n return 1;\n }\n}\n\nexport async function writeAgentPreference(input: {\n target: 'global' | 'project';\n provider: AgentProviderId;\n model?: string;\n phase?: AgentPhase;\n projectRoot?: string;\n}): Promise<string> {\n const path =\n input.target === 'global'\n ? join(getGlobalRoot(), GLOBAL_CONFIG_FILENAME)\n : join(input.projectRoot ?? (await getProjectRoot()), PROJECT_CONFIG_FILENAME);\n\n let existing: Record<string, unknown> = {};\n try {\n const raw = await readFile(path, 'utf-8');\n const parsed: unknown = JSON.parse(raw);\n if (parsed !== null && typeof parsed === 'object' && !Array.isArray(parsed)) {\n existing = parsed as Record<string, unknown>;\n }\n } catch (err: unknown) {\n if ((err as NodeJS.ErrnoException).code !== 'ENOENT') {\n throw new Error(`Could not read ${path}: ${(err as Error).message}`);\n }\n }\n\n const currentAgent =\n existing.agent !== null && typeof existing.agent === 'object' && !Array.isArray(existing.agent)\n ? { ...(existing.agent as Record<string, unknown>) }\n : {};\n\n if (input.phase) {\n const phases =\n currentAgent.phases !== null &&\n typeof currentAgent.phases === 'object' &&\n !Array.isArray(currentAgent.phases)\n ? { ...(currentAgent.phases as Record<string, unknown>) }\n : {};\n phases[input.phase] = {\n provider: input.provider,\n ...(input.model ? { model: input.model } : {}),\n };\n currentAgent.phases = phases;\n } else {\n currentAgent.provider = input.provider;\n if (input.model) currentAgent.model = input.model;\n else delete currentAgent.model;\n }\n\n existing.agent = currentAgent;\n await mkdir(dirname(path), { recursive: true });\n await writeFileAtomic(path, `${JSON.stringify(existing, null, 2)}\\n`);\n if (input.provider === 'cursor') {\n const { ensureCursorStorageGrant } = await import('../agents/permissions.js');\n await ensureCursorStorageGrant({\n mode: input.target === 'project' ? 'project' : 'global',\n ...(input.projectRoot === undefined ? {} : { projectRoot: input.projectRoot }),\n });\n }\n return path;\n}\n\n/** Used by init to persist a first-run choice without touching other keys. */\nexport async function persistFirstAgentChoice(provider: AgentProviderId): Promise<string> {\n return writeAgentPreference({ target: 'global', provider });\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
EXECUTION_PURPOSES,
|
|
4
|
+
getTelemetryContext
|
|
5
|
+
} from "./chunk-67YIU2VB.js";
|
|
6
|
+
import {
|
|
7
|
+
loadTaskPlan
|
|
8
|
+
} from "./chunk-J3SOTUVI.js";
|
|
9
|
+
|
|
10
|
+
// src/telemetry/timing.ts
|
|
11
|
+
var EMPTY_TIMING = {
|
|
12
|
+
harnessExecutionMs: null,
|
|
13
|
+
orchestrationOverheadMs: null,
|
|
14
|
+
harnessStartupMs: null,
|
|
15
|
+
ttftMs: null,
|
|
16
|
+
attemptCount: null,
|
|
17
|
+
retryDurationMs: null,
|
|
18
|
+
cliDurationMs: null,
|
|
19
|
+
apiDurationMs: null,
|
|
20
|
+
numTurns: null,
|
|
21
|
+
outputTokens: null,
|
|
22
|
+
iteration: null
|
|
23
|
+
};
|
|
24
|
+
function isPurpose(phase) {
|
|
25
|
+
return EXECUTION_PURPOSES.includes(phase);
|
|
26
|
+
}
|
|
27
|
+
function sum(values) {
|
|
28
|
+
const known = values.filter((value) => typeof value === "number");
|
|
29
|
+
return known.length === 0 ? null : known.reduce((acc, value) => acc + value, 0);
|
|
30
|
+
}
|
|
31
|
+
function firstKnown(values) {
|
|
32
|
+
for (const value of values) {
|
|
33
|
+
if (typeof value === "number") return value;
|
|
34
|
+
}
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
function summarizePhaseTiming(records, phase, phaseWallMs) {
|
|
38
|
+
if (!isPurpose(phase)) return { ...EMPTY_TIMING };
|
|
39
|
+
const matched = records.filter((record) => record.purpose === phase);
|
|
40
|
+
if (matched.length === 0) return { ...EMPTY_TIMING };
|
|
41
|
+
const harnessExecutionMs = sum(
|
|
42
|
+
matched.map((record) => {
|
|
43
|
+
if (record.durationMs !== null && record.durationMs !== void 0) return record.durationMs;
|
|
44
|
+
const cli = record.cliDurationMs;
|
|
45
|
+
const startup = record.harnessStartupMs;
|
|
46
|
+
if (cli == null && startup == null) return null;
|
|
47
|
+
return (cli ?? 0) + (startup ?? 0);
|
|
48
|
+
})
|
|
49
|
+
);
|
|
50
|
+
const orchestrationOverheadMs = phaseWallMs !== null && phaseWallMs !== void 0 && harnessExecutionMs !== null ? Math.max(0, phaseWallMs - harnessExecutionMs) : null;
|
|
51
|
+
const retryDurationMs = sum(
|
|
52
|
+
matched.filter(
|
|
53
|
+
(record) => record.trigger === "retry" || record.trigger === "fallback" || record.attempt > 1
|
|
54
|
+
).map((record) => record.durationMs)
|
|
55
|
+
);
|
|
56
|
+
return {
|
|
57
|
+
harnessExecutionMs,
|
|
58
|
+
orchestrationOverheadMs,
|
|
59
|
+
harnessStartupMs: sum(matched.map((record) => record.harnessStartupMs)),
|
|
60
|
+
ttftMs: firstKnown(matched.map((record) => record.ttftMs)),
|
|
61
|
+
attemptCount: matched.length,
|
|
62
|
+
retryDurationMs,
|
|
63
|
+
cliDurationMs: sum(matched.map((record) => record.cliDurationMs)),
|
|
64
|
+
apiDurationMs: sum(matched.map((record) => record.apiDurationMs)),
|
|
65
|
+
numTurns: sum(matched.map((record) => record.numTurns)),
|
|
66
|
+
outputTokens: sum(matched.map((record) => record.usage?.outputTokens)),
|
|
67
|
+
iteration: firstKnown(matched.map((record) => record.iteration))
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
async function loadPhaseTiming(phase, phaseWallMs) {
|
|
71
|
+
const ctx = getTelemetryContext();
|
|
72
|
+
if (ctx === null) return { ...EMPTY_TIMING };
|
|
73
|
+
try {
|
|
74
|
+
const plan = await loadTaskPlan(ctx.tasksPath);
|
|
75
|
+
return summarizePhaseTiming(plan.executions ?? [], phase, phaseWallMs);
|
|
76
|
+
} catch {
|
|
77
|
+
return { ...EMPTY_TIMING };
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
function formatSeconds(ms) {
|
|
81
|
+
if (ms === null) return "-";
|
|
82
|
+
const seconds = ms / 1e3;
|
|
83
|
+
if (seconds >= 10) return `${Math.round(seconds)}s`;
|
|
84
|
+
if (seconds >= 1) return `${seconds.toFixed(1)}s`;
|
|
85
|
+
return `${Math.round(ms)}ms`;
|
|
86
|
+
}
|
|
87
|
+
function formatPhaseLine(input) {
|
|
88
|
+
const iter = input.iteration == null ? "-" : String(input.iteration);
|
|
89
|
+
const turns = input.numTurns == null ? "-" : String(input.numTurns);
|
|
90
|
+
const out = input.outputTokens == null ? "-" : String(input.outputTokens);
|
|
91
|
+
return [
|
|
92
|
+
`task=${input.issueNumber}`,
|
|
93
|
+
`phase=${input.phase}`,
|
|
94
|
+
`iter=${iter}`,
|
|
95
|
+
`wall=${formatSeconds(input.wallMs)}`,
|
|
96
|
+
`cli=${formatSeconds(input.cliDurationMs)}`,
|
|
97
|
+
`startup=${formatSeconds(input.harnessStartupMs)}`,
|
|
98
|
+
`ttft=${formatSeconds(input.ttftMs)}`,
|
|
99
|
+
`turns=${turns}`,
|
|
100
|
+
`out=${out}`
|
|
101
|
+
].join(" ");
|
|
102
|
+
}
|
|
103
|
+
function snapshotTimingFields(timing) {
|
|
104
|
+
return {
|
|
105
|
+
harnessExecutionMs: timing.harnessExecutionMs,
|
|
106
|
+
orchestrationOverheadMs: timing.orchestrationOverheadMs,
|
|
107
|
+
harnessStartupMs: timing.harnessStartupMs,
|
|
108
|
+
ttftMs: timing.ttftMs,
|
|
109
|
+
attemptCount: timing.attemptCount,
|
|
110
|
+
retryDurationMs: timing.retryDurationMs
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export {
|
|
115
|
+
summarizePhaseTiming,
|
|
116
|
+
loadPhaseTiming,
|
|
117
|
+
formatPhaseLine,
|
|
118
|
+
snapshotTimingFields
|
|
119
|
+
};
|
|
120
|
+
//# sourceMappingURL=chunk-V7MO5EDS.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/telemetry/timing.ts"],"sourcesContent":["import { loadTaskPlan } from '../core/state-manager.js';\nimport { getTelemetryContext } from './recorder.js';\nimport { EXECUTION_PURPOSES, type ExecutionPurpose, type ExecutionRecord } from './types.js';\n\nexport interface PhaseTiming {\n harnessExecutionMs: number | null;\n orchestrationOverheadMs: number | null;\n harnessStartupMs: number | null;\n ttftMs: number | null;\n attemptCount: number | null;\n retryDurationMs: number | null;\n cliDurationMs: number | null;\n apiDurationMs: number | null;\n numTurns: number | null;\n outputTokens: number | null;\n iteration: number | null;\n}\n\nconst EMPTY_TIMING: PhaseTiming = {\n harnessExecutionMs: null,\n orchestrationOverheadMs: null,\n harnessStartupMs: null,\n ttftMs: null,\n attemptCount: null,\n retryDurationMs: null,\n cliDurationMs: null,\n apiDurationMs: null,\n numTurns: null,\n outputTokens: null,\n iteration: null,\n};\n\nfunction isPurpose(phase: string): phase is ExecutionPurpose {\n return (EXECUTION_PURPOSES as readonly string[]).includes(phase);\n}\n\nfunction sum(values: Array<number | null | undefined>): number | null {\n const known = values.filter((value): value is number => typeof value === 'number');\n return known.length === 0 ? null : known.reduce((acc, value) => acc + value, 0);\n}\n\nfunction firstKnown(values: Array<number | null | undefined>): number | null {\n for (const value of values) {\n if (typeof value === 'number') return value;\n }\n return null;\n}\n\n/**\n * Distinguishes harness wall time from orchestration leftover.\n *\n * `harnessExecutionMs` is the sum of invocation `durationMs` (or cli + startup\n * when wall is missing). `orchestrationOverheadMs` is the phase wall minus that\n * sum — absent when either side was not reported, never zero-filled.\n */\nexport function summarizePhaseTiming(\n records: readonly ExecutionRecord[],\n phase: string,\n phaseWallMs?: number | null,\n): PhaseTiming {\n if (!isPurpose(phase)) return { ...EMPTY_TIMING };\n\n const matched = records.filter((record) => record.purpose === phase);\n if (matched.length === 0) return { ...EMPTY_TIMING };\n\n const harnessExecutionMs = sum(\n matched.map((record) => {\n if (record.durationMs !== null && record.durationMs !== undefined) return record.durationMs;\n const cli = record.cliDurationMs;\n const startup = record.harnessStartupMs;\n if (cli == null && startup == null) return null;\n return (cli ?? 0) + (startup ?? 0);\n }),\n );\n\n const orchestrationOverheadMs =\n phaseWallMs !== null && phaseWallMs !== undefined && harnessExecutionMs !== null\n ? Math.max(0, phaseWallMs - harnessExecutionMs)\n : null;\n\n const retryDurationMs = sum(\n matched\n .filter(\n (record) =>\n record.trigger === 'retry' || record.trigger === 'fallback' || record.attempt > 1,\n )\n .map((record) => record.durationMs),\n );\n\n return {\n harnessExecutionMs,\n orchestrationOverheadMs,\n harnessStartupMs: sum(matched.map((record) => record.harnessStartupMs)),\n ttftMs: firstKnown(matched.map((record) => record.ttftMs)),\n attemptCount: matched.length,\n retryDurationMs,\n cliDurationMs: sum(matched.map((record) => record.cliDurationMs)),\n apiDurationMs: sum(matched.map((record) => record.apiDurationMs)),\n numTurns: sum(matched.map((record) => record.numTurns)),\n outputTokens: sum(matched.map((record) => record.usage?.outputTokens)),\n iteration: firstKnown(matched.map((record) => record.iteration)),\n };\n}\n\nexport async function loadPhaseTiming(\n phase: string,\n phaseWallMs?: number | null,\n): Promise<PhaseTiming> {\n const ctx = getTelemetryContext();\n if (ctx === null) return { ...EMPTY_TIMING };\n try {\n const plan = await loadTaskPlan(ctx.tasksPath);\n return summarizePhaseTiming(plan.executions ?? [], phase, phaseWallMs);\n } catch {\n return { ...EMPTY_TIMING };\n }\n}\n\nfunction formatSeconds(ms: number | null): string {\n if (ms === null) return '-';\n const seconds = ms / 1000;\n if (seconds >= 10) return `${Math.round(seconds)}s`;\n if (seconds >= 1) return `${seconds.toFixed(1)}s`;\n return `${Math.round(ms)}ms`;\n}\n\n/** One-line phase log: `task=63 phase=execute iter=3 wall=541s …`. */\nexport function formatPhaseLine(input: {\n issueNumber: number | string;\n phase: string;\n iteration?: number | null;\n wallMs: number | null;\n cliDurationMs: number | null;\n harnessStartupMs: number | null;\n ttftMs: number | null;\n numTurns: number | null;\n outputTokens: number | null;\n}): string {\n const iter = input.iteration == null ? '-' : String(input.iteration);\n const turns = input.numTurns == null ? '-' : String(input.numTurns);\n const out = input.outputTokens == null ? '-' : String(input.outputTokens);\n return [\n `task=${input.issueNumber}`,\n `phase=${input.phase}`,\n `iter=${iter}`,\n `wall=${formatSeconds(input.wallMs)}`,\n `cli=${formatSeconds(input.cliDurationMs)}`,\n `startup=${formatSeconds(input.harnessStartupMs)}`,\n `ttft=${formatSeconds(input.ttftMs)}`,\n `turns=${turns}`,\n `out=${out}`,\n ].join(' ');\n}\n\nexport function snapshotTimingFields(timing: PhaseTiming): {\n harnessExecutionMs: number | null;\n orchestrationOverheadMs: number | null;\n harnessStartupMs: number | null;\n ttftMs: number | null;\n attemptCount: number | null;\n retryDurationMs: number | null;\n} {\n return {\n harnessExecutionMs: timing.harnessExecutionMs,\n orchestrationOverheadMs: timing.orchestrationOverheadMs,\n harnessStartupMs: timing.harnessStartupMs,\n ttftMs: timing.ttftMs,\n attemptCount: timing.attemptCount,\n retryDurationMs: timing.retryDurationMs,\n };\n}\n"],"mappings":"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","names":[]}
|