ralphctl 0.5.0 → 0.6.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 +29 -16
- package/dist/absolute-path-WUTZQ37D.mjs +8 -0
- package/dist/chunk-6RDMCLWU.mjs +108 -0
- package/dist/chunk-HIU74KTO.mjs +1046 -0
- package/dist/chunk-S3PTDH57.mjs +78 -0
- package/dist/chunk-WV4D2CPG.mjs +26 -0
- package/dist/cli.mjs +22413 -717
- package/dist/manifest.json +24 -0
- package/dist/prompt-adapter-JQICGVX7.mjs +7 -0
- package/dist/prompts/ideate.md +3 -1
- package/dist/prompts/plan-auto.md +23 -8
- package/dist/prompts/plan-common-examples.md +3 -3
- package/dist/prompts/plan-common.md +6 -5
- package/dist/prompts/plan-interactive.md +30 -7
- package/dist/prompts/repo-onboard.md +154 -64
- package/dist/prompts/signals-task.md +3 -0
- package/dist/prompts/sprint-feedback.md +3 -0
- package/dist/prompts/task-evaluation.md +74 -53
- package/dist/prompts/task-execution.md +65 -21
- package/dist/prompts/ticket-refine.md +11 -8
- package/dist/prompts/validation-checklist.md +3 -2
- package/dist/skills/default/abstraction-first/SKILL.md +45 -0
- package/dist/skills/default/alignment/SKILL.md +46 -0
- package/dist/skills/default/iterative-review/SKILL.md +48 -0
- package/dist/skills/exec/.gitkeep +0 -0
- package/dist/skills/plan/.gitkeep +0 -0
- package/dist/skills/refine/.gitkeep +0 -0
- package/dist/storage-paths-IPNZZM5D.mjs +15 -0
- package/dist/validation-error-QT6Q7FYU.mjs +7 -0
- package/package.json +9 -4
- package/dist/add-67UFUI54.mjs +0 -17
- package/dist/add-DVPVHENV.mjs +0 -18
- package/dist/bootstrap-FMHG6DRY.mjs +0 -11
- package/dist/chunk-62HYDA7L.mjs +0 -1128
- package/dist/chunk-747KW2RW.mjs +0 -24
- package/dist/chunk-BSB4EDGR.mjs +0 -260
- package/dist/chunk-BT5FKIZX.mjs +0 -787
- package/dist/chunk-CBMFRQ4Y.mjs +0 -441
- package/dist/chunk-CFUVE2BP.mjs +0 -16
- package/dist/chunk-D6QZNEYN.mjs +0 -5520
- package/dist/chunk-FNAAA32W.mjs +0 -103
- package/dist/chunk-GQ2WFKBN.mjs +0 -269
- package/dist/chunk-IWXBJD2D.mjs +0 -27
- package/dist/chunk-OGEXYSFS.mjs +0 -228
- package/dist/chunk-VAZ3LJBI.mjs +0 -179
- package/dist/chunk-WDMLPXOD.mjs +0 -363
- package/dist/chunk-XN2UIHBY.mjs +0 -589
- package/dist/chunk-ZE2BRQA2.mjs +0 -5542
- package/dist/create-Z635FQKO.mjs +0 -15
- package/dist/handle-23EFF3BE.mjs +0 -22
- package/dist/mount-NCYR22SN.mjs +0 -7434
- package/dist/project-DQHF4ISP.mjs +0 -34
- package/dist/prompts/check-script-discover.md +0 -69
- package/dist/prompts/ideate-auto.md +0 -195
- package/dist/prompts/task-evaluation-resume.md +0 -41
- package/dist/resolver-OVPYVW6Q.mjs +0 -163
- package/dist/sprint-4E26AB5F.mjs +0 -38
- package/dist/start-T34NI3LF.mjs +0 -19
package/dist/chunk-XN2UIHBY.mjs
DELETED
|
@@ -1,589 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
unwrapOrThrow
|
|
4
|
-
} from "./chunk-IWXBJD2D.mjs";
|
|
5
|
-
import {
|
|
6
|
-
ConfigSchema,
|
|
7
|
-
fileExists,
|
|
8
|
-
getConfigPath,
|
|
9
|
-
readValidatedJson,
|
|
10
|
-
writeValidatedJson
|
|
11
|
-
} from "./chunk-WDMLPXOD.mjs";
|
|
12
|
-
|
|
13
|
-
// src/integration/ui/theme/theme.ts
|
|
14
|
-
import { bold, cyan, gray, green, red, yellow } from "colorette";
|
|
15
|
-
import gradient from "gradient-string";
|
|
16
|
-
import { isColorSupported } from "colorette";
|
|
17
|
-
var emoji = {
|
|
18
|
-
donut: "\u{1F369}"
|
|
19
|
-
};
|
|
20
|
-
var colors = {
|
|
21
|
-
// Semantic colors
|
|
22
|
-
success: green,
|
|
23
|
-
error: red,
|
|
24
|
-
warning: yellow,
|
|
25
|
-
info: cyan,
|
|
26
|
-
muted: gray,
|
|
27
|
-
highlight: yellow,
|
|
28
|
-
accent: bold
|
|
29
|
-
};
|
|
30
|
-
var success = (text) => colors.success(text);
|
|
31
|
-
var error = (text) => colors.error(text);
|
|
32
|
-
var muted = (text) => colors.muted(text);
|
|
33
|
-
var gradients = {
|
|
34
|
-
/** Gold → Orange → Hot Pink → Orchid → Violet (Ralph's signature donut warmth) */
|
|
35
|
-
donut: gradient(["#FFD700", "#FFA500", "#FF69B4", "#DA70D6", "#9400D3"], {
|
|
36
|
-
interpolation: "hsv",
|
|
37
|
-
hsvSpin: "short"
|
|
38
|
-
}),
|
|
39
|
-
/** Green → Dark Cyan (success/completion) */
|
|
40
|
-
success: gradient(["#00FF00", "#00CED1"]),
|
|
41
|
-
/** Orange Red → Gold (warning/attention) */
|
|
42
|
-
warning: gradient(["#FF4500", "#FFD700"])
|
|
43
|
-
};
|
|
44
|
-
var BANNER = `
|
|
45
|
-
\u{1F369} \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2557 \u{1F369}
|
|
46
|
-
\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u2550\u2588\u2588\u2554\u2550\u2550\u255D\u2588\u2588\u2551
|
|
47
|
-
\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551
|
|
48
|
-
\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u2550\u255D \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551
|
|
49
|
-
\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557
|
|
50
|
-
\u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D
|
|
51
|
-
`;
|
|
52
|
-
var banner = {
|
|
53
|
-
art: BANNER,
|
|
54
|
-
tagline: "I'm helping with your sprints!"
|
|
55
|
-
};
|
|
56
|
-
var RALPH_QUOTES = [
|
|
57
|
-
"I'm helping!",
|
|
58
|
-
"Me fail English? That's unpossible!",
|
|
59
|
-
"Go banana!",
|
|
60
|
-
"Hi, Super Nintendo Chalmers!",
|
|
61
|
-
"I bent my wookie.",
|
|
62
|
-
"My cat's breath smells like cat food.",
|
|
63
|
-
"I'm learnding!",
|
|
64
|
-
"The doctor said I wouldn't have so many nose bleeds if I kept my finger outta there.",
|
|
65
|
-
"I found a moonrock in my nose!",
|
|
66
|
-
"That's where I saw the leprechaun. He told me to burn things.",
|
|
67
|
-
"My daddy's gonna put you in jail!",
|
|
68
|
-
"I'm a unitard!",
|
|
69
|
-
"I ate the purple berries...",
|
|
70
|
-
"Tastes like burning!",
|
|
71
|
-
"My parents won't let me use scissors.",
|
|
72
|
-
"I dress myself!",
|
|
73
|
-
"Principal Skinner, I got carsick in your office.",
|
|
74
|
-
"I'm Idaho!",
|
|
75
|
-
"Mrs. Krabappel and Principal Skinner were in the closet making babies!",
|
|
76
|
-
"Even my boogers are spicy!",
|
|
77
|
-
"It smells like hot dogs.",
|
|
78
|
-
"I sleep in a drawer!",
|
|
79
|
-
"I picked the red one!",
|
|
80
|
-
"The pointy kitty took it!",
|
|
81
|
-
"When I grow up, I want to be a principal or a caterpillar."
|
|
82
|
-
];
|
|
83
|
-
function getRandomQuote() {
|
|
84
|
-
const index = Math.floor(Math.random() * RALPH_QUOTES.length);
|
|
85
|
-
return RALPH_QUOTES[index] ?? "";
|
|
86
|
-
}
|
|
87
|
-
var QUOTES_BY_CATEGORY = {
|
|
88
|
-
error: [
|
|
89
|
-
"My tummy hurts!",
|
|
90
|
-
"Tastes like burning!",
|
|
91
|
-
"I ate the purple berries...",
|
|
92
|
-
"The doctor said I wouldn't have so many nose bleeds if I kept my finger outta there.",
|
|
93
|
-
"My parents won't let me use scissors.",
|
|
94
|
-
"Principal Skinner, I got carsick in your office.",
|
|
95
|
-
"I eated the purple berries. They taste like... burning."
|
|
96
|
-
],
|
|
97
|
-
success: [
|
|
98
|
-
"I'm helping!",
|
|
99
|
-
"Go banana!",
|
|
100
|
-
"I'm learnding!",
|
|
101
|
-
"I'm a unitard!",
|
|
102
|
-
"I dress myself!",
|
|
103
|
-
"I picked the red one!",
|
|
104
|
-
"I found a moonrock in my nose!",
|
|
105
|
-
"Yay! I'm a helper!"
|
|
106
|
-
],
|
|
107
|
-
farewell: [
|
|
108
|
-
"Bye bye! My cat's breath smells like cat food!",
|
|
109
|
-
"When I grow up, I want to be a principal or a caterpillar.",
|
|
110
|
-
"I sleep in a drawer!",
|
|
111
|
-
"I'm Idaho!",
|
|
112
|
-
"The pointy kitty took it!"
|
|
113
|
-
],
|
|
114
|
-
idle: [
|
|
115
|
-
"Hi, Super Nintendo Chalmers!",
|
|
116
|
-
"I bent my wookie.",
|
|
117
|
-
"My cat's breath smells like cat food.",
|
|
118
|
-
"It smells like hot dogs.",
|
|
119
|
-
"That's where I saw the leprechaun. He told me to burn things.",
|
|
120
|
-
"Me fail English? That's unpossible!",
|
|
121
|
-
"Even my boogers are spicy!",
|
|
122
|
-
"Mrs. Krabappel and Principal Skinner were in the closet making babies!"
|
|
123
|
-
]
|
|
124
|
-
};
|
|
125
|
-
function getQuoteForContext(category) {
|
|
126
|
-
const quotes = QUOTES_BY_CATEGORY[category];
|
|
127
|
-
const index = Math.floor(Math.random() * quotes.length);
|
|
128
|
-
return quotes[index] ?? "";
|
|
129
|
-
}
|
|
130
|
-
var statusEmoji = {
|
|
131
|
-
todo: "\u{1F4DD}",
|
|
132
|
-
in_progress: "\u{1F3C3}",
|
|
133
|
-
done: "\u2705",
|
|
134
|
-
blocked: "\u{1F6AB}",
|
|
135
|
-
draft: "\u{1F4CB}",
|
|
136
|
-
active: "\u{1F3AF}",
|
|
137
|
-
closed: "\u{1F389}"
|
|
138
|
-
};
|
|
139
|
-
function getStatusEmoji(status) {
|
|
140
|
-
if (status in statusEmoji) {
|
|
141
|
-
return statusEmoji[status];
|
|
142
|
-
}
|
|
143
|
-
return status;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
// src/integration/ui/theme/ui.ts
|
|
147
|
-
var icons = {
|
|
148
|
-
sprint: ">",
|
|
149
|
-
ticket: "#",
|
|
150
|
-
task: "*",
|
|
151
|
-
project: "@",
|
|
152
|
-
edit: ">",
|
|
153
|
-
success: "+",
|
|
154
|
-
error: "x",
|
|
155
|
-
warning: "!",
|
|
156
|
-
info: "i",
|
|
157
|
-
tip: "?",
|
|
158
|
-
active: "*",
|
|
159
|
-
inactive: "o",
|
|
160
|
-
bullet: "-"
|
|
161
|
-
};
|
|
162
|
-
var INDENT = " ";
|
|
163
|
-
var log = {
|
|
164
|
-
info(message) {
|
|
165
|
-
console.log(`${INDENT}${colors.info(icons.info)} ${message}`);
|
|
166
|
-
},
|
|
167
|
-
success(message) {
|
|
168
|
-
console.log(`${INDENT}${colors.success(icons.success)} ${message}`);
|
|
169
|
-
},
|
|
170
|
-
warn(message) {
|
|
171
|
-
console.log(`${INDENT}${colors.warning(icons.warning)} ${message}`);
|
|
172
|
-
},
|
|
173
|
-
error(message) {
|
|
174
|
-
console.log(`${INDENT}${colors.error(icons.error)} ${message}`);
|
|
175
|
-
},
|
|
176
|
-
dim(message) {
|
|
177
|
-
console.log(`${INDENT}${colors.muted(message)}`);
|
|
178
|
-
},
|
|
179
|
-
item(message) {
|
|
180
|
-
console.log(`${INDENT}${INDENT}${colors.muted(icons.bullet)} ${message}`);
|
|
181
|
-
},
|
|
182
|
-
itemSuccess(message) {
|
|
183
|
-
console.log(`${INDENT}${INDENT}${colors.success(icons.success)} ${message}`);
|
|
184
|
-
},
|
|
185
|
-
itemError(message, detail) {
|
|
186
|
-
console.log(`${INDENT}${INDENT}${colors.error(icons.error)} ${message}`);
|
|
187
|
-
if (detail) console.log(`${INDENT}${INDENT} ${colors.muted(detail)}`);
|
|
188
|
-
},
|
|
189
|
-
raw(message, indentLevel = 1) {
|
|
190
|
-
console.log(`${INDENT.repeat(indentLevel)}${message}`);
|
|
191
|
-
},
|
|
192
|
-
newline() {
|
|
193
|
-
console.log("");
|
|
194
|
-
}
|
|
195
|
-
};
|
|
196
|
-
function printHeader(title, icon) {
|
|
197
|
-
const displayIcon = icon ?? emoji.donut;
|
|
198
|
-
console.log("");
|
|
199
|
-
console.log(` ${displayIcon} ${colors.highlight(title)}`);
|
|
200
|
-
console.log(colors.muted(` ${"\u2500".repeat(40)}`));
|
|
201
|
-
console.log("");
|
|
202
|
-
}
|
|
203
|
-
function printSeparator(width = 40) {
|
|
204
|
-
console.log(`${INDENT}${colors.muted("\u2500".repeat(width))}`);
|
|
205
|
-
}
|
|
206
|
-
function showSuccess(message, details) {
|
|
207
|
-
console.log(`
|
|
208
|
-
${INDENT}${colors.success(icons.success)} ${colors.success(message)}`);
|
|
209
|
-
if (details) {
|
|
210
|
-
console.log(details.map(([label, value]) => field(label, value)).join("\n"));
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
function showError(message) {
|
|
214
|
-
console.log(`
|
|
215
|
-
${INDENT}${colors.error(icons.error)} ${colors.error(message)}`);
|
|
216
|
-
}
|
|
217
|
-
function showWarning(message) {
|
|
218
|
-
console.log(`${INDENT}${colors.warning(icons.warning)} ${colors.warning(message)}`);
|
|
219
|
-
}
|
|
220
|
-
function showTip(message) {
|
|
221
|
-
console.log(`${INDENT}${colors.muted(icons.tip + " " + message)}`);
|
|
222
|
-
}
|
|
223
|
-
function showEmpty(what, hint) {
|
|
224
|
-
console.log(`
|
|
225
|
-
${INDENT}${colors.muted(icons.inactive)} ${colors.muted(`No ${what} yet.`)}`);
|
|
226
|
-
if (hint) {
|
|
227
|
-
console.log(`${INDENT} ${colors.muted(icons.tip + " " + hint)}
|
|
228
|
-
`);
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
function showNextStep(command, description) {
|
|
232
|
-
const desc = description ? ` ${colors.muted("- " + description)}` : "";
|
|
233
|
-
console.log(`${INDENT}${colors.muted("\u2192")} ${colors.highlight(command)}${desc}`);
|
|
234
|
-
}
|
|
235
|
-
function showNextSteps(steps) {
|
|
236
|
-
for (const [command, description] of steps) showNextStep(command, description);
|
|
237
|
-
}
|
|
238
|
-
function showRandomQuote() {
|
|
239
|
-
console.log(colors.muted(` "${getRandomQuote()}"`));
|
|
240
|
-
}
|
|
241
|
-
function printCountSummary(label, done, total) {
|
|
242
|
-
const percent = total > 0 ? Math.round(done / total * 100) : 0;
|
|
243
|
-
const color = percent === 100 ? colors.success : percent > 50 ? colors.warning : colors.muted;
|
|
244
|
-
printSeparator();
|
|
245
|
-
console.log(`${INDENT}${label} ${color(`${String(done)}/${String(total)} (${String(percent)}%)`)}`);
|
|
246
|
-
}
|
|
247
|
-
function getBannerText() {
|
|
248
|
-
const art = isColorSupported ? gradients.donut.multiline(banner.art) : banner.art;
|
|
249
|
-
const quote = getRandomQuote();
|
|
250
|
-
return `${art}
|
|
251
|
-
${colors.muted(`"${quote}"`)}
|
|
252
|
-
`;
|
|
253
|
-
}
|
|
254
|
-
function printBanner() {
|
|
255
|
-
console.log(getBannerText());
|
|
256
|
-
}
|
|
257
|
-
function isTTY() {
|
|
258
|
-
if (!process.stdout.isTTY || process.env["NO_COLOR"]) return false;
|
|
259
|
-
return true;
|
|
260
|
-
}
|
|
261
|
-
function terminalBell() {
|
|
262
|
-
if (isTTY()) process.stdout.write("\x07");
|
|
263
|
-
}
|
|
264
|
-
function createSpinner(text) {
|
|
265
|
-
let started = false;
|
|
266
|
-
const shim = {
|
|
267
|
-
text,
|
|
268
|
-
start() {
|
|
269
|
-
if (!started && isTTY()) {
|
|
270
|
-
console.log(`${INDENT}${colors.muted("\u2022")} ${shim.text}`);
|
|
271
|
-
}
|
|
272
|
-
started = true;
|
|
273
|
-
return shim;
|
|
274
|
-
},
|
|
275
|
-
stop() {
|
|
276
|
-
return shim;
|
|
277
|
-
},
|
|
278
|
-
succeed(msg) {
|
|
279
|
-
console.log(`${INDENT}${colors.success("+")} ${msg ?? shim.text}`);
|
|
280
|
-
return shim;
|
|
281
|
-
},
|
|
282
|
-
fail(msg) {
|
|
283
|
-
console.error(`${INDENT}${colors.error("x")} ${msg ?? shim.text}`);
|
|
284
|
-
return shim;
|
|
285
|
-
}
|
|
286
|
-
};
|
|
287
|
-
return shim;
|
|
288
|
-
}
|
|
289
|
-
function field(label, value, labelWidth = 12) {
|
|
290
|
-
const paddedLabel = (label + ":").padEnd(labelWidth);
|
|
291
|
-
return `${INDENT}${colors.muted(paddedLabel)} ${value}`;
|
|
292
|
-
}
|
|
293
|
-
function fieldMultiline(label, value, labelWidth = 12) {
|
|
294
|
-
const lines = value.split("\n");
|
|
295
|
-
const paddedLabel = (label + ":").padEnd(labelWidth);
|
|
296
|
-
const indent = INDENT + " ".repeat(labelWidth + 1);
|
|
297
|
-
if (lines.length === 1) return `${INDENT}${colors.muted(paddedLabel)} ${value}`;
|
|
298
|
-
const firstLine = lines[0] ?? "";
|
|
299
|
-
const result = [`${INDENT}${colors.muted(paddedLabel)} ${firstLine}`];
|
|
300
|
-
for (let i = 1; i < lines.length; i++) result.push(`${indent}${lines[i] ?? ""}`);
|
|
301
|
-
return result.join("\n");
|
|
302
|
-
}
|
|
303
|
-
function labelValue(label, value, labelWidth = DETAIL_LABEL_WIDTH) {
|
|
304
|
-
return field(label, value, labelWidth).trimStart();
|
|
305
|
-
}
|
|
306
|
-
function formatTaskStatus(status) {
|
|
307
|
-
const e = getStatusEmoji(status);
|
|
308
|
-
const labels = {
|
|
309
|
-
todo: "To Do",
|
|
310
|
-
in_progress: "In Progress",
|
|
311
|
-
done: "Done",
|
|
312
|
-
cancelled: "Cancelled"
|
|
313
|
-
};
|
|
314
|
-
const statusColors = {
|
|
315
|
-
todo: colors.muted,
|
|
316
|
-
in_progress: colors.warning,
|
|
317
|
-
done: colors.success,
|
|
318
|
-
cancelled: colors.muted
|
|
319
|
-
};
|
|
320
|
-
return (statusColors[status] ?? colors.muted)(`${e} ${labels[status] ?? status}`);
|
|
321
|
-
}
|
|
322
|
-
function formatSprintStatus(status) {
|
|
323
|
-
const e = getStatusEmoji(status);
|
|
324
|
-
const labels = { draft: "Draft", active: "Active", closed: "Closed" };
|
|
325
|
-
const statusColors = {
|
|
326
|
-
draft: colors.warning,
|
|
327
|
-
active: colors.success,
|
|
328
|
-
closed: colors.muted
|
|
329
|
-
};
|
|
330
|
-
return (statusColors[status] ?? colors.muted)(`${e} ${labels[status] ?? status}`);
|
|
331
|
-
}
|
|
332
|
-
function badge(text, type = "muted") {
|
|
333
|
-
return colors[type](`[${text}]`);
|
|
334
|
-
}
|
|
335
|
-
var boxChars = {
|
|
336
|
-
light: {
|
|
337
|
-
topLeft: "\u250C",
|
|
338
|
-
topRight: "\u2510",
|
|
339
|
-
bottomLeft: "\u2514",
|
|
340
|
-
bottomRight: "\u2518",
|
|
341
|
-
horizontal: "\u2500",
|
|
342
|
-
vertical: "\u2502",
|
|
343
|
-
teeRight: "\u251C",
|
|
344
|
-
teeLeft: "\u2524",
|
|
345
|
-
teeDown: "\u252C",
|
|
346
|
-
teeUp: "\u2534",
|
|
347
|
-
cross: "\u253C"
|
|
348
|
-
},
|
|
349
|
-
rounded: {
|
|
350
|
-
topLeft: "\u256D",
|
|
351
|
-
topRight: "\u256E",
|
|
352
|
-
bottomLeft: "\u2570",
|
|
353
|
-
bottomRight: "\u256F",
|
|
354
|
-
horizontal: "\u2500",
|
|
355
|
-
vertical: "\u2502",
|
|
356
|
-
teeRight: "\u251C",
|
|
357
|
-
teeLeft: "\u2524",
|
|
358
|
-
teeDown: "\u252C",
|
|
359
|
-
teeUp: "\u2534",
|
|
360
|
-
cross: "\u253C"
|
|
361
|
-
},
|
|
362
|
-
heavy: {
|
|
363
|
-
topLeft: "\u250F",
|
|
364
|
-
topRight: "\u2513",
|
|
365
|
-
bottomLeft: "\u2517",
|
|
366
|
-
bottomRight: "\u251B",
|
|
367
|
-
horizontal: "\u2501",
|
|
368
|
-
vertical: "\u2503",
|
|
369
|
-
teeRight: "\u2523",
|
|
370
|
-
teeLeft: "\u252B",
|
|
371
|
-
teeDown: "\u2533",
|
|
372
|
-
teeUp: "\u253B",
|
|
373
|
-
cross: "\u254B"
|
|
374
|
-
}
|
|
375
|
-
};
|
|
376
|
-
var ANSI_REGEX = /\x1B(?:\[[0-9;]*[A-Za-z]|\][^\x07]*\x07|\([A-Z])/g;
|
|
377
|
-
function stripAnsi(s) {
|
|
378
|
-
return s.replace(ANSI_REGEX, "");
|
|
379
|
-
}
|
|
380
|
-
function sanitizeForDisplay(s) {
|
|
381
|
-
return s.replace(ANSI_REGEX, "");
|
|
382
|
-
}
|
|
383
|
-
var MIN_BOX_WIDTH = 20;
|
|
384
|
-
var DEFAULT_TERMINAL_WIDTH = 80;
|
|
385
|
-
var DETAIL_LABEL_WIDTH = 14;
|
|
386
|
-
function getTerminalWidth() {
|
|
387
|
-
return process.stdout.columns || DEFAULT_TERMINAL_WIDTH;
|
|
388
|
-
}
|
|
389
|
-
function wrapLine(line, maxWidth) {
|
|
390
|
-
const visible = stripAnsi(line);
|
|
391
|
-
if (visible.length <= maxWidth) return [line];
|
|
392
|
-
const indentMatch = /^(\s*)/.exec(visible);
|
|
393
|
-
const indent = indentMatch?.[1] ?? "";
|
|
394
|
-
const indentLen = indent.length;
|
|
395
|
-
const wrapWidth = maxWidth - indentLen;
|
|
396
|
-
if (wrapWidth <= 0) return [line];
|
|
397
|
-
const words = visible.trimStart().split(/(\s+)/);
|
|
398
|
-
const wrapped = [];
|
|
399
|
-
let current = "";
|
|
400
|
-
for (const word of words) {
|
|
401
|
-
if (current.length + word.length <= wrapWidth) {
|
|
402
|
-
current += word;
|
|
403
|
-
} else if (current.length === 0) {
|
|
404
|
-
for (let i = 0; i < word.length; i += wrapWidth) wrapped.push(indent + word.slice(i, i + wrapWidth));
|
|
405
|
-
} else {
|
|
406
|
-
wrapped.push(indent + current.trimEnd());
|
|
407
|
-
current = word.trimStart();
|
|
408
|
-
}
|
|
409
|
-
}
|
|
410
|
-
if (current.trimEnd().length > 0) wrapped.push(indent + current.trimEnd());
|
|
411
|
-
return wrapped.length > 0 ? wrapped : [line];
|
|
412
|
-
}
|
|
413
|
-
function horizontalLine(width, style = "light") {
|
|
414
|
-
return boxChars[style].horizontal.repeat(width);
|
|
415
|
-
}
|
|
416
|
-
function renderCard(title, lines, options = {}) {
|
|
417
|
-
const { style = "rounded", colorFn = colors.muted } = options;
|
|
418
|
-
const chars = boxChars[style];
|
|
419
|
-
const termWidth = getTerminalWidth();
|
|
420
|
-
const maxInnerWidth = Math.max(MIN_BOX_WIDTH, termWidth - 4);
|
|
421
|
-
const safeTitle = sanitizeForDisplay(title);
|
|
422
|
-
const titleWidth = Math.min(safeTitle.length, maxInnerWidth - 2);
|
|
423
|
-
const wrappedLines = lines.flatMap((l) => wrapLine(l, maxInnerWidth - 2));
|
|
424
|
-
const contentWidths = wrappedLines.map((l) => stripAnsi(l).length);
|
|
425
|
-
const innerWidth = Math.min(Math.max(...contentWidths, titleWidth, MIN_BOX_WIDTH) + 2, maxInnerWidth);
|
|
426
|
-
const result = [];
|
|
427
|
-
result.push(colorFn(chars.topLeft + chars.horizontal.repeat(innerWidth) + chars.topRight));
|
|
428
|
-
const titlePad = " ".repeat(Math.max(0, innerWidth - titleWidth - 2));
|
|
429
|
-
result.push(colorFn(chars.vertical) + " " + colors.highlight(safeTitle) + titlePad + " " + colorFn(chars.vertical));
|
|
430
|
-
result.push(colorFn(chars.teeRight + chars.horizontal.repeat(innerWidth) + chars.teeLeft));
|
|
431
|
-
for (const line of wrappedLines) {
|
|
432
|
-
const visibleLen = stripAnsi(line).length;
|
|
433
|
-
const rightPad = " ".repeat(Math.max(0, innerWidth - visibleLen - 2));
|
|
434
|
-
result.push(colorFn(chars.vertical) + " " + line + rightPad + " " + colorFn(chars.vertical));
|
|
435
|
-
}
|
|
436
|
-
result.push(colorFn(chars.bottomLeft + chars.horizontal.repeat(innerWidth) + chars.bottomRight));
|
|
437
|
-
return result.join("\n");
|
|
438
|
-
}
|
|
439
|
-
function progressBar(done, total, options = {}) {
|
|
440
|
-
const { width = 20, filled = "\u2588", empty = "\u2591", showPercent = true } = options;
|
|
441
|
-
if (total === 0 || width <= 0) return colors.muted("\u2500".repeat(Math.max(0, width)));
|
|
442
|
-
const filledCount = Math.round(done / total * width);
|
|
443
|
-
const emptyCount = width - filledCount;
|
|
444
|
-
const percent = Math.round(done / total * 100);
|
|
445
|
-
const bar = colors.success(filled.repeat(filledCount)) + colors.muted(empty.repeat(emptyCount));
|
|
446
|
-
if (!showPercent) return bar;
|
|
447
|
-
const label = percent === 100 ? colors.success(`${String(percent)}%`) : colors.muted(`${String(percent)}%`);
|
|
448
|
-
return `${bar} ${label}`;
|
|
449
|
-
}
|
|
450
|
-
function renderTable(columns, rows, options = {}) {
|
|
451
|
-
const { style = "rounded", indent = 2, colorFn = colors.muted } = options;
|
|
452
|
-
const chars = boxChars[style];
|
|
453
|
-
const pad = " ".repeat(indent);
|
|
454
|
-
const colWidths = columns.map((col, i) => {
|
|
455
|
-
const headerWidth = col.header.length;
|
|
456
|
-
const dataWidth = Math.max(0, ...rows.map((row) => stripAnsi(row[i] ?? "").length));
|
|
457
|
-
return Math.max(headerWidth, dataWidth, col.minWidth ?? 0);
|
|
458
|
-
});
|
|
459
|
-
const result = [];
|
|
460
|
-
const topLine = colWidths.map((w) => chars.horizontal.repeat(w + 2)).join(chars.teeDown);
|
|
461
|
-
result.push(pad + colorFn(chars.topLeft + topLine + chars.topRight));
|
|
462
|
-
const headerCells = columns.map((col, i) => {
|
|
463
|
-
const w = colWidths[i] ?? 0;
|
|
464
|
-
return " " + colors.highlight(col.header.padEnd(w)) + " ";
|
|
465
|
-
});
|
|
466
|
-
result.push(pad + colorFn(chars.vertical) + headerCells.join(colorFn(chars.vertical)) + colorFn(chars.vertical));
|
|
467
|
-
const sepLine = colWidths.map((w) => chars.horizontal.repeat(w + 2)).join(chars.cross);
|
|
468
|
-
result.push(pad + colorFn(chars.teeRight + sepLine + chars.teeLeft));
|
|
469
|
-
for (const row of rows) {
|
|
470
|
-
const cells = columns.map((col, i) => {
|
|
471
|
-
const w = colWidths[i] ?? 0;
|
|
472
|
-
const cell = row[i] ?? "";
|
|
473
|
-
const visibleLen = stripAnsi(cell).length;
|
|
474
|
-
const padding = Math.max(0, w - visibleLen);
|
|
475
|
-
const coloredCell = col.color ? col.color(cell) : cell;
|
|
476
|
-
if (col.align === "right") return " " + " ".repeat(padding) + coloredCell + " ";
|
|
477
|
-
return " " + coloredCell + " ".repeat(padding) + " ";
|
|
478
|
-
});
|
|
479
|
-
result.push(pad + colorFn(chars.vertical) + cells.join(colorFn(chars.vertical)) + colorFn(chars.vertical));
|
|
480
|
-
}
|
|
481
|
-
const bottomLine = colWidths.map((w) => chars.horizontal.repeat(w + 2)).join(chars.teeUp);
|
|
482
|
-
result.push(pad + colorFn(chars.bottomLeft + bottomLine + chars.bottomRight));
|
|
483
|
-
return result.join("\n");
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
// src/integration/persistence/config.ts
|
|
487
|
-
var DEFAULT_EVALUATION_ITERATIONS = 1;
|
|
488
|
-
var DEFAULT_CONFIG = {
|
|
489
|
-
currentSprint: null,
|
|
490
|
-
aiProvider: null,
|
|
491
|
-
editor: null
|
|
492
|
-
};
|
|
493
|
-
async function getConfig() {
|
|
494
|
-
const configPath = getConfigPath();
|
|
495
|
-
if (!await fileExists(configPath)) {
|
|
496
|
-
return DEFAULT_CONFIG;
|
|
497
|
-
}
|
|
498
|
-
return unwrapOrThrow(await readValidatedJson(configPath, ConfigSchema));
|
|
499
|
-
}
|
|
500
|
-
async function saveConfig(config) {
|
|
501
|
-
unwrapOrThrow(await writeValidatedJson(getConfigPath(), config, ConfigSchema));
|
|
502
|
-
}
|
|
503
|
-
async function getCurrentSprint() {
|
|
504
|
-
const config = await getConfig();
|
|
505
|
-
return config.currentSprint;
|
|
506
|
-
}
|
|
507
|
-
async function setCurrentSprint(sprintId) {
|
|
508
|
-
const config = await getConfig();
|
|
509
|
-
config.currentSprint = sprintId;
|
|
510
|
-
await saveConfig(config);
|
|
511
|
-
}
|
|
512
|
-
async function getAiProvider() {
|
|
513
|
-
const config = await getConfig();
|
|
514
|
-
return config.aiProvider ?? null;
|
|
515
|
-
}
|
|
516
|
-
async function setAiProvider(provider) {
|
|
517
|
-
const config = await getConfig();
|
|
518
|
-
config.aiProvider = provider;
|
|
519
|
-
await saveConfig(config);
|
|
520
|
-
}
|
|
521
|
-
async function getEditor() {
|
|
522
|
-
const config = await getConfig();
|
|
523
|
-
return config.editor ?? null;
|
|
524
|
-
}
|
|
525
|
-
async function setEditor(editor) {
|
|
526
|
-
const config = await getConfig();
|
|
527
|
-
config.editor = editor;
|
|
528
|
-
await saveConfig(config);
|
|
529
|
-
}
|
|
530
|
-
async function getEvaluationIterations() {
|
|
531
|
-
const config = await getConfig();
|
|
532
|
-
return config.evaluationIterations ?? DEFAULT_EVALUATION_ITERATIONS;
|
|
533
|
-
}
|
|
534
|
-
async function setEvaluationIterations(iterations) {
|
|
535
|
-
const config = await getConfig();
|
|
536
|
-
config.evaluationIterations = iterations;
|
|
537
|
-
await saveConfig(config);
|
|
538
|
-
}
|
|
539
|
-
|
|
540
|
-
export {
|
|
541
|
-
emoji,
|
|
542
|
-
colors,
|
|
543
|
-
success,
|
|
544
|
-
error,
|
|
545
|
-
muted,
|
|
546
|
-
gradients,
|
|
547
|
-
banner,
|
|
548
|
-
getRandomQuote,
|
|
549
|
-
getQuoteForContext,
|
|
550
|
-
icons,
|
|
551
|
-
log,
|
|
552
|
-
printHeader,
|
|
553
|
-
printSeparator,
|
|
554
|
-
showSuccess,
|
|
555
|
-
showError,
|
|
556
|
-
showWarning,
|
|
557
|
-
showTip,
|
|
558
|
-
showEmpty,
|
|
559
|
-
showNextStep,
|
|
560
|
-
showNextSteps,
|
|
561
|
-
showRandomQuote,
|
|
562
|
-
printCountSummary,
|
|
563
|
-
printBanner,
|
|
564
|
-
isTTY,
|
|
565
|
-
terminalBell,
|
|
566
|
-
createSpinner,
|
|
567
|
-
field,
|
|
568
|
-
fieldMultiline,
|
|
569
|
-
labelValue,
|
|
570
|
-
formatTaskStatus,
|
|
571
|
-
formatSprintStatus,
|
|
572
|
-
badge,
|
|
573
|
-
boxChars,
|
|
574
|
-
DETAIL_LABEL_WIDTH,
|
|
575
|
-
horizontalLine,
|
|
576
|
-
renderCard,
|
|
577
|
-
progressBar,
|
|
578
|
-
renderTable,
|
|
579
|
-
getConfig,
|
|
580
|
-
saveConfig,
|
|
581
|
-
getCurrentSprint,
|
|
582
|
-
setCurrentSprint,
|
|
583
|
-
getAiProvider,
|
|
584
|
-
setAiProvider,
|
|
585
|
-
getEditor,
|
|
586
|
-
setEditor,
|
|
587
|
-
getEvaluationIterations,
|
|
588
|
-
setEvaluationIterations
|
|
589
|
-
};
|