@kb-labs/shared-cli-ui 1.0.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 +342 -0
- package/dist/debug.cjs +765 -0
- package/dist/debug.cjs.map +1 -0
- package/dist/debug.d.cts +151 -0
- package/dist/debug.d.ts +151 -0
- package/dist/debug.js +735 -0
- package/dist/debug.js.map +1 -0
- package/dist/index.cjs +2629 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1037 -0
- package/dist/index.d.ts +1037 -0
- package/dist/index.js +2516 -0
- package/dist/index.js.map +1 -0
- package/package.json +71 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,2629 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var path = require('path');
|
|
4
|
+
var fs = require('fs');
|
|
5
|
+
|
|
6
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
7
|
+
|
|
8
|
+
var path__default = /*#__PURE__*/_interopDefault(path);
|
|
9
|
+
|
|
10
|
+
// src/colors.ts
|
|
11
|
+
var CSI = "\x1B[";
|
|
12
|
+
var RESET = "\x1B[0m";
|
|
13
|
+
var createColor = (...codes) => (text) => `${CSI}${codes.join(";")}m${text}${RESET}`;
|
|
14
|
+
var accentBlue = "38;5;39";
|
|
15
|
+
var accentViolet = "38;5;99";
|
|
16
|
+
var accentTeal = "38;5;51";
|
|
17
|
+
var accentIndigo = "38;5;63";
|
|
18
|
+
var neutral = 37;
|
|
19
|
+
var neutralMuted = 90;
|
|
20
|
+
var colors = {
|
|
21
|
+
// Semantic colors
|
|
22
|
+
success: createColor(32),
|
|
23
|
+
error: createColor(31),
|
|
24
|
+
warning: createColor(33),
|
|
25
|
+
info: createColor(36),
|
|
26
|
+
// Accent palette (reused across CLI)
|
|
27
|
+
primary: createColor(accentBlue),
|
|
28
|
+
accent: createColor(accentViolet),
|
|
29
|
+
highlight: createColor(accentTeal),
|
|
30
|
+
secondary: createColor(accentIndigo),
|
|
31
|
+
emphasis: createColor("38;5;117"),
|
|
32
|
+
muted: createColor(neutralMuted),
|
|
33
|
+
foreground: createColor(neutral),
|
|
34
|
+
// Formatting helpers
|
|
35
|
+
dim: createColor(2),
|
|
36
|
+
bold: createColor(1),
|
|
37
|
+
underline: createColor(4),
|
|
38
|
+
inverse: createColor(7)
|
|
39
|
+
};
|
|
40
|
+
var symbolCharacters = {
|
|
41
|
+
success: "OK",
|
|
42
|
+
error: "ERR",
|
|
43
|
+
warning: "WARN",
|
|
44
|
+
info: "\u2139",
|
|
45
|
+
bullet: "\u2022",
|
|
46
|
+
clock: "TIME",
|
|
47
|
+
folder: "DIR",
|
|
48
|
+
package: "\u203A",
|
|
49
|
+
pointer: "\u203A",
|
|
50
|
+
section: "\u2502"
|
|
51
|
+
};
|
|
52
|
+
var symbols = {
|
|
53
|
+
success: colors.success(symbolCharacters.success),
|
|
54
|
+
error: colors.error(symbolCharacters.error),
|
|
55
|
+
warning: colors.warning(symbolCharacters.warning),
|
|
56
|
+
info: colors.info(symbolCharacters.info),
|
|
57
|
+
bullet: colors.muted(symbolCharacters.bullet),
|
|
58
|
+
clock: colors.info(symbolCharacters.clock),
|
|
59
|
+
folder: colors.primary(symbolCharacters.folder),
|
|
60
|
+
package: colors.accent(symbolCharacters.package),
|
|
61
|
+
pointer: colors.primary(symbolCharacters.pointer),
|
|
62
|
+
section: colors.primary(symbolCharacters.section)
|
|
63
|
+
};
|
|
64
|
+
var isTruthyEnv = (value) => {
|
|
65
|
+
if (!value) {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
const normalized = value.trim().toLowerCase();
|
|
69
|
+
return normalized !== "" && normalized !== "0" && normalized !== "false" && normalized !== "off";
|
|
70
|
+
};
|
|
71
|
+
var supportsColor = (() => {
|
|
72
|
+
if (typeof process === "undefined") {
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
const forceColor = process.env.FORCE_COLOR;
|
|
76
|
+
if (isTruthyEnv(process.env.NO_COLOR)) {
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
if (isTruthyEnv(forceColor)) {
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
if (!process.stdout) {
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
if (process.stdout.isTTY === false) {
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
return true;
|
|
89
|
+
})();
|
|
90
|
+
var passthrough = (fn) => (text) => supportsColor ? fn(text) : text;
|
|
91
|
+
var safeColors = {
|
|
92
|
+
success: passthrough(colors.success),
|
|
93
|
+
error: passthrough(colors.error),
|
|
94
|
+
warning: passthrough(colors.warning),
|
|
95
|
+
info: passthrough(colors.info),
|
|
96
|
+
accent: passthrough(colors.accent),
|
|
97
|
+
primary: passthrough(colors.primary),
|
|
98
|
+
highlight: passthrough(colors.highlight),
|
|
99
|
+
secondary: passthrough(colors.secondary),
|
|
100
|
+
emphasis: passthrough(colors.emphasis),
|
|
101
|
+
foreground: passthrough(colors.foreground),
|
|
102
|
+
muted: passthrough(colors.muted),
|
|
103
|
+
dim: passthrough(colors.dim),
|
|
104
|
+
bold: passthrough(colors.bold),
|
|
105
|
+
underline: passthrough(colors.underline),
|
|
106
|
+
inverse: passthrough(colors.inverse)
|
|
107
|
+
};
|
|
108
|
+
var safeSymbols = {
|
|
109
|
+
success: supportsColor ? symbols.success : "\u2713",
|
|
110
|
+
error: supportsColor ? symbols.error : "\u2717",
|
|
111
|
+
warning: supportsColor ? symbols.warning : "\u26A0",
|
|
112
|
+
info: supportsColor ? symbols.info : "\u2192",
|
|
113
|
+
bullet: supportsColor ? symbols.bullet : "\u2022",
|
|
114
|
+
clock: supportsColor ? symbols.clock : "time",
|
|
115
|
+
folder: supportsColor ? symbols.folder : "dir",
|
|
116
|
+
package: supportsColor ? symbols.package : "\u203A",
|
|
117
|
+
pointer: supportsColor ? symbols.pointer : ">",
|
|
118
|
+
section: supportsColor ? symbols.section : "|",
|
|
119
|
+
// Box-drawing characters for modern side border
|
|
120
|
+
separator: "\u2500",
|
|
121
|
+
// Horizontal line
|
|
122
|
+
border: "\u2502",
|
|
123
|
+
// Vertical line
|
|
124
|
+
topLeft: "\u250C",
|
|
125
|
+
// Top-left corner
|
|
126
|
+
topRight: "\u2510",
|
|
127
|
+
// Top-right corner
|
|
128
|
+
bottomLeft: "\u2514",
|
|
129
|
+
// Bottom-left corner
|
|
130
|
+
bottomRight: "\u2518",
|
|
131
|
+
// Bottom-right corner
|
|
132
|
+
leftT: "\u251C",
|
|
133
|
+
// Left T-junction
|
|
134
|
+
rightT: "\u2524"
|
|
135
|
+
// Right T-junction
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
// src/loader.ts
|
|
139
|
+
var SPINNER_CHARS = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
140
|
+
var Loader = class {
|
|
141
|
+
isActive = false;
|
|
142
|
+
options;
|
|
143
|
+
frameIndex = 0;
|
|
144
|
+
intervalId;
|
|
145
|
+
currentText;
|
|
146
|
+
// ← Реактивная переменная для текста
|
|
147
|
+
constructor(options = {}) {
|
|
148
|
+
this.options = {
|
|
149
|
+
text: "Loading...",
|
|
150
|
+
spinner: true,
|
|
151
|
+
jsonMode: false,
|
|
152
|
+
...options
|
|
153
|
+
};
|
|
154
|
+
this.currentText = this.options.text ?? "Loading...";
|
|
155
|
+
}
|
|
156
|
+
start() {
|
|
157
|
+
if (this.options.jsonMode || this.isActive) {
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
this.isActive = true;
|
|
161
|
+
if (this.options.spinner && !this.options.jsonMode) {
|
|
162
|
+
this.intervalId = setInterval(() => {
|
|
163
|
+
if (!this.isActive) {
|
|
164
|
+
this.clearInterval();
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
const char = SPINNER_CHARS[this.frameIndex % SPINNER_CHARS.length];
|
|
168
|
+
process.stdout.write(`\r${char} ${this.currentText}`);
|
|
169
|
+
this.frameIndex++;
|
|
170
|
+
}, 200);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
update(options) {
|
|
174
|
+
this.options = { ...this.options, ...options };
|
|
175
|
+
if (!this.isActive || this.options.jsonMode) {
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
if (options.text !== void 0) {
|
|
179
|
+
this.currentText = options.text;
|
|
180
|
+
}
|
|
181
|
+
if (!this.intervalId) {
|
|
182
|
+
if (this.options.spinner) {
|
|
183
|
+
const text = this.options.text ?? "Loading...";
|
|
184
|
+
console.log(`${safeSymbols.info} ${text}`);
|
|
185
|
+
} else if (this.options.total !== void 0) {
|
|
186
|
+
this.updateProgress();
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
stop() {
|
|
191
|
+
this.isActive = false;
|
|
192
|
+
this.clearInterval();
|
|
193
|
+
}
|
|
194
|
+
succeed(message) {
|
|
195
|
+
this.stop();
|
|
196
|
+
if (!this.options.jsonMode && message) {
|
|
197
|
+
process.stdout.write(`\r\x1B[K${safeSymbols.success} ${message}
|
|
198
|
+
`);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
fail(message) {
|
|
202
|
+
this.stop();
|
|
203
|
+
if (!this.options.jsonMode && message) {
|
|
204
|
+
process.stdout.write(`\r\x1B[K${safeSymbols.error} ${message}
|
|
205
|
+
`);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
clearInterval() {
|
|
209
|
+
if (this.intervalId) {
|
|
210
|
+
clearInterval(this.intervalId);
|
|
211
|
+
this.intervalId = void 0;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
updateProgress() {
|
|
215
|
+
if (this.options.total === void 0 || this.options.current === void 0) {
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
const current = this.options.current;
|
|
219
|
+
const total = this.options.total;
|
|
220
|
+
const percentage = Math.round(current / total * 100);
|
|
221
|
+
const barLength = 20;
|
|
222
|
+
const filledLength = Math.round(current / total * barLength);
|
|
223
|
+
const bar = "\u2588".repeat(filledLength) + "\u2591".repeat(barLength - filledLength);
|
|
224
|
+
const text = this.options.text || "Progress";
|
|
225
|
+
process.stdout.write(`\r${safeColors.info("\u2192")} ${text}... ${bar} ${percentage}% (${current}/${total})`);
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
function createSpinner(text, jsonMode = false) {
|
|
229
|
+
return new Loader({ text, spinner: true, jsonMode });
|
|
230
|
+
}
|
|
231
|
+
function createProgressBar(text, total, jsonMode = false) {
|
|
232
|
+
return new Loader({ text, spinner: false, total, current: 0, jsonMode });
|
|
233
|
+
}
|
|
234
|
+
function showLoading(text, jsonMode = false) {
|
|
235
|
+
if (!jsonMode) {
|
|
236
|
+
console.log(`${safeColors.info("\u2192")} ${text}...`);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
function showSuccess(text, jsonMode = false) {
|
|
240
|
+
if (!jsonMode) {
|
|
241
|
+
console.log(`${safeSymbols.success} ${text}`);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
function showError(text, jsonMode = false) {
|
|
245
|
+
if (!jsonMode) {
|
|
246
|
+
console.log(`${safeSymbols.error} ${text}`);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
function useLoader(text, options) {
|
|
250
|
+
return new Loader({ text, ...options });
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// src/format.ts
|
|
254
|
+
var ANSI_PATTERN = /\u001B\[[0-9;]*m/g;
|
|
255
|
+
function stripAnsi(input) {
|
|
256
|
+
return input.replace(ANSI_PATTERN, "");
|
|
257
|
+
}
|
|
258
|
+
function hasAnsi(input) {
|
|
259
|
+
return /\u001B\[[0-9;]*m/.test(input);
|
|
260
|
+
}
|
|
261
|
+
function visibleLength(input) {
|
|
262
|
+
return stripAnsi(input).length;
|
|
263
|
+
}
|
|
264
|
+
function box(title, content = [], maxWidth) {
|
|
265
|
+
const lines = content.length > 0 ? content : [""];
|
|
266
|
+
const titleWidth = visibleLength(title);
|
|
267
|
+
const terminalWidth = typeof process !== "undefined" && process.stdout?.columns ? process.stdout.columns : 80;
|
|
268
|
+
const effectiveMaxWidth = maxWidth ?? Math.min(terminalWidth - 4, 120);
|
|
269
|
+
const bodyWidth = Math.min(
|
|
270
|
+
effectiveMaxWidth,
|
|
271
|
+
Math.max(titleWidth, ...lines.map((line) => visibleLength(line)))
|
|
272
|
+
);
|
|
273
|
+
const wrappedLines = [];
|
|
274
|
+
for (const line of lines) {
|
|
275
|
+
const lineLength = visibleLength(line);
|
|
276
|
+
if (lineLength <= bodyWidth) {
|
|
277
|
+
wrappedLines.push(line);
|
|
278
|
+
} else {
|
|
279
|
+
const words = line.split(/(\s+)/);
|
|
280
|
+
let currentLine = "";
|
|
281
|
+
for (const word of words) {
|
|
282
|
+
const testLine = currentLine + word;
|
|
283
|
+
if (visibleLength(testLine) <= bodyWidth) {
|
|
284
|
+
currentLine = testLine;
|
|
285
|
+
} else {
|
|
286
|
+
if (currentLine) {
|
|
287
|
+
wrappedLines.push(currentLine.trimEnd());
|
|
288
|
+
}
|
|
289
|
+
if (visibleLength(word) > bodyWidth) {
|
|
290
|
+
wrappedLines.push(truncate(word, bodyWidth));
|
|
291
|
+
currentLine = "";
|
|
292
|
+
} else {
|
|
293
|
+
currentLine = word;
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
if (currentLine) {
|
|
298
|
+
wrappedLines.push(currentLine.trimEnd());
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
const topBorder = `\u250C${"\u2500".repeat(bodyWidth + 2)}\u2510`;
|
|
303
|
+
const titleLine = `\u2502 ${safeColors.bold(title)}${" ".repeat(Math.max(0, bodyWidth - titleWidth))} \u2502`;
|
|
304
|
+
const bodyLines = wrappedLines.map((line) => {
|
|
305
|
+
const padding = Math.max(0, bodyWidth - visibleLength(line));
|
|
306
|
+
return `\u2502 ${line}${" ".repeat(padding)} \u2502`;
|
|
307
|
+
});
|
|
308
|
+
const bottomBorder = `\u2514${"\u2500".repeat(bodyWidth + 2)}\u2518`;
|
|
309
|
+
return [topBorder, titleLine, ...bodyLines, bottomBorder].join("\n");
|
|
310
|
+
}
|
|
311
|
+
function indent(lines, level = 1) {
|
|
312
|
+
const prefix = " ".repeat(level);
|
|
313
|
+
return lines.map((line) => `${prefix}${line}`);
|
|
314
|
+
}
|
|
315
|
+
function section(header, content) {
|
|
316
|
+
return [
|
|
317
|
+
"",
|
|
318
|
+
safeColors.bold(header),
|
|
319
|
+
...indent(content)
|
|
320
|
+
];
|
|
321
|
+
}
|
|
322
|
+
function table(rows, headers) {
|
|
323
|
+
if (rows.length === 0) {
|
|
324
|
+
return [];
|
|
325
|
+
}
|
|
326
|
+
const allRows = headers ? [headers, ...rows] : rows;
|
|
327
|
+
if (allRows.length === 0) {
|
|
328
|
+
return [];
|
|
329
|
+
}
|
|
330
|
+
const columnWidths = allRows[0].map(
|
|
331
|
+
(_, colIndex) => Math.max(...allRows.map((row) => String(row[colIndex] || "").length))
|
|
332
|
+
);
|
|
333
|
+
return allRows.map((row) => {
|
|
334
|
+
return row.map(
|
|
335
|
+
(cell, colIndex) => String(cell || "").padEnd(columnWidths[colIndex] || 0)
|
|
336
|
+
).join(" ");
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
function keyValue(pairs, options = {}) {
|
|
340
|
+
const { padKeys = true } = options;
|
|
341
|
+
return safeKeyValue(pairs, { pad: padKeys });
|
|
342
|
+
}
|
|
343
|
+
function bulletList(items) {
|
|
344
|
+
return items.map((item) => `${safeSymbols.bullet} ${item}`);
|
|
345
|
+
}
|
|
346
|
+
function safeKeyValue(pairs, options = {}) {
|
|
347
|
+
const { indent: indent2 = 0, pad: pad3 = true, valueColor } = options;
|
|
348
|
+
const keys = Object.keys(pairs);
|
|
349
|
+
if (keys.length === 0) {
|
|
350
|
+
return [];
|
|
351
|
+
}
|
|
352
|
+
const indentStr = " ".repeat(indent2);
|
|
353
|
+
const maxKeyLength = pad3 ? Math.max(...keys.map((key) => indent2 + stripAnsi(key).length)) : 0;
|
|
354
|
+
return keys.map((key) => {
|
|
355
|
+
const rawKey = key;
|
|
356
|
+
const rawValue = String(pairs[key] ?? "");
|
|
357
|
+
const keyLength = indent2 + stripAnsi(rawKey).length;
|
|
358
|
+
const padding = pad3 ? Math.max(0, maxKeyLength - keyLength) : 0;
|
|
359
|
+
const formattedKey = `${indentStr}${rawKey}${" ".repeat(padding)}`;
|
|
360
|
+
const computedValue = valueColor ? valueColor(rawValue, key) : rawValue;
|
|
361
|
+
const valueText = hasAnsi(computedValue) ? computedValue : safeColors.muted(computedValue);
|
|
362
|
+
return `${safeColors.bold(formattedKey)}: ${valueText}`;
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
var pad2 = (value) => value.toString().padStart(2, "0");
|
|
366
|
+
var toDate = (value) => value instanceof Date ? new Date(value.getTime()) : new Date(value);
|
|
367
|
+
var isValidDate = (date) => Number.isFinite(date.getTime());
|
|
368
|
+
function getOffsetMinutes(date, timeZone) {
|
|
369
|
+
if (!timeZone) {
|
|
370
|
+
return -date.getTimezoneOffset();
|
|
371
|
+
}
|
|
372
|
+
const dtf = new Intl.DateTimeFormat("en-US", {
|
|
373
|
+
timeZone,
|
|
374
|
+
hour12: false,
|
|
375
|
+
year: "numeric",
|
|
376
|
+
month: "2-digit",
|
|
377
|
+
day: "2-digit",
|
|
378
|
+
hour: "2-digit",
|
|
379
|
+
minute: "2-digit",
|
|
380
|
+
second: "2-digit"
|
|
381
|
+
});
|
|
382
|
+
const parts = dtf.formatToParts(date);
|
|
383
|
+
const lookup = Object.fromEntries(
|
|
384
|
+
parts.filter((part) => part.type !== "literal").map((part) => [part.type, Number(part.value)])
|
|
385
|
+
);
|
|
386
|
+
const year = lookup.year ?? date.getUTCFullYear();
|
|
387
|
+
const month = (lookup.month ?? date.getUTCMonth() + 1) - 1;
|
|
388
|
+
const day = lookup.day ?? date.getUTCDate();
|
|
389
|
+
const hour = lookup.hour ?? date.getUTCHours();
|
|
390
|
+
const minute = lookup.minute ?? date.getUTCMinutes();
|
|
391
|
+
const second = lookup.second ?? date.getUTCSeconds();
|
|
392
|
+
const asUTC = Date.UTC(year, month, day, hour, minute, second);
|
|
393
|
+
return Math.round((asUTC - date.getTime()) / 6e4);
|
|
394
|
+
}
|
|
395
|
+
function formatOffset(offsetMinutes) {
|
|
396
|
+
const sign = offsetMinutes >= 0 ? "+" : "-";
|
|
397
|
+
const absMinutes = Math.abs(offsetMinutes);
|
|
398
|
+
const hours = Math.floor(absMinutes / 60);
|
|
399
|
+
const minutes = absMinutes % 60;
|
|
400
|
+
return `${sign}${pad2(hours)}:${pad2(minutes)}`;
|
|
401
|
+
}
|
|
402
|
+
function getDateParts(date, timeZone) {
|
|
403
|
+
if (!timeZone) {
|
|
404
|
+
return {
|
|
405
|
+
year: date.getFullYear(),
|
|
406
|
+
month: date.getMonth() + 1,
|
|
407
|
+
day: date.getDate(),
|
|
408
|
+
hour: date.getHours(),
|
|
409
|
+
minute: date.getMinutes(),
|
|
410
|
+
second: date.getSeconds()
|
|
411
|
+
};
|
|
412
|
+
}
|
|
413
|
+
const dtf = new Intl.DateTimeFormat("en-US", {
|
|
414
|
+
timeZone,
|
|
415
|
+
hour12: false,
|
|
416
|
+
year: "numeric",
|
|
417
|
+
month: "2-digit",
|
|
418
|
+
day: "2-digit",
|
|
419
|
+
hour: "2-digit",
|
|
420
|
+
minute: "2-digit",
|
|
421
|
+
second: "2-digit"
|
|
422
|
+
});
|
|
423
|
+
const parts = dtf.formatToParts(date);
|
|
424
|
+
const lookup = Object.fromEntries(
|
|
425
|
+
parts.filter((part) => part.type !== "literal").map((part) => [part.type, Number(part.value)])
|
|
426
|
+
);
|
|
427
|
+
return {
|
|
428
|
+
year: lookup.year ?? date.getUTCFullYear(),
|
|
429
|
+
month: lookup.month ?? date.getUTCMonth() + 1,
|
|
430
|
+
day: lookup.day ?? date.getUTCDate(),
|
|
431
|
+
hour: lookup.hour ?? date.getUTCHours(),
|
|
432
|
+
minute: lookup.minute ?? date.getUTCMinutes(),
|
|
433
|
+
second: lookup.second ?? date.getUTCSeconds()
|
|
434
|
+
};
|
|
435
|
+
}
|
|
436
|
+
function headline(text) {
|
|
437
|
+
return safeColors.primary(safeColors.bold(text));
|
|
438
|
+
}
|
|
439
|
+
function accentLabel(text) {
|
|
440
|
+
return safeColors.accent(safeColors.bold(text));
|
|
441
|
+
}
|
|
442
|
+
function muted(text) {
|
|
443
|
+
return safeColors.muted(text);
|
|
444
|
+
}
|
|
445
|
+
function formatSize(bytes) {
|
|
446
|
+
const units = ["B", "KB", "MB", "GB"];
|
|
447
|
+
let size = bytes;
|
|
448
|
+
let unitIndex = 0;
|
|
449
|
+
while (size >= 1024 && unitIndex < units.length - 1) {
|
|
450
|
+
size /= 1024;
|
|
451
|
+
unitIndex++;
|
|
452
|
+
}
|
|
453
|
+
return `${size.toFixed(unitIndex === 0 ? 0 : 1)} ${units[unitIndex]}`;
|
|
454
|
+
}
|
|
455
|
+
function formatRelativeTime(timestamp) {
|
|
456
|
+
const now = /* @__PURE__ */ new Date();
|
|
457
|
+
const time = toDate(timestamp);
|
|
458
|
+
if (!isValidDate(time)) {
|
|
459
|
+
return "Invalid date";
|
|
460
|
+
}
|
|
461
|
+
const diffMs = now.getTime() - time.getTime();
|
|
462
|
+
const seconds = Math.floor(diffMs / 1e3);
|
|
463
|
+
const minutes = Math.floor(seconds / 60);
|
|
464
|
+
const hours = Math.floor(minutes / 60);
|
|
465
|
+
const days = Math.floor(hours / 24);
|
|
466
|
+
if (days > 0) {
|
|
467
|
+
return `${days} day${days > 1 ? "s" : ""} ago`;
|
|
468
|
+
} else if (hours > 0) {
|
|
469
|
+
return `${hours} hour${hours > 1 ? "s" : ""} ago`;
|
|
470
|
+
} else if (minutes > 0) {
|
|
471
|
+
return `${minutes} minute${minutes > 1 ? "s" : ""} ago`;
|
|
472
|
+
} else {
|
|
473
|
+
return `${seconds} second${seconds > 1 ? "s" : ""} ago`;
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
function formatTimestamp(timestamp, options = {}) {
|
|
477
|
+
const {
|
|
478
|
+
mode = "local",
|
|
479
|
+
timeZone,
|
|
480
|
+
includeSeconds = false,
|
|
481
|
+
includeMilliseconds = true,
|
|
482
|
+
includeOffset = true
|
|
483
|
+
} = options;
|
|
484
|
+
const date = toDate(timestamp);
|
|
485
|
+
if (!isValidDate(date)) {
|
|
486
|
+
return "Invalid date";
|
|
487
|
+
}
|
|
488
|
+
const offsetMinutes = includeOffset ? getOffsetMinutes(date, timeZone) : null;
|
|
489
|
+
const offsetSuffix = includeOffset && offsetMinutes !== null ? ` (${formatOffset(offsetMinutes)})` : "";
|
|
490
|
+
if (mode === "iso") {
|
|
491
|
+
const isoRaw = date.toISOString();
|
|
492
|
+
const iso = includeMilliseconds ? isoRaw : isoRaw.replace(/\.\d{3}Z$/, "Z");
|
|
493
|
+
return `${iso}${offsetSuffix}`;
|
|
494
|
+
}
|
|
495
|
+
const { year, month, day, hour, minute, second } = getDateParts(date, timeZone);
|
|
496
|
+
const base = [
|
|
497
|
+
`${year}-${pad2(month)}-${pad2(day)}`,
|
|
498
|
+
`${pad2(hour)}:${pad2(minute)}${includeSeconds ? `:${pad2(second)}` : ""}`
|
|
499
|
+
].join(" ");
|
|
500
|
+
return `${base}${offsetSuffix}`;
|
|
501
|
+
}
|
|
502
|
+
function truncate(text, maxLength) {
|
|
503
|
+
if (text.length <= maxLength) {
|
|
504
|
+
return text;
|
|
505
|
+
}
|
|
506
|
+
return text.substring(0, maxLength - 3) + "...";
|
|
507
|
+
}
|
|
508
|
+
function pad(text, width, align = "left") {
|
|
509
|
+
if (text.length >= width) {
|
|
510
|
+
return text;
|
|
511
|
+
}
|
|
512
|
+
const padding = width - text.length;
|
|
513
|
+
switch (align) {
|
|
514
|
+
case "right":
|
|
515
|
+
return " ".repeat(padding) + text;
|
|
516
|
+
case "center":
|
|
517
|
+
const leftPad = Math.floor(padding / 2);
|
|
518
|
+
const rightPad = padding - leftPad;
|
|
519
|
+
return " ".repeat(leftPad) + text + " ".repeat(rightPad);
|
|
520
|
+
default:
|
|
521
|
+
return text + " ".repeat(padding);
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
// src/command-output.ts
|
|
526
|
+
function formatTiming(ms) {
|
|
527
|
+
if (ms < 1e3) {
|
|
528
|
+
return `${ms}ms`;
|
|
529
|
+
} else if (ms < 6e4) {
|
|
530
|
+
return `${(ms / 1e3).toFixed(1)}s`;
|
|
531
|
+
} else {
|
|
532
|
+
const minutes = Math.floor(ms / 6e4);
|
|
533
|
+
const seconds = (ms % 6e4 / 1e3).toFixed(1);
|
|
534
|
+
return `${minutes}m ${seconds}s`;
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
function formatTimingBreakdown(timings) {
|
|
538
|
+
const lines = [];
|
|
539
|
+
const sortedEntries = Object.entries(timings).filter(([key]) => key !== "total").sort(([, a], [, b]) => b - a);
|
|
540
|
+
for (const [name, ms] of sortedEntries) {
|
|
541
|
+
const formattedName = name.charAt(0).toUpperCase() + name.slice(1);
|
|
542
|
+
lines.push(`${formattedName}: ${formatTiming(ms)}`);
|
|
543
|
+
}
|
|
544
|
+
if (timings.total !== void 0) {
|
|
545
|
+
lines.push(`Total: ${formatTiming(timings.total)}`);
|
|
546
|
+
}
|
|
547
|
+
return lines;
|
|
548
|
+
}
|
|
549
|
+
function formatCommandOutput(result) {
|
|
550
|
+
const sections = [];
|
|
551
|
+
const summaryLines = keyValue(result.summary);
|
|
552
|
+
sections.push(...summaryLines);
|
|
553
|
+
if (result.timing !== void 0) {
|
|
554
|
+
sections.push("");
|
|
555
|
+
if (typeof result.timing === "number") {
|
|
556
|
+
sections.push(`Time: ${formatTiming(result.timing)}`);
|
|
557
|
+
} else {
|
|
558
|
+
const timingLines = formatTimingBreakdown(result.timing);
|
|
559
|
+
sections.push(...timingLines);
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
if (result.warnings && result.warnings.length > 0) {
|
|
563
|
+
sections.push("");
|
|
564
|
+
sections.push(safeColors.warning("Warnings:"));
|
|
565
|
+
result.warnings.forEach(
|
|
566
|
+
(warning) => sections.push(` ${safeColors.dim("\u2022")} ${warning}`)
|
|
567
|
+
);
|
|
568
|
+
}
|
|
569
|
+
if (result.errors && result.errors.length > 0) {
|
|
570
|
+
sections.push("");
|
|
571
|
+
sections.push(safeColors.error("Errors:"));
|
|
572
|
+
result.errors.forEach(
|
|
573
|
+
(error) => sections.push(` ${safeColors.dim("\u2022")} ${error}`)
|
|
574
|
+
);
|
|
575
|
+
}
|
|
576
|
+
if (result.diagnostics && result.diagnostics.length > 0) {
|
|
577
|
+
sections.push("");
|
|
578
|
+
sections.push(safeColors.info("Diagnostics:"));
|
|
579
|
+
result.diagnostics.forEach(
|
|
580
|
+
(diagnostic) => sections.push(` ${safeColors.dim("\u2022")} ${diagnostic}`)
|
|
581
|
+
);
|
|
582
|
+
}
|
|
583
|
+
if (result.suggestions && result.suggestions.length > 0) {
|
|
584
|
+
sections.push("");
|
|
585
|
+
sections.push(safeColors.info("Suggestions:"));
|
|
586
|
+
result.suggestions.forEach(
|
|
587
|
+
(suggestion) => sections.push(` ${safeColors.dim("\u2022")} ${suggestion}`)
|
|
588
|
+
);
|
|
589
|
+
}
|
|
590
|
+
return box(result.title, sections);
|
|
591
|
+
}
|
|
592
|
+
function createSimpleResult(title, summary, timing) {
|
|
593
|
+
return {
|
|
594
|
+
title,
|
|
595
|
+
summary,
|
|
596
|
+
timing
|
|
597
|
+
};
|
|
598
|
+
}
|
|
599
|
+
function createDetailedResult(title, summary, options = {}) {
|
|
600
|
+
return {
|
|
601
|
+
title,
|
|
602
|
+
summary,
|
|
603
|
+
...options
|
|
604
|
+
};
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
// src/timing-tracker.ts
|
|
608
|
+
var TimingTracker = class {
|
|
609
|
+
start;
|
|
610
|
+
checkpoints = {};
|
|
611
|
+
constructor() {
|
|
612
|
+
this.start = Date.now();
|
|
613
|
+
}
|
|
614
|
+
/**
|
|
615
|
+
* Record a timing checkpoint
|
|
616
|
+
*/
|
|
617
|
+
checkpoint(name) {
|
|
618
|
+
this.checkpoints[name] = Date.now() - this.start;
|
|
619
|
+
}
|
|
620
|
+
/**
|
|
621
|
+
* Get total elapsed time in milliseconds
|
|
622
|
+
*/
|
|
623
|
+
total() {
|
|
624
|
+
return Date.now() - this.start;
|
|
625
|
+
}
|
|
626
|
+
/**
|
|
627
|
+
* Get timing breakdown including total
|
|
628
|
+
*/
|
|
629
|
+
breakdown() {
|
|
630
|
+
return { ...this.checkpoints, total: this.total() };
|
|
631
|
+
}
|
|
632
|
+
/**
|
|
633
|
+
* Get timing breakdown without total
|
|
634
|
+
*/
|
|
635
|
+
checkpointsOnly() {
|
|
636
|
+
return { ...this.checkpoints };
|
|
637
|
+
}
|
|
638
|
+
/**
|
|
639
|
+
* Reset the timer
|
|
640
|
+
*/
|
|
641
|
+
reset() {
|
|
642
|
+
this.start = Date.now();
|
|
643
|
+
this.checkpoints = {};
|
|
644
|
+
}
|
|
645
|
+
/**
|
|
646
|
+
* Get elapsed time since last checkpoint or start
|
|
647
|
+
*/
|
|
648
|
+
sinceLastCheckpoint() {
|
|
649
|
+
const lastCheckpointTime = Math.max(...Object.values(this.checkpoints), 0);
|
|
650
|
+
return Date.now() - this.start - lastCheckpointTime;
|
|
651
|
+
}
|
|
652
|
+
/**
|
|
653
|
+
* Get elapsed time since a specific checkpoint
|
|
654
|
+
*/
|
|
655
|
+
sinceCheckpoint(checkpointName) {
|
|
656
|
+
const checkpointTime = this.checkpoints[checkpointName];
|
|
657
|
+
if (checkpointTime === void 0) {
|
|
658
|
+
return null;
|
|
659
|
+
}
|
|
660
|
+
return Date.now() - this.start - checkpointTime;
|
|
661
|
+
}
|
|
662
|
+
};
|
|
663
|
+
|
|
664
|
+
// src/command-suggestions.ts
|
|
665
|
+
function createCommandRegistry(commands) {
|
|
666
|
+
const commandSet = new Set(commands);
|
|
667
|
+
const groups = /* @__PURE__ */ new Map();
|
|
668
|
+
for (const cmd of commands) {
|
|
669
|
+
const [group, ...rest] = cmd.split(":");
|
|
670
|
+
if (group && rest.length > 0) {
|
|
671
|
+
if (!groups.has(group)) {
|
|
672
|
+
groups.set(group, /* @__PURE__ */ new Set());
|
|
673
|
+
}
|
|
674
|
+
groups.get(group).add(rest.join(":"));
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
return {
|
|
678
|
+
commands: commandSet,
|
|
679
|
+
groups
|
|
680
|
+
};
|
|
681
|
+
}
|
|
682
|
+
function isCommandAvailable(command, registry) {
|
|
683
|
+
if (command.startsWith("kb ")) {
|
|
684
|
+
const parts = command.split(" ");
|
|
685
|
+
if (parts.length >= 3 && parts[1] && parts[2]) {
|
|
686
|
+
const group = parts[1];
|
|
687
|
+
const subcommand = parts[2];
|
|
688
|
+
const fullCommand = `${group}:${subcommand}`;
|
|
689
|
+
return registry.commands.has(fullCommand);
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
return registry.commands.has(command);
|
|
693
|
+
}
|
|
694
|
+
function validateSuggestions(suggestions, registry) {
|
|
695
|
+
return suggestions.map((suggestion) => ({
|
|
696
|
+
...suggestion,
|
|
697
|
+
available: isCommandAvailable(suggestion.command, registry)
|
|
698
|
+
})).filter((suggestion) => suggestion.available);
|
|
699
|
+
}
|
|
700
|
+
function generateDevlinkSuggestions(warningCodes, context, registry) {
|
|
701
|
+
const suggestions = [];
|
|
702
|
+
if (warningCodes.has("LOCK_MISMATCH")) {
|
|
703
|
+
suggestions.push({
|
|
704
|
+
id: "SYNC_LOCK",
|
|
705
|
+
command: "kb devlink apply",
|
|
706
|
+
args: ["--yes"],
|
|
707
|
+
description: "Apply changes to sync manifests",
|
|
708
|
+
impact: "safe",
|
|
709
|
+
when: "LOCK_MISMATCH"
|
|
710
|
+
});
|
|
711
|
+
}
|
|
712
|
+
if (warningCodes.has("BACKUP_MISSING")) {
|
|
713
|
+
suggestions.push({
|
|
714
|
+
id: "CREATE_BACKUP",
|
|
715
|
+
command: "kb devlink freeze",
|
|
716
|
+
args: ["--replace"],
|
|
717
|
+
description: "Create a fresh backup",
|
|
718
|
+
impact: "safe",
|
|
719
|
+
when: "BACKUP_MISSING"
|
|
720
|
+
});
|
|
721
|
+
}
|
|
722
|
+
if (warningCodes.has("STALE_LOCK")) {
|
|
723
|
+
suggestions.push({
|
|
724
|
+
id: "REFRESH_LOCK",
|
|
725
|
+
command: "kb devlink freeze",
|
|
726
|
+
args: ["--pin=caret"],
|
|
727
|
+
description: "Refresh lock file",
|
|
728
|
+
impact: "safe",
|
|
729
|
+
when: "STALE_LOCK"
|
|
730
|
+
});
|
|
731
|
+
}
|
|
732
|
+
if (warningCodes.has("STALE_YALC_ARTIFACTS")) {
|
|
733
|
+
suggestions.push({
|
|
734
|
+
id: "CLEAN_YALC",
|
|
735
|
+
command: "kb devlink clean",
|
|
736
|
+
args: [],
|
|
737
|
+
description: "Remove yalc artifacts",
|
|
738
|
+
impact: "safe",
|
|
739
|
+
when: "STALE_YALC_ARTIFACTS"
|
|
740
|
+
});
|
|
741
|
+
}
|
|
742
|
+
if (warningCodes.has("PROTOCOL_CONFLICTS")) {
|
|
743
|
+
suggestions.push({
|
|
744
|
+
id: "FIX_PROTOCOLS",
|
|
745
|
+
command: "kb devlink clean",
|
|
746
|
+
args: ["--hard"],
|
|
747
|
+
description: "Reset all protocols and reapply",
|
|
748
|
+
impact: "disruptive",
|
|
749
|
+
when: "PROTOCOL_CONFLICTS"
|
|
750
|
+
});
|
|
751
|
+
}
|
|
752
|
+
if (context.undo?.available) {
|
|
753
|
+
suggestions.push({
|
|
754
|
+
id: "UNDO_LAST",
|
|
755
|
+
command: "kb devlink undo",
|
|
756
|
+
args: [],
|
|
757
|
+
description: "Revert last operation",
|
|
758
|
+
impact: "safe",
|
|
759
|
+
when: "BACKUP_AVAILABLE"
|
|
760
|
+
});
|
|
761
|
+
}
|
|
762
|
+
return validateSuggestions(suggestions, registry);
|
|
763
|
+
}
|
|
764
|
+
function generateQuickActions(hasWarnings, registry, group = "devlink") {
|
|
765
|
+
if (!hasWarnings) {
|
|
766
|
+
return [];
|
|
767
|
+
}
|
|
768
|
+
const quickActions = [
|
|
769
|
+
{
|
|
770
|
+
id: "QUICK_CLEAN",
|
|
771
|
+
command: `kb ${group} clean`,
|
|
772
|
+
args: [],
|
|
773
|
+
description: "Clean artifacts",
|
|
774
|
+
impact: "safe",
|
|
775
|
+
when: "QUICK_ACTIONS"
|
|
776
|
+
},
|
|
777
|
+
{
|
|
778
|
+
id: "QUICK_PLAN",
|
|
779
|
+
command: `kb ${group} plan`,
|
|
780
|
+
args: [],
|
|
781
|
+
description: "Create plan",
|
|
782
|
+
impact: "safe",
|
|
783
|
+
when: "QUICK_ACTIONS"
|
|
784
|
+
},
|
|
785
|
+
{
|
|
786
|
+
id: "QUICK_APPLY",
|
|
787
|
+
command: `kb ${group} apply`,
|
|
788
|
+
args: [],
|
|
789
|
+
description: "Apply changes",
|
|
790
|
+
impact: "safe",
|
|
791
|
+
when: "QUICK_ACTIONS"
|
|
792
|
+
}
|
|
793
|
+
];
|
|
794
|
+
return validateSuggestions(quickActions, registry);
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
// src/command-discovery.ts
|
|
798
|
+
var StaticCommandDiscovery = class {
|
|
799
|
+
constructor(commands) {
|
|
800
|
+
this.commands = commands;
|
|
801
|
+
}
|
|
802
|
+
async getAvailableCommands() {
|
|
803
|
+
return [...this.commands];
|
|
804
|
+
}
|
|
805
|
+
async getCommandInfo(commandId) {
|
|
806
|
+
if (!this.commands.includes(commandId)) {
|
|
807
|
+
return null;
|
|
808
|
+
}
|
|
809
|
+
const [group, name] = commandId.split(":");
|
|
810
|
+
return {
|
|
811
|
+
id: commandId,
|
|
812
|
+
group: group || "unknown",
|
|
813
|
+
name: name || commandId,
|
|
814
|
+
description: `Execute ${commandId}`,
|
|
815
|
+
available: true
|
|
816
|
+
};
|
|
817
|
+
}
|
|
818
|
+
async isCommandAvailable(commandId) {
|
|
819
|
+
return this.commands.includes(commandId);
|
|
820
|
+
}
|
|
821
|
+
};
|
|
822
|
+
function createCommandDiscovery(commands) {
|
|
823
|
+
return new StaticCommandDiscovery(commands);
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
// src/manifest-parser.ts
|
|
827
|
+
function extractCommandIds(manifest) {
|
|
828
|
+
return manifest.map((cmd) => cmd.id);
|
|
829
|
+
}
|
|
830
|
+
function extractCommandGroups(manifest) {
|
|
831
|
+
const groups = /* @__PURE__ */ new Set();
|
|
832
|
+
manifest.forEach((cmd) => groups.add(cmd.group));
|
|
833
|
+
return Array.from(groups);
|
|
834
|
+
}
|
|
835
|
+
function findCommandsByGroup(manifest, group) {
|
|
836
|
+
return manifest.filter((cmd) => cmd.group === group);
|
|
837
|
+
}
|
|
838
|
+
function findCommandById(manifest, id) {
|
|
839
|
+
return manifest.find((cmd) => cmd.id === id);
|
|
840
|
+
}
|
|
841
|
+
function getCommandInfo(manifest, commandId) {
|
|
842
|
+
const cmd = findCommandById(manifest, commandId);
|
|
843
|
+
if (!cmd) {
|
|
844
|
+
return null;
|
|
845
|
+
}
|
|
846
|
+
const [group, name] = commandId.split(":");
|
|
847
|
+
return {
|
|
848
|
+
id: commandId,
|
|
849
|
+
group: group || "unknown",
|
|
850
|
+
name: name || commandId,
|
|
851
|
+
description: cmd.describe,
|
|
852
|
+
available: true
|
|
853
|
+
};
|
|
854
|
+
}
|
|
855
|
+
function generateGroupSuggestions(manifest, group, _warningCodes, _context) {
|
|
856
|
+
const groupCommands = findCommandsByGroup(manifest, group);
|
|
857
|
+
const suggestions = [];
|
|
858
|
+
for (const cmd of groupCommands) {
|
|
859
|
+
suggestions.push({
|
|
860
|
+
id: `${cmd.group.toUpperCase()}_${cmd.id.split(":")[1]?.toUpperCase() || "UNKNOWN"}`,
|
|
861
|
+
command: `kb ${cmd.group} ${cmd.id.split(":")[1] || ""}`,
|
|
862
|
+
args: [],
|
|
863
|
+
description: cmd.describe,
|
|
864
|
+
impact: "safe",
|
|
865
|
+
when: "GENERAL",
|
|
866
|
+
available: true
|
|
867
|
+
});
|
|
868
|
+
if (cmd.id.includes("init")) {
|
|
869
|
+
suggestions.push({
|
|
870
|
+
id: `${cmd.group.toUpperCase()}_INIT_FORCE`,
|
|
871
|
+
command: `kb ${cmd.group} ${cmd.id.split(":")[1] || ""}`,
|
|
872
|
+
args: ["--force"],
|
|
873
|
+
description: `${cmd.describe} (force)`,
|
|
874
|
+
impact: "disruptive",
|
|
875
|
+
when: "INIT_FAILED",
|
|
876
|
+
available: true
|
|
877
|
+
});
|
|
878
|
+
}
|
|
879
|
+
if (cmd.id.includes("clean") || cmd.id.includes("reset")) {
|
|
880
|
+
suggestions.push({
|
|
881
|
+
id: `${cmd.group.toUpperCase()}_CLEAN_HARD`,
|
|
882
|
+
command: `kb ${cmd.group} ${cmd.id.split(":")[1] || ""}`,
|
|
883
|
+
args: ["--hard"],
|
|
884
|
+
description: `${cmd.describe} (hard)`,
|
|
885
|
+
impact: "disruptive",
|
|
886
|
+
when: "CLEAN_NEEDED",
|
|
887
|
+
available: true
|
|
888
|
+
});
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
return suggestions;
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
// src/multi-cli-suggestions.ts
|
|
895
|
+
var MultiCLISuggestions = class {
|
|
896
|
+
packages = /* @__PURE__ */ new Map();
|
|
897
|
+
globalRegistry = null;
|
|
898
|
+
/**
|
|
899
|
+
* Register a CLI package
|
|
900
|
+
*/
|
|
901
|
+
registerPackage(pkg) {
|
|
902
|
+
this.packages.set(pkg.name, pkg);
|
|
903
|
+
this.globalRegistry = null;
|
|
904
|
+
}
|
|
905
|
+
/**
|
|
906
|
+
* Get or create global command registry
|
|
907
|
+
*/
|
|
908
|
+
getGlobalRegistry() {
|
|
909
|
+
if (this.globalRegistry) {
|
|
910
|
+
return this.globalRegistry;
|
|
911
|
+
}
|
|
912
|
+
const allCommands = [];
|
|
913
|
+
for (const pkg of this.packages.values()) {
|
|
914
|
+
allCommands.push(...extractCommandIds(pkg.commands));
|
|
915
|
+
}
|
|
916
|
+
this.globalRegistry = createCommandRegistry(allCommands);
|
|
917
|
+
return this.globalRegistry;
|
|
918
|
+
}
|
|
919
|
+
/**
|
|
920
|
+
* Generate suggestions for a specific group
|
|
921
|
+
*/
|
|
922
|
+
generateGroupSuggestions(group, context) {
|
|
923
|
+
const suggestions = [];
|
|
924
|
+
const registry = this.getGlobalRegistry();
|
|
925
|
+
const groupPackages = Array.from(this.packages.values()).filter((pkg) => pkg.group === group).sort((a, b) => b.priority - a.priority);
|
|
926
|
+
for (const pkg of groupPackages) {
|
|
927
|
+
const groupSuggestions = generateGroupSuggestions(
|
|
928
|
+
pkg.commands,
|
|
929
|
+
group,
|
|
930
|
+
context.warningCodes);
|
|
931
|
+
for (const suggestion of groupSuggestions) {
|
|
932
|
+
if (registry.commands.has(suggestion.command.replace("kb ", "").replace(" ", ":"))) {
|
|
933
|
+
suggestions.push({
|
|
934
|
+
id: suggestion.id,
|
|
935
|
+
command: suggestion.command,
|
|
936
|
+
args: suggestion.args,
|
|
937
|
+
description: suggestion.description,
|
|
938
|
+
impact: suggestion.impact,
|
|
939
|
+
when: suggestion.when,
|
|
940
|
+
available: true
|
|
941
|
+
});
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
return suggestions;
|
|
946
|
+
}
|
|
947
|
+
/**
|
|
948
|
+
* Generate all suggestions across all packages
|
|
949
|
+
*/
|
|
950
|
+
generateAllSuggestions(context) {
|
|
951
|
+
const suggestions = [];
|
|
952
|
+
const registry = this.getGlobalRegistry();
|
|
953
|
+
if (this.packages.has("devlink")) {
|
|
954
|
+
const devlinkSuggestions = generateDevlinkSuggestions(
|
|
955
|
+
context.warningCodes,
|
|
956
|
+
{ undo: context.undo },
|
|
957
|
+
registry
|
|
958
|
+
);
|
|
959
|
+
suggestions.push(...devlinkSuggestions);
|
|
960
|
+
}
|
|
961
|
+
const groups = /* @__PURE__ */ new Set();
|
|
962
|
+
for (const pkg of this.packages.values()) {
|
|
963
|
+
groups.add(pkg.group);
|
|
964
|
+
}
|
|
965
|
+
for (const group of groups) {
|
|
966
|
+
if (group !== "devlink") {
|
|
967
|
+
const groupSuggestions = this.generateGroupSuggestions(group, context);
|
|
968
|
+
suggestions.push(...groupSuggestions);
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
return suggestions;
|
|
972
|
+
}
|
|
973
|
+
/**
|
|
974
|
+
* Get available commands for a group
|
|
975
|
+
*/
|
|
976
|
+
getAvailableCommands(group) {
|
|
977
|
+
const groupPackages = Array.from(this.packages.values()).filter((pkg) => pkg.group === group);
|
|
978
|
+
const commands = [];
|
|
979
|
+
for (const pkg of groupPackages) {
|
|
980
|
+
commands.push(...extractCommandIds(pkg.commands));
|
|
981
|
+
}
|
|
982
|
+
return commands;
|
|
983
|
+
}
|
|
984
|
+
/**
|
|
985
|
+
* Get all registered packages
|
|
986
|
+
*/
|
|
987
|
+
getPackages() {
|
|
988
|
+
return Array.from(this.packages.values());
|
|
989
|
+
}
|
|
990
|
+
};
|
|
991
|
+
|
|
992
|
+
// src/dynamic-command-discovery.ts
|
|
993
|
+
var DynamicCommandDiscovery = class {
|
|
994
|
+
constructor(manifestLoader, packageNames) {
|
|
995
|
+
this.manifestLoader = manifestLoader;
|
|
996
|
+
this.packageNames = packageNames;
|
|
997
|
+
}
|
|
998
|
+
manifestCache = /* @__PURE__ */ new Map();
|
|
999
|
+
commandCache = /* @__PURE__ */ new Map();
|
|
1000
|
+
async getAvailableCommands() {
|
|
1001
|
+
const allCommands = [];
|
|
1002
|
+
for (const packageName of this.packageNames) {
|
|
1003
|
+
try {
|
|
1004
|
+
const manifest = await this.loadManifest(packageName);
|
|
1005
|
+
const commands = manifest.map((cmd) => cmd.id);
|
|
1006
|
+
allCommands.push(...commands);
|
|
1007
|
+
} catch (error) {
|
|
1008
|
+
console.warn(`Failed to load manifest for ${packageName}:`, error);
|
|
1009
|
+
}
|
|
1010
|
+
}
|
|
1011
|
+
return allCommands;
|
|
1012
|
+
}
|
|
1013
|
+
async getCommandInfo(commandId) {
|
|
1014
|
+
if (this.commandCache.has(commandId)) {
|
|
1015
|
+
return this.commandCache.get(commandId);
|
|
1016
|
+
}
|
|
1017
|
+
for (const packageName of this.packageNames) {
|
|
1018
|
+
try {
|
|
1019
|
+
const manifest = await this.loadManifest(packageName);
|
|
1020
|
+
const command = manifest.find((cmd) => cmd.id === commandId);
|
|
1021
|
+
if (command) {
|
|
1022
|
+
const [group, name] = commandId.split(":");
|
|
1023
|
+
const info = {
|
|
1024
|
+
id: commandId,
|
|
1025
|
+
group: group || "unknown",
|
|
1026
|
+
name: name || commandId,
|
|
1027
|
+
description: command.describe || `Execute ${commandId}`,
|
|
1028
|
+
available: true
|
|
1029
|
+
};
|
|
1030
|
+
this.commandCache.set(commandId, info);
|
|
1031
|
+
return info;
|
|
1032
|
+
}
|
|
1033
|
+
} catch (error) {
|
|
1034
|
+
console.warn(`Failed to load manifest for ${packageName}:`, error);
|
|
1035
|
+
}
|
|
1036
|
+
}
|
|
1037
|
+
return null;
|
|
1038
|
+
}
|
|
1039
|
+
async isCommandAvailable(commandId) {
|
|
1040
|
+
const info = await this.getCommandInfo(commandId);
|
|
1041
|
+
return info !== null;
|
|
1042
|
+
}
|
|
1043
|
+
async loadManifest(packageName) {
|
|
1044
|
+
if (this.manifestCache.has(packageName)) {
|
|
1045
|
+
return this.manifestCache.get(packageName);
|
|
1046
|
+
}
|
|
1047
|
+
const manifest = await this.manifestLoader.loadManifest(packageName);
|
|
1048
|
+
this.manifestCache.set(packageName, manifest);
|
|
1049
|
+
return manifest;
|
|
1050
|
+
}
|
|
1051
|
+
};
|
|
1052
|
+
function createKBLabsCommandDiscovery() {
|
|
1053
|
+
const manifestLoader = {
|
|
1054
|
+
async loadManifest(packageName) {
|
|
1055
|
+
try {
|
|
1056
|
+
const possiblePaths = [
|
|
1057
|
+
`@kb-labs/${packageName}/cli.manifest.js`,
|
|
1058
|
+
`@kb-labs/${packageName}/dist/cli.manifest.js`,
|
|
1059
|
+
`@kb-labs/${packageName}/src/cli.manifest.js`
|
|
1060
|
+
];
|
|
1061
|
+
for (const path2 of possiblePaths) {
|
|
1062
|
+
try {
|
|
1063
|
+
const manifest = await import(path2);
|
|
1064
|
+
if (manifest.commands && Array.isArray(manifest.commands)) {
|
|
1065
|
+
return manifest.commands;
|
|
1066
|
+
}
|
|
1067
|
+
} catch {
|
|
1068
|
+
continue;
|
|
1069
|
+
}
|
|
1070
|
+
}
|
|
1071
|
+
throw new Error(`No manifest found for ${packageName}`);
|
|
1072
|
+
} catch (error) {
|
|
1073
|
+
console.warn(`Failed to load manifest for ${packageName}:`, error);
|
|
1074
|
+
return [];
|
|
1075
|
+
}
|
|
1076
|
+
}
|
|
1077
|
+
};
|
|
1078
|
+
const packageNames = [
|
|
1079
|
+
"devlink-core",
|
|
1080
|
+
"mind-cli",
|
|
1081
|
+
"tox-cli",
|
|
1082
|
+
"core-cli"
|
|
1083
|
+
];
|
|
1084
|
+
return new DynamicCommandDiscovery(manifestLoader, packageNames);
|
|
1085
|
+
}
|
|
1086
|
+
function displayArtifacts(artifacts, options = {}) {
|
|
1087
|
+
const {
|
|
1088
|
+
showSize = true,
|
|
1089
|
+
showTime = true,
|
|
1090
|
+
showDescription = false,
|
|
1091
|
+
maxItems = 10,
|
|
1092
|
+
title = "Generated Artifacts",
|
|
1093
|
+
groupBy = "none"
|
|
1094
|
+
} = options;
|
|
1095
|
+
if (artifacts.length === 0) {
|
|
1096
|
+
return [];
|
|
1097
|
+
}
|
|
1098
|
+
let sortedArtifacts = artifacts;
|
|
1099
|
+
if (groupBy === "time") {
|
|
1100
|
+
sortedArtifacts = [...artifacts].sort(
|
|
1101
|
+
(a, b) => (b.modified?.getTime() ?? 0) - (a.modified?.getTime() ?? 0)
|
|
1102
|
+
);
|
|
1103
|
+
} else if (groupBy === "type") {
|
|
1104
|
+
sortedArtifacts = [...artifacts].sort((a, b) => a.name.localeCompare(b.name));
|
|
1105
|
+
} else {
|
|
1106
|
+
sortedArtifacts = [...artifacts].sort(
|
|
1107
|
+
(a, b) => (b.modified?.getTime() ?? 0) - (a.modified?.getTime() ?? 0)
|
|
1108
|
+
);
|
|
1109
|
+
}
|
|
1110
|
+
sortedArtifacts = sortedArtifacts.slice(0, maxItems);
|
|
1111
|
+
const lines = [];
|
|
1112
|
+
if (title) {
|
|
1113
|
+
lines.push(safeColors.bold(title));
|
|
1114
|
+
}
|
|
1115
|
+
if (groupBy === "type") {
|
|
1116
|
+
const grouped = sortedArtifacts.reduce((acc, artifact) => {
|
|
1117
|
+
const type = artifact.name.split(" ")[0] || "Other";
|
|
1118
|
+
if (!acc[type]) {
|
|
1119
|
+
acc[type] = [];
|
|
1120
|
+
}
|
|
1121
|
+
acc[type].push(artifact);
|
|
1122
|
+
return acc;
|
|
1123
|
+
}, {});
|
|
1124
|
+
Object.entries(grouped).forEach(([type, items], index) => {
|
|
1125
|
+
if (index > 0 || title) {
|
|
1126
|
+
lines.push("");
|
|
1127
|
+
}
|
|
1128
|
+
lines.push(...safeKeyValue({ [type]: "" }, { pad: false }));
|
|
1129
|
+
items.forEach((artifact, artifactIndex) => {
|
|
1130
|
+
if (artifactIndex > 0) {
|
|
1131
|
+
lines.push("");
|
|
1132
|
+
}
|
|
1133
|
+
lines.push(...formatArtifactLines(artifact, {
|
|
1134
|
+
showSize,
|
|
1135
|
+
showTime,
|
|
1136
|
+
showDescription,
|
|
1137
|
+
indent: 2
|
|
1138
|
+
}));
|
|
1139
|
+
});
|
|
1140
|
+
});
|
|
1141
|
+
return lines;
|
|
1142
|
+
}
|
|
1143
|
+
sortedArtifacts.forEach((artifact, index) => {
|
|
1144
|
+
if (index > 0) {
|
|
1145
|
+
lines.push("");
|
|
1146
|
+
}
|
|
1147
|
+
lines.push(...formatArtifactLines(artifact, {
|
|
1148
|
+
showSize,
|
|
1149
|
+
showTime,
|
|
1150
|
+
showDescription,
|
|
1151
|
+
indent: 0
|
|
1152
|
+
}));
|
|
1153
|
+
});
|
|
1154
|
+
return lines;
|
|
1155
|
+
}
|
|
1156
|
+
function formatArtifactLines(artifact, options) {
|
|
1157
|
+
const { showSize, showTime, showDescription, indent: indent2 } = options;
|
|
1158
|
+
const relativePath = path__default.default.relative(process.cwd(), artifact.path);
|
|
1159
|
+
const lines = [];
|
|
1160
|
+
lines.push(
|
|
1161
|
+
...safeKeyValue({ [artifact.name]: relativePath }, { pad: false, indent: indent2 })
|
|
1162
|
+
);
|
|
1163
|
+
if (showSize && artifact.size) {
|
|
1164
|
+
lines.push(
|
|
1165
|
+
...safeKeyValue({ Size: formatSize(artifact.size) }, { pad: false, indent: indent2 + 2 })
|
|
1166
|
+
);
|
|
1167
|
+
}
|
|
1168
|
+
if (showTime && artifact.modified) {
|
|
1169
|
+
lines.push(
|
|
1170
|
+
...safeKeyValue({ Updated: formatRelativeTime(artifact.modified) }, { pad: false, indent: indent2 + 2 })
|
|
1171
|
+
);
|
|
1172
|
+
}
|
|
1173
|
+
if (showDescription && artifact.description) {
|
|
1174
|
+
lines.push(
|
|
1175
|
+
...safeKeyValue({ Note: artifact.description }, { pad: false, indent: indent2 + 2 })
|
|
1176
|
+
);
|
|
1177
|
+
}
|
|
1178
|
+
return lines;
|
|
1179
|
+
}
|
|
1180
|
+
function displaySingleArtifact(artifact, title) {
|
|
1181
|
+
const relativePath = path__default.default.relative(process.cwd(), artifact.path);
|
|
1182
|
+
const lines = [];
|
|
1183
|
+
if (title) {
|
|
1184
|
+
lines.push("");
|
|
1185
|
+
lines.push(safeColors.bold(title));
|
|
1186
|
+
}
|
|
1187
|
+
lines.push(` ${safeColors.bold(artifact.name)}: ${safeColors.info(relativePath)}`);
|
|
1188
|
+
if (artifact.size) {
|
|
1189
|
+
lines.push(` Size: ${formatSize(artifact.size)}`);
|
|
1190
|
+
}
|
|
1191
|
+
if (artifact.modified) {
|
|
1192
|
+
lines.push(` Modified: ${formatRelativeTime(artifact.modified)}`);
|
|
1193
|
+
}
|
|
1194
|
+
if (artifact.description) {
|
|
1195
|
+
lines.push(` Description: ${artifact.description}`);
|
|
1196
|
+
}
|
|
1197
|
+
return lines;
|
|
1198
|
+
}
|
|
1199
|
+
function displayArtifactsCompact(artifacts, options = {}) {
|
|
1200
|
+
const {
|
|
1201
|
+
maxItems = 5,
|
|
1202
|
+
showSize = true,
|
|
1203
|
+
sortByTime = true,
|
|
1204
|
+
showTime = true,
|
|
1205
|
+
title = "Artifacts"
|
|
1206
|
+
} = options;
|
|
1207
|
+
if (artifacts.length === 0) {
|
|
1208
|
+
return [];
|
|
1209
|
+
}
|
|
1210
|
+
const sortedArtifacts = (sortByTime ? [...artifacts].sort((a, b) => (b.modified?.getTime() ?? 0) - (a.modified?.getTime() ?? 0)) : artifacts.slice()).slice(0, maxItems);
|
|
1211
|
+
const lines = [];
|
|
1212
|
+
lines.push(safeColors.bold(title));
|
|
1213
|
+
sortedArtifacts.forEach((artifact, index) => {
|
|
1214
|
+
if (index > 0) {
|
|
1215
|
+
lines.push("");
|
|
1216
|
+
}
|
|
1217
|
+
lines.push(
|
|
1218
|
+
...formatArtifactLines(artifact, {
|
|
1219
|
+
showSize,
|
|
1220
|
+
showTime,
|
|
1221
|
+
showDescription: false,
|
|
1222
|
+
indent: 0
|
|
1223
|
+
})
|
|
1224
|
+
);
|
|
1225
|
+
});
|
|
1226
|
+
return lines;
|
|
1227
|
+
}
|
|
1228
|
+
async function discoverArtifacts(baseDir, patterns) {
|
|
1229
|
+
const artifacts = [];
|
|
1230
|
+
for (const artifact of patterns) {
|
|
1231
|
+
const artifactPath = path__default.default.join(baseDir, artifact.pattern);
|
|
1232
|
+
try {
|
|
1233
|
+
await fs.promises.access(artifactPath);
|
|
1234
|
+
const stats = await fs.promises.stat(artifactPath);
|
|
1235
|
+
artifacts.push({
|
|
1236
|
+
name: artifact.name,
|
|
1237
|
+
path: artifactPath,
|
|
1238
|
+
size: stats.size,
|
|
1239
|
+
modified: stats.mtime,
|
|
1240
|
+
description: artifact.description || ""
|
|
1241
|
+
});
|
|
1242
|
+
} catch {
|
|
1243
|
+
}
|
|
1244
|
+
}
|
|
1245
|
+
return artifacts;
|
|
1246
|
+
}
|
|
1247
|
+
|
|
1248
|
+
// src/table.ts
|
|
1249
|
+
function visualWidth(str) {
|
|
1250
|
+
const ansiRegex = /\x1B\[[0-9;]*[a-zA-Z]/g;
|
|
1251
|
+
const cleanStr = str.replace(ansiRegex, "");
|
|
1252
|
+
const emojiRegex = /[\u{1F300}-\u{1F9FF}]|[\u{2600}-\u{26FF}]|[\u{2700}-\u{27BF}]|[\u{1F600}-\u{1F64F}]|[\u{1F680}-\u{1F6FF}]|[\u{1F900}-\u{1F9FF}]|[\u{1FA00}-\u{1FA6F}]|[\u{1FA70}-\u{1FAFF}]|[\u{2190}-\u{21FF}]|[\u{2300}-\u{23FF}]|[\u{24C2}-\u{1F251}]|[\u{2B50}-\u{2B55}]|[\u{3030}-\u{303D}]|[\u{3297}-\u{3299}]|[\u{1F000}-\u{1F02F}]|[\u{1F0A0}-\u{1F0FF}]|[\u{1F100}-\u{1F1FF}]|[\u{1F200}-\u{1F2FF}]|[\u{1F300}-\u{1F5FF}]|[\u{1F600}-\u{1F64F}]|[\u{1F680}-\u{1F6FF}]|[\u{1F700}-\u{1F7FF}]|[\u{1F800}-\u{1F8FF}]|[\u{1F900}-\u{1F9FF}]|[\u{1FA00}-\u{1FA6F}]|[\u{1FA70}-\u{1FAFF}]|[\u{23F0}-\u{23FF}]|[\u{25A0}-\u{25FF}]|[\u{2600}-\u{26FF}]|[\u{2700}-\u{27BF}]|[\u{FE00}-\u{FE0F}]|[\u{1F1E6}-\u{1F1FF}]|[\u{1F3FB}-\u{1F3FF}]|[\u{1F9B0}-\u{1F9B3}]|[\u{20E3}]|[\u{FE0F}]/gu;
|
|
1253
|
+
const emojiMatches = cleanStr.match(emojiRegex);
|
|
1254
|
+
const emojiCount = emojiMatches ? emojiMatches.length : 0;
|
|
1255
|
+
return cleanStr.length - emojiCount + emojiCount * 2;
|
|
1256
|
+
}
|
|
1257
|
+
function padVisual(str, width, padChar = " ") {
|
|
1258
|
+
const vWidth = visualWidth(str);
|
|
1259
|
+
const padding = Math.max(0, width - vWidth);
|
|
1260
|
+
return str + padChar.repeat(padding);
|
|
1261
|
+
}
|
|
1262
|
+
function formatTable(columns, rows, options = {}) {
|
|
1263
|
+
const { header = true, separator = "\u2500", padding = 1 } = options;
|
|
1264
|
+
const widths = columns.map((col, idx) => {
|
|
1265
|
+
if (col.width !== void 0) {
|
|
1266
|
+
return col.width;
|
|
1267
|
+
}
|
|
1268
|
+
let maxWidth = visualWidth(col.header);
|
|
1269
|
+
for (const row of rows) {
|
|
1270
|
+
if (row[idx]) {
|
|
1271
|
+
maxWidth = Math.max(maxWidth, visualWidth(String(row[idx])));
|
|
1272
|
+
}
|
|
1273
|
+
}
|
|
1274
|
+
return maxWidth;
|
|
1275
|
+
});
|
|
1276
|
+
const lines = [];
|
|
1277
|
+
if (header) {
|
|
1278
|
+
const headerCells = columns.map((col, idx) => {
|
|
1279
|
+
const cell = col.header;
|
|
1280
|
+
const width = widths[idx];
|
|
1281
|
+
return padVisual(cell, width);
|
|
1282
|
+
});
|
|
1283
|
+
lines.push(headerCells.join(" ".repeat(padding)));
|
|
1284
|
+
if (separator) {
|
|
1285
|
+
const separatorLine = widths.map((w) => separator.repeat(w)).join(" ".repeat(padding));
|
|
1286
|
+
lines.push(separatorLine);
|
|
1287
|
+
}
|
|
1288
|
+
}
|
|
1289
|
+
for (const row of rows) {
|
|
1290
|
+
const cells = columns.map((col, idx) => {
|
|
1291
|
+
const cell = row[idx] !== void 0 ? String(row[idx]) : "";
|
|
1292
|
+
const align = col.align || "left";
|
|
1293
|
+
const width = widths[idx];
|
|
1294
|
+
if (align === "right") {
|
|
1295
|
+
const vWidth = visualWidth(cell);
|
|
1296
|
+
const padding2 = Math.max(0, width - vWidth);
|
|
1297
|
+
return " ".repeat(padding2) + cell;
|
|
1298
|
+
} else if (align === "center") {
|
|
1299
|
+
const vWidth = visualWidth(cell);
|
|
1300
|
+
const padding2 = Math.max(0, width - vWidth);
|
|
1301
|
+
const leftPad = Math.floor(padding2 / 2);
|
|
1302
|
+
const rightPad = padding2 - leftPad;
|
|
1303
|
+
return " ".repeat(leftPad) + cell + " ".repeat(rightPad);
|
|
1304
|
+
} else {
|
|
1305
|
+
return padVisual(cell, width);
|
|
1306
|
+
}
|
|
1307
|
+
});
|
|
1308
|
+
lines.push(cells.join(" ".repeat(padding)));
|
|
1309
|
+
}
|
|
1310
|
+
return lines;
|
|
1311
|
+
}
|
|
1312
|
+
function formatKeyValueTable(data, options = {}) {
|
|
1313
|
+
const keys = Object.keys(data);
|
|
1314
|
+
if (keys.length === 0) {
|
|
1315
|
+
return [];
|
|
1316
|
+
}
|
|
1317
|
+
const keyWidth = options.keyWidth || Math.max(...keys.map((k) => visualWidth(k)), 0);
|
|
1318
|
+
const valueWidth = options.valueWidth || Math.max(...Object.values(data).map((v) => visualWidth(String(v))), 0);
|
|
1319
|
+
return keys.map((key) => {
|
|
1320
|
+
const value = String(data[key]);
|
|
1321
|
+
return `${padVisual(key, keyWidth)} ${padVisual(value, valueWidth)}`;
|
|
1322
|
+
});
|
|
1323
|
+
}
|
|
1324
|
+
|
|
1325
|
+
// src/debug/formatters/ai.ts
|
|
1326
|
+
function formatDebugEntryAI(entry) {
|
|
1327
|
+
return JSON.stringify(entry, null, 2);
|
|
1328
|
+
}
|
|
1329
|
+
function formatDebugEntriesAI(entries) {
|
|
1330
|
+
return JSON.stringify(entries, null, 2);
|
|
1331
|
+
}
|
|
1332
|
+
function shouldUseAIFormat(format, jsonMode) {
|
|
1333
|
+
if (jsonMode) {
|
|
1334
|
+
return true;
|
|
1335
|
+
}
|
|
1336
|
+
return format === "ai";
|
|
1337
|
+
}
|
|
1338
|
+
|
|
1339
|
+
// src/debug/formatters/human.ts
|
|
1340
|
+
function formatTimestamp2(timestamp) {
|
|
1341
|
+
const date = new Date(timestamp);
|
|
1342
|
+
return date.toISOString();
|
|
1343
|
+
}
|
|
1344
|
+
function formatDuration(duration) {
|
|
1345
|
+
if (duration < 1e3) {
|
|
1346
|
+
return `${duration}ms`;
|
|
1347
|
+
}
|
|
1348
|
+
return `${(duration / 1e3).toFixed(2)}s`;
|
|
1349
|
+
}
|
|
1350
|
+
function formatDebugEntryHuman(entry, options = {}) {
|
|
1351
|
+
const parts = [];
|
|
1352
|
+
if (options.showTimestamp) {
|
|
1353
|
+
parts.push(safeColors.dim(formatTimestamp2(entry.timestamp)));
|
|
1354
|
+
}
|
|
1355
|
+
parts.push(safeColors.bold(`[${entry.namespace}]`));
|
|
1356
|
+
parts.push(entry.message);
|
|
1357
|
+
if (options.showDuration && typeof entry.duration === "number") {
|
|
1358
|
+
parts.push(safeColors.dim(`(${formatDuration(entry.duration)})`));
|
|
1359
|
+
}
|
|
1360
|
+
if (entry.level === "error") {
|
|
1361
|
+
parts.push(safeColors.error(safeSymbols.error));
|
|
1362
|
+
} else if (entry.level === "warn") {
|
|
1363
|
+
parts.push(safeColors.warning(safeSymbols.warning));
|
|
1364
|
+
}
|
|
1365
|
+
return parts.join(" ");
|
|
1366
|
+
}
|
|
1367
|
+
function formatDebugEntriesHuman(entries, options = {}) {
|
|
1368
|
+
if (entries.length === 0) {
|
|
1369
|
+
return "";
|
|
1370
|
+
}
|
|
1371
|
+
const sorted = [...entries].sort((a, b) => a.timestamp - b.timestamp);
|
|
1372
|
+
const lines = [];
|
|
1373
|
+
if (options.groupBy === "namespace") {
|
|
1374
|
+
const namespaces = /* @__PURE__ */ new Map();
|
|
1375
|
+
for (const entry of sorted) {
|
|
1376
|
+
if (!namespaces.has(entry.namespace)) {
|
|
1377
|
+
namespaces.set(entry.namespace, []);
|
|
1378
|
+
}
|
|
1379
|
+
namespaces.get(entry.namespace).push(entry);
|
|
1380
|
+
}
|
|
1381
|
+
for (const [namespace, namespaceEntries] of namespaces) {
|
|
1382
|
+
lines.push(safeColors.bold(namespace));
|
|
1383
|
+
for (const entry of namespaceEntries) {
|
|
1384
|
+
lines.push(` ${formatDebugEntryHuman(entry, options)}`);
|
|
1385
|
+
}
|
|
1386
|
+
lines.push("");
|
|
1387
|
+
}
|
|
1388
|
+
return lines.join("\n").trimEnd();
|
|
1389
|
+
}
|
|
1390
|
+
if (options.groupBy === "group") {
|
|
1391
|
+
const groups = /* @__PURE__ */ new Map();
|
|
1392
|
+
for (const entry of sorted) {
|
|
1393
|
+
const groupName = entry.group ?? "default";
|
|
1394
|
+
if (!groups.has(groupName)) {
|
|
1395
|
+
groups.set(groupName, []);
|
|
1396
|
+
}
|
|
1397
|
+
groups.get(groupName).push(entry);
|
|
1398
|
+
}
|
|
1399
|
+
for (const [groupName, groupEntries] of groups) {
|
|
1400
|
+
lines.push(safeColors.bold(groupName));
|
|
1401
|
+
for (const entry of groupEntries) {
|
|
1402
|
+
lines.push(` ${formatDebugEntryHuman(entry, options)}`);
|
|
1403
|
+
}
|
|
1404
|
+
lines.push("");
|
|
1405
|
+
}
|
|
1406
|
+
return lines.join("\n").trimEnd();
|
|
1407
|
+
}
|
|
1408
|
+
for (const entry of sorted) {
|
|
1409
|
+
lines.push(formatDebugEntryHuman(entry, options));
|
|
1410
|
+
}
|
|
1411
|
+
return lines.join("\n");
|
|
1412
|
+
}
|
|
1413
|
+
|
|
1414
|
+
// src/debug/utilities.ts
|
|
1415
|
+
function toRegex(pattern) {
|
|
1416
|
+
if (!pattern.includes("*")) {
|
|
1417
|
+
return new RegExp(`^${pattern.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}$`, "i");
|
|
1418
|
+
}
|
|
1419
|
+
const escaped = pattern.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*");
|
|
1420
|
+
return new RegExp(`^${escaped}$`, "i");
|
|
1421
|
+
}
|
|
1422
|
+
function filterByNamespace(entries, pattern) {
|
|
1423
|
+
const matcher = typeof pattern === "string" ? toRegex(pattern) : pattern;
|
|
1424
|
+
return entries.filter((entry) => matcher.test(entry.namespace));
|
|
1425
|
+
}
|
|
1426
|
+
function filterByLevel(entries, level) {
|
|
1427
|
+
const allowed = Array.isArray(level) ? new Set(level) : /* @__PURE__ */ new Set([level]);
|
|
1428
|
+
return entries.filter((entry) => allowed.has(entry.level));
|
|
1429
|
+
}
|
|
1430
|
+
function filterByTimeRange(entries, from, to) {
|
|
1431
|
+
return entries.filter((entry) => {
|
|
1432
|
+
if (from !== void 0 && entry.timestamp < from) {
|
|
1433
|
+
return false;
|
|
1434
|
+
}
|
|
1435
|
+
if (to !== void 0 && entry.timestamp > to) {
|
|
1436
|
+
return false;
|
|
1437
|
+
}
|
|
1438
|
+
return true;
|
|
1439
|
+
});
|
|
1440
|
+
}
|
|
1441
|
+
function searchInLogs(entries, query) {
|
|
1442
|
+
const lowered = query.toLowerCase();
|
|
1443
|
+
return entries.filter((entry) => {
|
|
1444
|
+
if (entry.message.toLowerCase().includes(lowered)) {
|
|
1445
|
+
return true;
|
|
1446
|
+
}
|
|
1447
|
+
if (entry.namespace.toLowerCase().includes(lowered)) {
|
|
1448
|
+
return true;
|
|
1449
|
+
}
|
|
1450
|
+
if (entry.meta) {
|
|
1451
|
+
const metaString = JSON.stringify(entry.meta).toLowerCase();
|
|
1452
|
+
if (metaString.includes(lowered)) {
|
|
1453
|
+
return true;
|
|
1454
|
+
}
|
|
1455
|
+
}
|
|
1456
|
+
return false;
|
|
1457
|
+
});
|
|
1458
|
+
}
|
|
1459
|
+
function filterDebugEntries(entries, options) {
|
|
1460
|
+
let filtered = [...entries];
|
|
1461
|
+
if (options.namespace) {
|
|
1462
|
+
filtered = filterByNamespace(filtered, options.namespace);
|
|
1463
|
+
}
|
|
1464
|
+
if (options.level) {
|
|
1465
|
+
filtered = filterByLevel(filtered, options.level);
|
|
1466
|
+
}
|
|
1467
|
+
if (options.timeRange) {
|
|
1468
|
+
filtered = filterByTimeRange(filtered, options.timeRange.from, options.timeRange.to);
|
|
1469
|
+
}
|
|
1470
|
+
if (options.search) {
|
|
1471
|
+
filtered = searchInLogs(filtered, options.search);
|
|
1472
|
+
}
|
|
1473
|
+
if (options.traceId) {
|
|
1474
|
+
filtered = filtered.filter((entry) => entry.traceId === options.traceId);
|
|
1475
|
+
}
|
|
1476
|
+
return filtered;
|
|
1477
|
+
}
|
|
1478
|
+
function groupByNamespace(entries) {
|
|
1479
|
+
const map = /* @__PURE__ */ new Map();
|
|
1480
|
+
for (const entry of entries) {
|
|
1481
|
+
if (!map.has(entry.namespace)) {
|
|
1482
|
+
map.set(entry.namespace, []);
|
|
1483
|
+
}
|
|
1484
|
+
map.get(entry.namespace).push(entry);
|
|
1485
|
+
}
|
|
1486
|
+
return map;
|
|
1487
|
+
}
|
|
1488
|
+
function groupByGroup(entries) {
|
|
1489
|
+
const map = /* @__PURE__ */ new Map();
|
|
1490
|
+
for (const entry of entries) {
|
|
1491
|
+
const group = entry.group ?? "default";
|
|
1492
|
+
if (!map.has(group)) {
|
|
1493
|
+
map.set(group, []);
|
|
1494
|
+
}
|
|
1495
|
+
map.get(group).push(entry);
|
|
1496
|
+
}
|
|
1497
|
+
return map;
|
|
1498
|
+
}
|
|
1499
|
+
function createDebugTree(entries) {
|
|
1500
|
+
if (entries.length === 0) {
|
|
1501
|
+
return null;
|
|
1502
|
+
}
|
|
1503
|
+
const sorted = [...entries].sort((a, b) => a.timestamp - b.timestamp);
|
|
1504
|
+
const nodes = /* @__PURE__ */ new Map();
|
|
1505
|
+
let root = null;
|
|
1506
|
+
function ensureNode(entry) {
|
|
1507
|
+
if (entry.spanId && nodes.has(entry.spanId)) {
|
|
1508
|
+
return nodes.get(entry.spanId);
|
|
1509
|
+
}
|
|
1510
|
+
const node = { entry, children: [], depth: 0 };
|
|
1511
|
+
if (entry.spanId) {
|
|
1512
|
+
nodes.set(entry.spanId, node);
|
|
1513
|
+
}
|
|
1514
|
+
return node;
|
|
1515
|
+
}
|
|
1516
|
+
for (const entry of sorted) {
|
|
1517
|
+
const node = ensureNode(entry);
|
|
1518
|
+
if (entry.parentSpanId && nodes.has(entry.parentSpanId)) {
|
|
1519
|
+
const parent = nodes.get(entry.parentSpanId);
|
|
1520
|
+
node.depth = parent.depth + 1;
|
|
1521
|
+
parent.children.push(node);
|
|
1522
|
+
} else if (root === null) {
|
|
1523
|
+
root = node;
|
|
1524
|
+
} else {
|
|
1525
|
+
node.depth = root.depth + 1;
|
|
1526
|
+
root.children.push(node);
|
|
1527
|
+
}
|
|
1528
|
+
}
|
|
1529
|
+
return root;
|
|
1530
|
+
}
|
|
1531
|
+
function exportToJSON(entries, options = {}) {
|
|
1532
|
+
const filtered = options.filter ? filterDebugEntries(entries, options.filter) : entries;
|
|
1533
|
+
if (options.includeMeta === false) {
|
|
1534
|
+
return JSON.stringify(
|
|
1535
|
+
filtered.map(({ meta, ...rest }) => rest),
|
|
1536
|
+
null,
|
|
1537
|
+
2
|
|
1538
|
+
);
|
|
1539
|
+
}
|
|
1540
|
+
return JSON.stringify(filtered, null, 2);
|
|
1541
|
+
}
|
|
1542
|
+
function exportToChromeFormat(entries, options = {}) {
|
|
1543
|
+
const filtered = options.filter ? filterDebugEntries(entries, options.filter) : entries;
|
|
1544
|
+
const traceEvents = filtered.map((entry) => ({
|
|
1545
|
+
name: entry.message,
|
|
1546
|
+
cat: entry.namespace,
|
|
1547
|
+
ph: entry.level === "error" ? "E" : entry.level === "warn" ? "W" : "X",
|
|
1548
|
+
ts: entry.timestamp * 1e3,
|
|
1549
|
+
dur: (entry.duration ?? 0) * 1e3,
|
|
1550
|
+
pid: 1,
|
|
1551
|
+
tid: entry.spanId ?? entry.namespace,
|
|
1552
|
+
args: entry.meta ?? {}
|
|
1553
|
+
}));
|
|
1554
|
+
return JSON.stringify({ traceEvents }, null, 2);
|
|
1555
|
+
}
|
|
1556
|
+
function exportToPlainText(entries, options = {}) {
|
|
1557
|
+
const filtered = options.filter ? filterDebugEntries(entries, options.filter) : entries;
|
|
1558
|
+
return formatDebugEntriesHuman(filtered, { groupBy: "namespace", showTimestamp: true, showDuration: true });
|
|
1559
|
+
}
|
|
1560
|
+
function exportDebugEntries(entries, options) {
|
|
1561
|
+
const format = options.format ?? "json";
|
|
1562
|
+
switch (format) {
|
|
1563
|
+
case "chrome":
|
|
1564
|
+
return exportToChromeFormat(entries, options);
|
|
1565
|
+
case "text":
|
|
1566
|
+
return exportToPlainText(entries, options);
|
|
1567
|
+
case "json":
|
|
1568
|
+
default:
|
|
1569
|
+
return exportToJSON(entries, options);
|
|
1570
|
+
}
|
|
1571
|
+
}
|
|
1572
|
+
function describeEntriesHuman(entries, options = {}) {
|
|
1573
|
+
const filtered = filterDebugEntries(entries, options);
|
|
1574
|
+
return formatDebugEntriesHuman(filtered, { showTimestamp: true, showDuration: true, groupBy: "namespace" });
|
|
1575
|
+
}
|
|
1576
|
+
function describeEntriesAI(entries, options = {}) {
|
|
1577
|
+
const filtered = filterDebugEntries(entries, options);
|
|
1578
|
+
return formatDebugEntriesAI(filtered);
|
|
1579
|
+
}
|
|
1580
|
+
function describeEntriesTimeline(entries, options = {}) {
|
|
1581
|
+
const filtered = filterDebugEntries(entries, options);
|
|
1582
|
+
return formatTimelineWithSummary(filtered);
|
|
1583
|
+
}
|
|
1584
|
+
|
|
1585
|
+
// src/debug/formatters/timeline.ts
|
|
1586
|
+
function formatDuration2(duration) {
|
|
1587
|
+
if (duration < 1e3) {
|
|
1588
|
+
return `${duration}ms`;
|
|
1589
|
+
}
|
|
1590
|
+
return `${(duration / 1e3).toFixed(2)}s`;
|
|
1591
|
+
}
|
|
1592
|
+
function formatTimelineNode(node, isLast, prefix = "", maxDepth) {
|
|
1593
|
+
const lines = [];
|
|
1594
|
+
const connector = isLast ? "\u2514\u2500" : "\u251C\u2500";
|
|
1595
|
+
const parts = [];
|
|
1596
|
+
parts.push(safeColors.bold(`[${node.entry.namespace}]`));
|
|
1597
|
+
parts.push(node.entry.message);
|
|
1598
|
+
if (typeof node.entry.duration === "number") {
|
|
1599
|
+
parts.push(safeColors.dim(`(${formatDuration2(node.entry.duration)})`));
|
|
1600
|
+
}
|
|
1601
|
+
if (node.entry.level === "error") {
|
|
1602
|
+
parts.push(safeColors.error(safeSymbols.error));
|
|
1603
|
+
} else if (node.entry.level === "warn") {
|
|
1604
|
+
parts.push(safeColors.warning(safeSymbols.warning));
|
|
1605
|
+
}
|
|
1606
|
+
lines.push(`${prefix}${connector} ${parts.join(" ")}`.trimEnd());
|
|
1607
|
+
if (maxDepth !== void 0 && node.depth + 1 >= maxDepth) {
|
|
1608
|
+
return lines;
|
|
1609
|
+
}
|
|
1610
|
+
const childPrefix = prefix + (isLast ? " " : "\u2502 ");
|
|
1611
|
+
for (let index = 0; index < node.children.length; index++) {
|
|
1612
|
+
const child = node.children[index];
|
|
1613
|
+
if (!child) {
|
|
1614
|
+
continue;
|
|
1615
|
+
}
|
|
1616
|
+
const childIsLast = index === node.children.length - 1;
|
|
1617
|
+
lines.push(...formatTimelineNode(child, childIsLast, childPrefix, maxDepth));
|
|
1618
|
+
}
|
|
1619
|
+
return lines;
|
|
1620
|
+
}
|
|
1621
|
+
function formatTimeline(entries) {
|
|
1622
|
+
if (entries.length === 0) {
|
|
1623
|
+
return "";
|
|
1624
|
+
}
|
|
1625
|
+
const tree = createDebugTree(entries);
|
|
1626
|
+
if (!tree) {
|
|
1627
|
+
return "";
|
|
1628
|
+
}
|
|
1629
|
+
return formatTimelineNode(tree, true).join("\n");
|
|
1630
|
+
}
|
|
1631
|
+
function formatTimelineWithSummary(entries) {
|
|
1632
|
+
const timeline = formatTimeline(entries);
|
|
1633
|
+
if (timeline.length === 0) {
|
|
1634
|
+
return "";
|
|
1635
|
+
}
|
|
1636
|
+
const totalDuration = entries.reduce((acc, entry) => acc + (entry.duration ?? 0), 0);
|
|
1637
|
+
const errorCount = entries.filter((entry) => entry.level === "error").length;
|
|
1638
|
+
const warnCount = entries.filter((entry) => entry.level === "warn").length;
|
|
1639
|
+
const summaryParts = [];
|
|
1640
|
+
if (totalDuration > 0) {
|
|
1641
|
+
summaryParts.push(`Total: ${formatDuration2(totalDuration)}`);
|
|
1642
|
+
}
|
|
1643
|
+
if (errorCount > 0) {
|
|
1644
|
+
summaryParts.push(safeColors.error(`${errorCount} errors`));
|
|
1645
|
+
}
|
|
1646
|
+
if (warnCount > 0) {
|
|
1647
|
+
summaryParts.push(safeColors.warning(`${warnCount} warnings`));
|
|
1648
|
+
}
|
|
1649
|
+
if (summaryParts.length === 0) {
|
|
1650
|
+
return timeline;
|
|
1651
|
+
}
|
|
1652
|
+
return `${timeline}
|
|
1653
|
+
|
|
1654
|
+
${safeColors.bold("Summary:")} ${summaryParts.join(", ")}`;
|
|
1655
|
+
}
|
|
1656
|
+
|
|
1657
|
+
// src/debug/components/output.ts
|
|
1658
|
+
function formatDebugOutput(entry, options = {}) {
|
|
1659
|
+
if (shouldUseAIFormat(options.format)) {
|
|
1660
|
+
return formatDebugEntryAI(entry);
|
|
1661
|
+
}
|
|
1662
|
+
return formatDebugEntryHuman(entry, options);
|
|
1663
|
+
}
|
|
1664
|
+
function formatDebugOutputs(entries, options = {}) {
|
|
1665
|
+
if (shouldUseAIFormat(options.format)) {
|
|
1666
|
+
return formatDebugEntriesAI(entries);
|
|
1667
|
+
}
|
|
1668
|
+
if (options.useTimeline) {
|
|
1669
|
+
return formatTimelineWithSummary(entries);
|
|
1670
|
+
}
|
|
1671
|
+
return formatDebugEntriesHuman(entries, options);
|
|
1672
|
+
}
|
|
1673
|
+
var DebugSection = class {
|
|
1674
|
+
entries = [];
|
|
1675
|
+
title;
|
|
1676
|
+
options;
|
|
1677
|
+
constructor(title, options = {}) {
|
|
1678
|
+
this.title = title;
|
|
1679
|
+
this.options = options;
|
|
1680
|
+
}
|
|
1681
|
+
add(entry) {
|
|
1682
|
+
this.entries.push(entry);
|
|
1683
|
+
}
|
|
1684
|
+
addAll(entries) {
|
|
1685
|
+
this.entries.push(...entries);
|
|
1686
|
+
}
|
|
1687
|
+
clear() {
|
|
1688
|
+
this.entries.length = 0;
|
|
1689
|
+
}
|
|
1690
|
+
format() {
|
|
1691
|
+
if (this.entries.length === 0) {
|
|
1692
|
+
return "";
|
|
1693
|
+
}
|
|
1694
|
+
const content = formatDebugOutputs(this.entries, this.options);
|
|
1695
|
+
if (!content) {
|
|
1696
|
+
return "";
|
|
1697
|
+
}
|
|
1698
|
+
if (shouldUseAIFormat(this.options.format)) {
|
|
1699
|
+
return content;
|
|
1700
|
+
}
|
|
1701
|
+
return box(this.title, content.split("\n"));
|
|
1702
|
+
}
|
|
1703
|
+
get count() {
|
|
1704
|
+
return this.entries.length;
|
|
1705
|
+
}
|
|
1706
|
+
};
|
|
1707
|
+
var DebugOutput = class {
|
|
1708
|
+
sections = /* @__PURE__ */ new Map();
|
|
1709
|
+
globalEntries = [];
|
|
1710
|
+
options;
|
|
1711
|
+
constructor(options = {}) {
|
|
1712
|
+
this.options = options;
|
|
1713
|
+
}
|
|
1714
|
+
add(entry) {
|
|
1715
|
+
this.globalEntries.push(entry);
|
|
1716
|
+
}
|
|
1717
|
+
addToSection(sectionName, entry) {
|
|
1718
|
+
if (!this.sections.has(sectionName)) {
|
|
1719
|
+
this.sections.set(sectionName, new DebugSection(sectionName, this.options));
|
|
1720
|
+
}
|
|
1721
|
+
this.sections.get(sectionName).add(entry);
|
|
1722
|
+
}
|
|
1723
|
+
getSection(sectionName) {
|
|
1724
|
+
if (!this.sections.has(sectionName)) {
|
|
1725
|
+
this.sections.set(sectionName, new DebugSection(sectionName, this.options));
|
|
1726
|
+
}
|
|
1727
|
+
return this.sections.get(sectionName);
|
|
1728
|
+
}
|
|
1729
|
+
format() {
|
|
1730
|
+
const parts = [];
|
|
1731
|
+
if (this.globalEntries.length > 0) {
|
|
1732
|
+
const formatted = formatDebugOutputs(this.globalEntries, this.options);
|
|
1733
|
+
if (formatted) {
|
|
1734
|
+
parts.push(formatted);
|
|
1735
|
+
}
|
|
1736
|
+
}
|
|
1737
|
+
for (const [, section2] of this.sections) {
|
|
1738
|
+
const formatted = section2.format();
|
|
1739
|
+
if (formatted) {
|
|
1740
|
+
parts.push(formatted);
|
|
1741
|
+
}
|
|
1742
|
+
}
|
|
1743
|
+
return parts.join("\n\n");
|
|
1744
|
+
}
|
|
1745
|
+
clear() {
|
|
1746
|
+
this.globalEntries.length = 0;
|
|
1747
|
+
this.sections.clear();
|
|
1748
|
+
}
|
|
1749
|
+
get totalCount() {
|
|
1750
|
+
let count = this.globalEntries.length;
|
|
1751
|
+
for (const section2 of this.sections.values()) {
|
|
1752
|
+
count += section2.count;
|
|
1753
|
+
}
|
|
1754
|
+
return count;
|
|
1755
|
+
}
|
|
1756
|
+
};
|
|
1757
|
+
|
|
1758
|
+
// src/debug/components/tree.ts
|
|
1759
|
+
var DebugTree = class {
|
|
1760
|
+
tree = null;
|
|
1761
|
+
options;
|
|
1762
|
+
constructor(entries, options = {}) {
|
|
1763
|
+
this.options = options;
|
|
1764
|
+
this.tree = createDebugTree(entries);
|
|
1765
|
+
}
|
|
1766
|
+
update(entries) {
|
|
1767
|
+
this.tree = createDebugTree(entries);
|
|
1768
|
+
}
|
|
1769
|
+
format() {
|
|
1770
|
+
if (!this.tree) {
|
|
1771
|
+
return "";
|
|
1772
|
+
}
|
|
1773
|
+
const lines = formatTimelineNode(this.tree, true, "", this.options.maxDepth);
|
|
1774
|
+
if (this.options.showSummary) {
|
|
1775
|
+
const summary = this.getSummary();
|
|
1776
|
+
if (summary) {
|
|
1777
|
+
lines.push("", summary);
|
|
1778
|
+
}
|
|
1779
|
+
}
|
|
1780
|
+
return lines.join("\n");
|
|
1781
|
+
}
|
|
1782
|
+
getSummary() {
|
|
1783
|
+
if (!this.tree) {
|
|
1784
|
+
return "";
|
|
1785
|
+
}
|
|
1786
|
+
const stats = this.collectStats(this.tree);
|
|
1787
|
+
const parts = [];
|
|
1788
|
+
if (stats.totalDuration > 0) {
|
|
1789
|
+
parts.push(`total ${stats.totalDuration}ms`);
|
|
1790
|
+
}
|
|
1791
|
+
if (stats.errorCount > 0) {
|
|
1792
|
+
parts.push(`${stats.errorCount} errors`);
|
|
1793
|
+
}
|
|
1794
|
+
if (stats.warnCount > 0) {
|
|
1795
|
+
parts.push(`${stats.warnCount} warnings`);
|
|
1796
|
+
}
|
|
1797
|
+
parts.push(`${stats.nodeCount} nodes`);
|
|
1798
|
+
return `Summary: ${parts.join(", ")}`;
|
|
1799
|
+
}
|
|
1800
|
+
collectStats(node) {
|
|
1801
|
+
let totalDuration = node.entry.duration ?? 0;
|
|
1802
|
+
let errorCount = node.entry.level === "error" ? 1 : 0;
|
|
1803
|
+
let warnCount = node.entry.level === "warn" ? 1 : 0;
|
|
1804
|
+
let nodeCount = 1;
|
|
1805
|
+
for (const child of node.children) {
|
|
1806
|
+
const childStats = this.collectStats(child);
|
|
1807
|
+
totalDuration += childStats.totalDuration;
|
|
1808
|
+
errorCount += childStats.errorCount;
|
|
1809
|
+
warnCount += childStats.warnCount;
|
|
1810
|
+
nodeCount += childStats.nodeCount;
|
|
1811
|
+
}
|
|
1812
|
+
return { totalDuration, errorCount, warnCount, nodeCount };
|
|
1813
|
+
}
|
|
1814
|
+
get root() {
|
|
1815
|
+
return this.tree;
|
|
1816
|
+
}
|
|
1817
|
+
};
|
|
1818
|
+
|
|
1819
|
+
// src/debug/components/trace.ts
|
|
1820
|
+
var DebugTrace = class {
|
|
1821
|
+
entries = [];
|
|
1822
|
+
options;
|
|
1823
|
+
constructor(entries = [], options = {}) {
|
|
1824
|
+
this.entries.push(...entries);
|
|
1825
|
+
this.options = options;
|
|
1826
|
+
}
|
|
1827
|
+
add(entry) {
|
|
1828
|
+
this.entries.push(entry);
|
|
1829
|
+
}
|
|
1830
|
+
addAll(entries) {
|
|
1831
|
+
this.entries.push(...entries);
|
|
1832
|
+
}
|
|
1833
|
+
clear() {
|
|
1834
|
+
this.entries.length = 0;
|
|
1835
|
+
}
|
|
1836
|
+
format() {
|
|
1837
|
+
if (this.entries.length === 0) {
|
|
1838
|
+
return "";
|
|
1839
|
+
}
|
|
1840
|
+
const sorted = [...this.entries].sort((a, b) => a.timestamp - b.timestamp);
|
|
1841
|
+
if (this.options.groupByPlugin) {
|
|
1842
|
+
return this.formatGrouped(sorted);
|
|
1843
|
+
}
|
|
1844
|
+
return formatTimelineWithSummary(sorted);
|
|
1845
|
+
}
|
|
1846
|
+
formatGrouped(entries) {
|
|
1847
|
+
const groups = /* @__PURE__ */ new Map();
|
|
1848
|
+
for (const entry of entries) {
|
|
1849
|
+
const plugin = entry.namespace.split(":")[0] ?? entry.namespace;
|
|
1850
|
+
if (!groups.has(plugin)) {
|
|
1851
|
+
groups.set(plugin, []);
|
|
1852
|
+
}
|
|
1853
|
+
groups.get(plugin).push(entry);
|
|
1854
|
+
}
|
|
1855
|
+
const parts = [];
|
|
1856
|
+
for (const [plugin, pluginEntries] of groups) {
|
|
1857
|
+
const tree = new DebugTree(pluginEntries, {
|
|
1858
|
+
showSummary: this.options.showSummary,
|
|
1859
|
+
maxDepth: this.options.maxDepth
|
|
1860
|
+
});
|
|
1861
|
+
const formatted = tree.format();
|
|
1862
|
+
if (formatted) {
|
|
1863
|
+
parts.push(`[${plugin}]`, formatted);
|
|
1864
|
+
}
|
|
1865
|
+
}
|
|
1866
|
+
return parts.join("\n\n");
|
|
1867
|
+
}
|
|
1868
|
+
getStats() {
|
|
1869
|
+
const plugins = /* @__PURE__ */ new Set();
|
|
1870
|
+
let totalDuration = 0;
|
|
1871
|
+
let errorCount = 0;
|
|
1872
|
+
let warnCount = 0;
|
|
1873
|
+
for (const entry of this.entries) {
|
|
1874
|
+
const plugin = entry.namespace.split(":")[0] ?? entry.namespace;
|
|
1875
|
+
plugins.add(plugin);
|
|
1876
|
+
totalDuration += entry.duration ?? 0;
|
|
1877
|
+
if (entry.level === "error") {
|
|
1878
|
+
errorCount += 1;
|
|
1879
|
+
} else if (entry.level === "warn") {
|
|
1880
|
+
warnCount += 1;
|
|
1881
|
+
}
|
|
1882
|
+
}
|
|
1883
|
+
return {
|
|
1884
|
+
totalEntries: this.entries.length,
|
|
1885
|
+
plugins: Array.from(plugins),
|
|
1886
|
+
totalDuration,
|
|
1887
|
+
errorCount,
|
|
1888
|
+
warnCount
|
|
1889
|
+
};
|
|
1890
|
+
}
|
|
1891
|
+
};
|
|
1892
|
+
|
|
1893
|
+
// src/command-runner.ts
|
|
1894
|
+
function createCommandRunner(options) {
|
|
1895
|
+
return async (ctx, argv, flags) => {
|
|
1896
|
+
const tracker = new TimingTracker();
|
|
1897
|
+
const jsonMode = flags.json === true;
|
|
1898
|
+
const quietMode = flags.quiet === true;
|
|
1899
|
+
let runScope = null;
|
|
1900
|
+
if (options.analytics !== void 0) {
|
|
1901
|
+
try {
|
|
1902
|
+
const analyticsModule = await import('@kb-labs/analytics-sdk-node');
|
|
1903
|
+
if (analyticsModule.runScope) {
|
|
1904
|
+
runScope = analyticsModule.runScope;
|
|
1905
|
+
}
|
|
1906
|
+
} catch {
|
|
1907
|
+
runScope = null;
|
|
1908
|
+
}
|
|
1909
|
+
}
|
|
1910
|
+
const execute = async () => {
|
|
1911
|
+
tracker.checkpoint("start");
|
|
1912
|
+
try {
|
|
1913
|
+
const result2 = await options.execute(ctx, flags, tracker);
|
|
1914
|
+
tracker.checkpoint("complete");
|
|
1915
|
+
formatSuccessOutput(ctx, options.title, result2, tracker.total(), {
|
|
1916
|
+
jsonMode,
|
|
1917
|
+
quietMode
|
|
1918
|
+
});
|
|
1919
|
+
return 0;
|
|
1920
|
+
} catch (error) {
|
|
1921
|
+
tracker.checkpoint("error");
|
|
1922
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1923
|
+
formatErrorOutput(ctx, message, tracker.total(), {
|
|
1924
|
+
jsonMode,
|
|
1925
|
+
quietMode
|
|
1926
|
+
});
|
|
1927
|
+
return 1;
|
|
1928
|
+
}
|
|
1929
|
+
};
|
|
1930
|
+
if (!runScope || !options.analytics) {
|
|
1931
|
+
return execute();
|
|
1932
|
+
}
|
|
1933
|
+
const totalStart = Date.now();
|
|
1934
|
+
const result = await runScope(
|
|
1935
|
+
{
|
|
1936
|
+
actor: options.analytics.actor,
|
|
1937
|
+
ctx: { workspace: ctx.cwd }
|
|
1938
|
+
},
|
|
1939
|
+
async (emit) => {
|
|
1940
|
+
await emit({
|
|
1941
|
+
type: options.analytics.started,
|
|
1942
|
+
payload: options.analytics.getPayload?.(flags) ?? {}
|
|
1943
|
+
});
|
|
1944
|
+
let exitCode = 0;
|
|
1945
|
+
try {
|
|
1946
|
+
exitCode = await execute();
|
|
1947
|
+
await emit({
|
|
1948
|
+
type: options.analytics.finished,
|
|
1949
|
+
payload: {
|
|
1950
|
+
...options.analytics.getPayload?.(flags) ?? {},
|
|
1951
|
+
durationMs: Date.now() - totalStart,
|
|
1952
|
+
result: exitCode === 0 ? "success" : "error"
|
|
1953
|
+
}
|
|
1954
|
+
});
|
|
1955
|
+
} catch (error) {
|
|
1956
|
+
await emit({
|
|
1957
|
+
type: options.analytics.finished,
|
|
1958
|
+
payload: {
|
|
1959
|
+
...options.analytics.getPayload?.(flags) ?? {},
|
|
1960
|
+
durationMs: Date.now() - totalStart,
|
|
1961
|
+
result: "error",
|
|
1962
|
+
error: error instanceof Error ? error.message : String(error)
|
|
1963
|
+
}
|
|
1964
|
+
});
|
|
1965
|
+
throw error;
|
|
1966
|
+
}
|
|
1967
|
+
return exitCode;
|
|
1968
|
+
}
|
|
1969
|
+
);
|
|
1970
|
+
return result;
|
|
1971
|
+
};
|
|
1972
|
+
}
|
|
1973
|
+
function formatSuccessOutput(ctx, title, result, durationMs, flags) {
|
|
1974
|
+
if (flags.jsonMode) {
|
|
1975
|
+
const payload = {
|
|
1976
|
+
ok: true,
|
|
1977
|
+
summary: result.summary,
|
|
1978
|
+
timing: result.timing ?? durationMs,
|
|
1979
|
+
diagnostics: result.diagnostics,
|
|
1980
|
+
warnings: result.warnings,
|
|
1981
|
+
errors: result.errors
|
|
1982
|
+
};
|
|
1983
|
+
if (result.artifacts) {
|
|
1984
|
+
payload.artifacts = result.artifacts;
|
|
1985
|
+
}
|
|
1986
|
+
if (result.data) {
|
|
1987
|
+
Object.assign(payload, result.data);
|
|
1988
|
+
}
|
|
1989
|
+
ctx.presenter.json(payload);
|
|
1990
|
+
return;
|
|
1991
|
+
}
|
|
1992
|
+
if (flags.quietMode) {
|
|
1993
|
+
return;
|
|
1994
|
+
}
|
|
1995
|
+
const statusEntry = extractStatusEntry(result.summary);
|
|
1996
|
+
const summaryForDisplay = statusEntry ? { ...result.summary } : result.summary;
|
|
1997
|
+
if (statusEntry) {
|
|
1998
|
+
delete summaryForDisplay[statusEntry.key];
|
|
1999
|
+
}
|
|
2000
|
+
const lines = [];
|
|
2001
|
+
const summaryLines = keyValue(summaryForDisplay);
|
|
2002
|
+
if (summaryLines.length > 0) {
|
|
2003
|
+
lines.push(...summaryLines);
|
|
2004
|
+
}
|
|
2005
|
+
if (result.artifacts && result.artifacts.length > 0) {
|
|
2006
|
+
if (lines.length > 0) {
|
|
2007
|
+
lines.push("");
|
|
2008
|
+
}
|
|
2009
|
+
lines.push(...displayArtifacts(result.artifacts, result.artifactsOptions));
|
|
2010
|
+
}
|
|
2011
|
+
const timing = result.timing ?? durationMs;
|
|
2012
|
+
if (typeof timing !== "number") {
|
|
2013
|
+
const entries = Object.entries(timing);
|
|
2014
|
+
if (entries.length > 0) {
|
|
2015
|
+
if (lines.length > 0) {
|
|
2016
|
+
lines.push("");
|
|
2017
|
+
}
|
|
2018
|
+
lines.push(safeColors.bold("Timing"));
|
|
2019
|
+
for (const [label, value] of entries) {
|
|
2020
|
+
lines.push(...safeKeyValue({ [label]: formatTiming(value) }, { indent: 2, pad: false }));
|
|
2021
|
+
}
|
|
2022
|
+
}
|
|
2023
|
+
}
|
|
2024
|
+
if (result.diagnostics && result.diagnostics.length > 0) {
|
|
2025
|
+
if (lines.length > 0) {
|
|
2026
|
+
lines.push("");
|
|
2027
|
+
}
|
|
2028
|
+
lines.push(safeColors.bold("Diagnostics"));
|
|
2029
|
+
result.diagnostics.forEach((item) => lines.push(safeColors.muted(`- ${item}`)));
|
|
2030
|
+
}
|
|
2031
|
+
if (result.warnings && result.warnings.length > 0) {
|
|
2032
|
+
if (lines.length > 0) {
|
|
2033
|
+
lines.push("");
|
|
2034
|
+
}
|
|
2035
|
+
lines.push(safeColors.bold("Warnings"));
|
|
2036
|
+
result.warnings.forEach((item) => lines.push(safeColors.muted(`- ${item}`)));
|
|
2037
|
+
}
|
|
2038
|
+
if (result.errors && result.errors.length > 0) {
|
|
2039
|
+
if (lines.length > 0) {
|
|
2040
|
+
lines.push("");
|
|
2041
|
+
}
|
|
2042
|
+
lines.push(safeColors.bold("Errors"));
|
|
2043
|
+
result.errors.forEach((item) => lines.push(safeColors.muted(`- ${item}`)));
|
|
2044
|
+
}
|
|
2045
|
+
if (lines.length > 0) {
|
|
2046
|
+
lines.push("");
|
|
2047
|
+
}
|
|
2048
|
+
lines.push(formatStatusLine(statusEntry?.value, durationMs));
|
|
2049
|
+
ctx.presenter.write(box(title, lines));
|
|
2050
|
+
}
|
|
2051
|
+
function formatErrorOutput(ctx, errorMessage, durationMs, flags) {
|
|
2052
|
+
if (flags.jsonMode) {
|
|
2053
|
+
ctx.presenter.json({
|
|
2054
|
+
ok: false,
|
|
2055
|
+
error: errorMessage,
|
|
2056
|
+
timing: durationMs
|
|
2057
|
+
});
|
|
2058
|
+
return;
|
|
2059
|
+
}
|
|
2060
|
+
if (flags.quietMode) {
|
|
2061
|
+
return;
|
|
2062
|
+
}
|
|
2063
|
+
ctx.presenter.error(errorMessage);
|
|
2064
|
+
}
|
|
2065
|
+
function extractStatusEntry(summary) {
|
|
2066
|
+
for (const [key, value] of Object.entries(summary)) {
|
|
2067
|
+
if (typeof value === "string" && key.toLowerCase().includes("status")) {
|
|
2068
|
+
return { key, value };
|
|
2069
|
+
}
|
|
2070
|
+
}
|
|
2071
|
+
return null;
|
|
2072
|
+
}
|
|
2073
|
+
function formatStatusLine(statusValue, durationMs) {
|
|
2074
|
+
const rawStatus = statusValue ?? "Done";
|
|
2075
|
+
const normalized = rawStatus.toLowerCase();
|
|
2076
|
+
let symbol = safeSymbols.success;
|
|
2077
|
+
let colorize = safeColors.success;
|
|
2078
|
+
if (normalized.includes("error") || normalized.includes("fail")) {
|
|
2079
|
+
symbol = safeSymbols.error;
|
|
2080
|
+
colorize = safeColors.error;
|
|
2081
|
+
} else if (normalized.includes("partial") || normalized.includes("warn")) {
|
|
2082
|
+
symbol = safeSymbols.warning;
|
|
2083
|
+
colorize = safeColors.warning;
|
|
2084
|
+
}
|
|
2085
|
+
const statusText = hasAnsi(rawStatus) ? rawStatus : colorize(rawStatus);
|
|
2086
|
+
return `${symbol} ${statusText} \xB7 ${safeColors.muted(formatTiming(durationMs))}`;
|
|
2087
|
+
}
|
|
2088
|
+
|
|
2089
|
+
// src/utils/flags.ts
|
|
2090
|
+
function defineFlags(schema) {
|
|
2091
|
+
return {
|
|
2092
|
+
schema,
|
|
2093
|
+
type: {},
|
|
2094
|
+
parse: (input) => parseFlagsFromInput(input, schema)
|
|
2095
|
+
};
|
|
2096
|
+
}
|
|
2097
|
+
function parseFlagsFromInput(input, schema) {
|
|
2098
|
+
const result = {};
|
|
2099
|
+
const rawInput = input;
|
|
2100
|
+
for (const [key, spec] of Object.entries(schema)) {
|
|
2101
|
+
const value = rawInput?.[key];
|
|
2102
|
+
if (value === void 0) {
|
|
2103
|
+
if ("default" in spec) {
|
|
2104
|
+
result[key] = spec.default;
|
|
2105
|
+
}
|
|
2106
|
+
continue;
|
|
2107
|
+
}
|
|
2108
|
+
switch (spec.type) {
|
|
2109
|
+
case "boolean":
|
|
2110
|
+
result[key] = parseBoolean(value, key);
|
|
2111
|
+
break;
|
|
2112
|
+
case "string":
|
|
2113
|
+
result[key] = parseString(value, key);
|
|
2114
|
+
if (spec.validate && result[key] !== void 0) {
|
|
2115
|
+
spec.validate(result[key]);
|
|
2116
|
+
}
|
|
2117
|
+
break;
|
|
2118
|
+
case "number":
|
|
2119
|
+
result[key] = parseNumber(value, key);
|
|
2120
|
+
if (spec.validate && result[key] !== void 0) {
|
|
2121
|
+
spec.validate(result[key]);
|
|
2122
|
+
}
|
|
2123
|
+
break;
|
|
2124
|
+
}
|
|
2125
|
+
}
|
|
2126
|
+
return result;
|
|
2127
|
+
}
|
|
2128
|
+
function parseBoolean(value, flagName) {
|
|
2129
|
+
if (typeof value === "boolean") {
|
|
2130
|
+
return value;
|
|
2131
|
+
}
|
|
2132
|
+
if (typeof value === "string") {
|
|
2133
|
+
const lower = value.toLowerCase();
|
|
2134
|
+
if (lower === "true" || lower === "1" || lower === "yes") {
|
|
2135
|
+
return true;
|
|
2136
|
+
}
|
|
2137
|
+
if (lower === "false" || lower === "0" || lower === "no") {
|
|
2138
|
+
return false;
|
|
2139
|
+
}
|
|
2140
|
+
}
|
|
2141
|
+
throw new Error(
|
|
2142
|
+
`Flag "${flagName}" must be boolean, got ${typeof value}. Use true/false or 1/0 or yes/no.`
|
|
2143
|
+
);
|
|
2144
|
+
}
|
|
2145
|
+
function parseString(value, flagName) {
|
|
2146
|
+
if (typeof value === "string") {
|
|
2147
|
+
return value;
|
|
2148
|
+
}
|
|
2149
|
+
if (typeof value === "number") {
|
|
2150
|
+
return String(value);
|
|
2151
|
+
}
|
|
2152
|
+
throw new Error(
|
|
2153
|
+
`Flag "${flagName}" must be string, got ${typeof value}.`
|
|
2154
|
+
);
|
|
2155
|
+
}
|
|
2156
|
+
function parseNumber(value, flagName) {
|
|
2157
|
+
if (typeof value === "number") {
|
|
2158
|
+
if (!Number.isFinite(value)) {
|
|
2159
|
+
throw new Error(`Flag "${flagName}" must be finite number, got ${value}.`);
|
|
2160
|
+
}
|
|
2161
|
+
return value;
|
|
2162
|
+
}
|
|
2163
|
+
if (typeof value === "string") {
|
|
2164
|
+
const trimmed = value.trim();
|
|
2165
|
+
const parsed = Number(trimmed);
|
|
2166
|
+
if (!Number.isFinite(parsed)) {
|
|
2167
|
+
throw new Error(
|
|
2168
|
+
`Flag "${flagName}" must be number, got invalid string "${value}".`
|
|
2169
|
+
);
|
|
2170
|
+
}
|
|
2171
|
+
return parsed;
|
|
2172
|
+
}
|
|
2173
|
+
throw new Error(
|
|
2174
|
+
`Flag "${flagName}" must be number, got ${typeof value}.`
|
|
2175
|
+
);
|
|
2176
|
+
}
|
|
2177
|
+
function parseNumberFlag(value) {
|
|
2178
|
+
if (typeof value === "number") {
|
|
2179
|
+
return Number.isFinite(value) ? value : void 0;
|
|
2180
|
+
}
|
|
2181
|
+
if (typeof value === "string") {
|
|
2182
|
+
const trimmed = value.trim();
|
|
2183
|
+
if (trimmed.length === 0) {
|
|
2184
|
+
return void 0;
|
|
2185
|
+
}
|
|
2186
|
+
const parsed = Number(trimmed);
|
|
2187
|
+
return Number.isFinite(parsed) ? parsed : void 0;
|
|
2188
|
+
}
|
|
2189
|
+
return void 0;
|
|
2190
|
+
}
|
|
2191
|
+
function mergeFlags(input) {
|
|
2192
|
+
if (!input.flags || typeof input.flags !== "object") {
|
|
2193
|
+
return input;
|
|
2194
|
+
}
|
|
2195
|
+
return { ...input, ...input.flags };
|
|
2196
|
+
}
|
|
2197
|
+
|
|
2198
|
+
// src/utils/env.ts
|
|
2199
|
+
function defineEnv(schema) {
|
|
2200
|
+
return {
|
|
2201
|
+
schema,
|
|
2202
|
+
type: {},
|
|
2203
|
+
parse: (runtime) => parseEnvFromRuntime(runtime, schema)
|
|
2204
|
+
};
|
|
2205
|
+
}
|
|
2206
|
+
function parseEnvFromRuntime(runtime, schema) {
|
|
2207
|
+
const result = {};
|
|
2208
|
+
for (const [key, spec] of Object.entries(schema)) {
|
|
2209
|
+
const rawValue = runtime.env(key);
|
|
2210
|
+
if (rawValue === void 0) {
|
|
2211
|
+
if ("default" in spec) {
|
|
2212
|
+
result[key] = spec.default;
|
|
2213
|
+
}
|
|
2214
|
+
continue;
|
|
2215
|
+
}
|
|
2216
|
+
result[key] = parseEnvValue(rawValue, key, spec);
|
|
2217
|
+
}
|
|
2218
|
+
return result;
|
|
2219
|
+
}
|
|
2220
|
+
function parseEnvValue(value, key, spec) {
|
|
2221
|
+
if (value === void 0) {
|
|
2222
|
+
return void 0;
|
|
2223
|
+
}
|
|
2224
|
+
switch (spec.type) {
|
|
2225
|
+
case "boolean":
|
|
2226
|
+
return parseBoolean(value, key);
|
|
2227
|
+
case "string":
|
|
2228
|
+
const strValue = parseString(value, key);
|
|
2229
|
+
if (spec.validate) {
|
|
2230
|
+
spec.validate(strValue);
|
|
2231
|
+
}
|
|
2232
|
+
return strValue;
|
|
2233
|
+
case "number":
|
|
2234
|
+
const numValue = parseNumber(value, key);
|
|
2235
|
+
if (spec.validate) {
|
|
2236
|
+
spec.validate(numValue);
|
|
2237
|
+
}
|
|
2238
|
+
return numValue;
|
|
2239
|
+
default:
|
|
2240
|
+
return value;
|
|
2241
|
+
}
|
|
2242
|
+
}
|
|
2243
|
+
|
|
2244
|
+
// src/utils/context.ts
|
|
2245
|
+
function getContextCwd(input) {
|
|
2246
|
+
if (input && typeof input.cwd === "string" && input.cwd.length > 0) {
|
|
2247
|
+
return input.cwd;
|
|
2248
|
+
}
|
|
2249
|
+
return process.cwd();
|
|
2250
|
+
}
|
|
2251
|
+
|
|
2252
|
+
// src/utils/path.ts
|
|
2253
|
+
function toPosixPath(input) {
|
|
2254
|
+
return input.replace(/\\/g, "/");
|
|
2255
|
+
}
|
|
2256
|
+
|
|
2257
|
+
// src/modern-format.ts
|
|
2258
|
+
function sideBorderBox(options) {
|
|
2259
|
+
const { title, sections, footer, status, timing } = options;
|
|
2260
|
+
const lines = [];
|
|
2261
|
+
const titleLine = `${safeSymbols.topLeft}${safeSymbols.separator.repeat(2)} ${safeColors.primary(safeColors.bold(title))}`;
|
|
2262
|
+
lines.push(titleLine);
|
|
2263
|
+
lines.push(safeSymbols.border);
|
|
2264
|
+
for (let i = 0; i < sections.length; i++) {
|
|
2265
|
+
const section2 = sections[i];
|
|
2266
|
+
if (!section2) {
|
|
2267
|
+
continue;
|
|
2268
|
+
}
|
|
2269
|
+
if (section2.header) {
|
|
2270
|
+
lines.push(`${safeSymbols.border} ${safeColors.bold(section2.header)}`);
|
|
2271
|
+
}
|
|
2272
|
+
for (const item of section2.items) {
|
|
2273
|
+
lines.push(`${safeSymbols.border} ${item}`);
|
|
2274
|
+
}
|
|
2275
|
+
if (i < sections.length - 1) {
|
|
2276
|
+
lines.push(safeSymbols.border);
|
|
2277
|
+
}
|
|
2278
|
+
}
|
|
2279
|
+
if (footer || status || timing !== void 0) {
|
|
2280
|
+
lines.push(safeSymbols.border);
|
|
2281
|
+
const footerParts = [];
|
|
2282
|
+
if (footer) {
|
|
2283
|
+
footerParts.push(footer);
|
|
2284
|
+
} else if (status) {
|
|
2285
|
+
const statusSymbol = getStatusSymbol(status);
|
|
2286
|
+
const statusText = getStatusText(status);
|
|
2287
|
+
const statusColor = getStatusColor(status);
|
|
2288
|
+
footerParts.push(statusColor(`${statusSymbol} ${statusText}`));
|
|
2289
|
+
}
|
|
2290
|
+
if (timing !== void 0) {
|
|
2291
|
+
footerParts.push(formatTiming2(timing));
|
|
2292
|
+
}
|
|
2293
|
+
const footerLine = `${safeSymbols.bottomLeft}${safeSymbols.separator.repeat(2)} ${footerParts.join(" / ")}`;
|
|
2294
|
+
lines.push(footerLine);
|
|
2295
|
+
}
|
|
2296
|
+
return lines.join("\n");
|
|
2297
|
+
}
|
|
2298
|
+
function sectionHeader(text) {
|
|
2299
|
+
return safeColors.bold(text);
|
|
2300
|
+
}
|
|
2301
|
+
function metricsList(metrics) {
|
|
2302
|
+
const entries = Object.entries(metrics);
|
|
2303
|
+
if (entries.length === 0) {
|
|
2304
|
+
return [];
|
|
2305
|
+
}
|
|
2306
|
+
const maxKeyLength = Math.max(
|
|
2307
|
+
...entries.map(([key]) => stripAnsi(key).length)
|
|
2308
|
+
);
|
|
2309
|
+
return entries.map(([key, value]) => {
|
|
2310
|
+
const keyLength = stripAnsi(key).length;
|
|
2311
|
+
const padding = " ".repeat(maxKeyLength - keyLength + 2);
|
|
2312
|
+
const formattedKey = safeColors.bold(key);
|
|
2313
|
+
const formattedValue = safeColors.muted(String(value));
|
|
2314
|
+
return `${formattedKey}:${padding}${formattedValue}`;
|
|
2315
|
+
});
|
|
2316
|
+
}
|
|
2317
|
+
var bulletList2 = bulletList;
|
|
2318
|
+
var formatTiming2 = formatTiming;
|
|
2319
|
+
function statusLine(status, timing) {
|
|
2320
|
+
const symbol = getStatusSymbol(status);
|
|
2321
|
+
const text = getStatusText(status);
|
|
2322
|
+
const color = getStatusColor(status);
|
|
2323
|
+
const parts = [color(`${symbol} ${text}`)];
|
|
2324
|
+
if (timing !== void 0) {
|
|
2325
|
+
parts.push(formatTiming2(timing));
|
|
2326
|
+
}
|
|
2327
|
+
return parts.join(" / ");
|
|
2328
|
+
}
|
|
2329
|
+
function getStatusSymbol(status) {
|
|
2330
|
+
switch (status) {
|
|
2331
|
+
case "success":
|
|
2332
|
+
return safeSymbols.success;
|
|
2333
|
+
case "error":
|
|
2334
|
+
return safeSymbols.error;
|
|
2335
|
+
case "warning":
|
|
2336
|
+
return safeSymbols.warning;
|
|
2337
|
+
case "info":
|
|
2338
|
+
return safeSymbols.info;
|
|
2339
|
+
}
|
|
2340
|
+
}
|
|
2341
|
+
function getStatusText(status) {
|
|
2342
|
+
switch (status) {
|
|
2343
|
+
case "success":
|
|
2344
|
+
return "Success";
|
|
2345
|
+
case "error":
|
|
2346
|
+
return "Failed";
|
|
2347
|
+
case "warning":
|
|
2348
|
+
return "Warning";
|
|
2349
|
+
case "info":
|
|
2350
|
+
return "Info";
|
|
2351
|
+
}
|
|
2352
|
+
}
|
|
2353
|
+
function getStatusColor(status) {
|
|
2354
|
+
switch (status) {
|
|
2355
|
+
case "success":
|
|
2356
|
+
return safeColors.success;
|
|
2357
|
+
case "error":
|
|
2358
|
+
return safeColors.error;
|
|
2359
|
+
case "warning":
|
|
2360
|
+
return safeColors.warning;
|
|
2361
|
+
case "info":
|
|
2362
|
+
return safeColors.info;
|
|
2363
|
+
}
|
|
2364
|
+
}
|
|
2365
|
+
function formatCommandHelp(options) {
|
|
2366
|
+
const { title, description, longDescription, examples, flags, aliases } = options;
|
|
2367
|
+
const sections = [];
|
|
2368
|
+
if (description) {
|
|
2369
|
+
sections.push({
|
|
2370
|
+
header: "Description",
|
|
2371
|
+
items: [description]
|
|
2372
|
+
});
|
|
2373
|
+
}
|
|
2374
|
+
if (longDescription) {
|
|
2375
|
+
sections.push({
|
|
2376
|
+
header: "Details",
|
|
2377
|
+
items: [longDescription]
|
|
2378
|
+
});
|
|
2379
|
+
}
|
|
2380
|
+
if (aliases && aliases.length > 0) {
|
|
2381
|
+
sections.push({
|
|
2382
|
+
header: "Aliases",
|
|
2383
|
+
items: aliases.map((a) => safeColors.muted(a))
|
|
2384
|
+
});
|
|
2385
|
+
}
|
|
2386
|
+
if (flags && flags.length > 0) {
|
|
2387
|
+
const flagItems = flags.map((flag) => {
|
|
2388
|
+
const label = flag.alias ? `--${flag.name}, -${flag.alias}` : `--${flag.name}`;
|
|
2389
|
+
const required = flag.required ? safeColors.warning(" (required)") : "";
|
|
2390
|
+
const desc = flag.description ? safeColors.muted(` \u2014 ${flag.description}`) : "";
|
|
2391
|
+
return `${safeColors.bold(label)}${required}${desc}`;
|
|
2392
|
+
});
|
|
2393
|
+
sections.push({
|
|
2394
|
+
header: "Flags",
|
|
2395
|
+
items: flagItems
|
|
2396
|
+
});
|
|
2397
|
+
}
|
|
2398
|
+
if (examples && examples.length > 0) {
|
|
2399
|
+
sections.push({
|
|
2400
|
+
header: "Examples",
|
|
2401
|
+
items: examples.map((ex) => safeColors.muted(` ${ex}`))
|
|
2402
|
+
});
|
|
2403
|
+
}
|
|
2404
|
+
return sideBorderBox({
|
|
2405
|
+
title,
|
|
2406
|
+
sections,
|
|
2407
|
+
status: "info"
|
|
2408
|
+
});
|
|
2409
|
+
}
|
|
2410
|
+
|
|
2411
|
+
// src/command-result.ts
|
|
2412
|
+
function formatCommandResult(params) {
|
|
2413
|
+
const {
|
|
2414
|
+
title,
|
|
2415
|
+
summary,
|
|
2416
|
+
details = [],
|
|
2417
|
+
warnings = [],
|
|
2418
|
+
errors = [],
|
|
2419
|
+
timing,
|
|
2420
|
+
status,
|
|
2421
|
+
jsonData
|
|
2422
|
+
} = params;
|
|
2423
|
+
const sections = [];
|
|
2424
|
+
if (summary && Object.keys(summary).length > 0) {
|
|
2425
|
+
sections.push({
|
|
2426
|
+
header: "Summary",
|
|
2427
|
+
items: metricsList(summary)
|
|
2428
|
+
});
|
|
2429
|
+
}
|
|
2430
|
+
for (const detail of details) {
|
|
2431
|
+
sections.push({
|
|
2432
|
+
header: detail.section,
|
|
2433
|
+
items: detail.items
|
|
2434
|
+
});
|
|
2435
|
+
}
|
|
2436
|
+
if (warnings.length > 0) {
|
|
2437
|
+
sections.push({
|
|
2438
|
+
header: "\u26A0 Warnings",
|
|
2439
|
+
items: bulletList2(warnings)
|
|
2440
|
+
});
|
|
2441
|
+
}
|
|
2442
|
+
if (errors.length > 0) {
|
|
2443
|
+
sections.push({
|
|
2444
|
+
header: "\u2717 Errors",
|
|
2445
|
+
items: bulletList2(errors)
|
|
2446
|
+
});
|
|
2447
|
+
}
|
|
2448
|
+
const human = sideBorderBox({
|
|
2449
|
+
title,
|
|
2450
|
+
sections,
|
|
2451
|
+
status,
|
|
2452
|
+
timing
|
|
2453
|
+
});
|
|
2454
|
+
const json = {
|
|
2455
|
+
ok: status === "success",
|
|
2456
|
+
status,
|
|
2457
|
+
...summary && { summary },
|
|
2458
|
+
...details.length > 0 && {
|
|
2459
|
+
details: details.reduce((acc, d) => {
|
|
2460
|
+
acc[d.section] = d.items;
|
|
2461
|
+
return acc;
|
|
2462
|
+
}, {})
|
|
2463
|
+
},
|
|
2464
|
+
...warnings.length > 0 && { warnings },
|
|
2465
|
+
...errors.length > 0 && { errors },
|
|
2466
|
+
...timing !== void 0 && { timingMs: timing },
|
|
2467
|
+
...jsonData && { data: jsonData }
|
|
2468
|
+
};
|
|
2469
|
+
return {
|
|
2470
|
+
ok: status === "success",
|
|
2471
|
+
status,
|
|
2472
|
+
human,
|
|
2473
|
+
json
|
|
2474
|
+
};
|
|
2475
|
+
}
|
|
2476
|
+
function successResult(title, data) {
|
|
2477
|
+
return formatCommandResult({
|
|
2478
|
+
title,
|
|
2479
|
+
summary: data?.summary,
|
|
2480
|
+
details: data?.details,
|
|
2481
|
+
timing: data?.timing,
|
|
2482
|
+
status: "success",
|
|
2483
|
+
jsonData: data?.json
|
|
2484
|
+
});
|
|
2485
|
+
}
|
|
2486
|
+
function errorResult(title, error, options) {
|
|
2487
|
+
const errorMessage = error instanceof Error ? error.message : error;
|
|
2488
|
+
const errorStack = error instanceof Error ? error.stack : void 0;
|
|
2489
|
+
return formatCommandResult({
|
|
2490
|
+
title,
|
|
2491
|
+
errors: [errorMessage],
|
|
2492
|
+
details: options?.suggestions ? [{ section: "Suggestions", items: bulletList2(options.suggestions) }] : [],
|
|
2493
|
+
timing: options?.timing,
|
|
2494
|
+
status: "error",
|
|
2495
|
+
jsonData: {
|
|
2496
|
+
error: errorMessage,
|
|
2497
|
+
...errorStack && { stack: errorStack }
|
|
2498
|
+
}
|
|
2499
|
+
});
|
|
2500
|
+
}
|
|
2501
|
+
function warningResult(title, warnings, options) {
|
|
2502
|
+
return formatCommandResult({
|
|
2503
|
+
title,
|
|
2504
|
+
warnings,
|
|
2505
|
+
summary: options?.summary,
|
|
2506
|
+
timing: options?.timing,
|
|
2507
|
+
status: "warning"
|
|
2508
|
+
});
|
|
2509
|
+
}
|
|
2510
|
+
function infoResult(title, data) {
|
|
2511
|
+
return formatCommandResult({
|
|
2512
|
+
title,
|
|
2513
|
+
summary: data?.summary,
|
|
2514
|
+
details: data?.details,
|
|
2515
|
+
timing: data?.timing,
|
|
2516
|
+
status: "info"
|
|
2517
|
+
});
|
|
2518
|
+
}
|
|
2519
|
+
|
|
2520
|
+
exports.DebugOutput = DebugOutput;
|
|
2521
|
+
exports.DebugSection = DebugSection;
|
|
2522
|
+
exports.DebugTrace = DebugTrace;
|
|
2523
|
+
exports.DebugTree = DebugTree;
|
|
2524
|
+
exports.DynamicCommandDiscovery = DynamicCommandDiscovery;
|
|
2525
|
+
exports.Loader = Loader;
|
|
2526
|
+
exports.MultiCLISuggestions = MultiCLISuggestions;
|
|
2527
|
+
exports.StaticCommandDiscovery = StaticCommandDiscovery;
|
|
2528
|
+
exports.TimingTracker = TimingTracker;
|
|
2529
|
+
exports.accentLabel = accentLabel;
|
|
2530
|
+
exports.box = box;
|
|
2531
|
+
exports.bulletList = bulletList;
|
|
2532
|
+
exports.colors = colors;
|
|
2533
|
+
exports.createCommandDiscovery = createCommandDiscovery;
|
|
2534
|
+
exports.createCommandRegistry = createCommandRegistry;
|
|
2535
|
+
exports.createCommandRunner = createCommandRunner;
|
|
2536
|
+
exports.createDebugTree = createDebugTree;
|
|
2537
|
+
exports.createDetailedResult = createDetailedResult;
|
|
2538
|
+
exports.createKBLabsCommandDiscovery = createKBLabsCommandDiscovery;
|
|
2539
|
+
exports.createProgressBar = createProgressBar;
|
|
2540
|
+
exports.createSimpleResult = createSimpleResult;
|
|
2541
|
+
exports.createSpinner = createSpinner;
|
|
2542
|
+
exports.defineEnv = defineEnv;
|
|
2543
|
+
exports.defineFlags = defineFlags;
|
|
2544
|
+
exports.describeEntriesAI = describeEntriesAI;
|
|
2545
|
+
exports.describeEntriesHuman = describeEntriesHuman;
|
|
2546
|
+
exports.describeEntriesTimeline = describeEntriesTimeline;
|
|
2547
|
+
exports.discoverArtifacts = discoverArtifacts;
|
|
2548
|
+
exports.displayArtifacts = displayArtifacts;
|
|
2549
|
+
exports.displayArtifactsCompact = displayArtifactsCompact;
|
|
2550
|
+
exports.displaySingleArtifact = displaySingleArtifact;
|
|
2551
|
+
exports.errorResult = errorResult;
|
|
2552
|
+
exports.exportDebugEntries = exportDebugEntries;
|
|
2553
|
+
exports.exportToChromeFormat = exportToChromeFormat;
|
|
2554
|
+
exports.exportToJSON = exportToJSON;
|
|
2555
|
+
exports.exportToPlainText = exportToPlainText;
|
|
2556
|
+
exports.extractCommandGroups = extractCommandGroups;
|
|
2557
|
+
exports.extractCommandIds = extractCommandIds;
|
|
2558
|
+
exports.filterByLevel = filterByLevel;
|
|
2559
|
+
exports.filterByNamespace = filterByNamespace;
|
|
2560
|
+
exports.filterByTimeRange = filterByTimeRange;
|
|
2561
|
+
exports.filterDebugEntries = filterDebugEntries;
|
|
2562
|
+
exports.findCommandById = findCommandById;
|
|
2563
|
+
exports.findCommandsByGroup = findCommandsByGroup;
|
|
2564
|
+
exports.formatCommandHelp = formatCommandHelp;
|
|
2565
|
+
exports.formatCommandOutput = formatCommandOutput;
|
|
2566
|
+
exports.formatCommandResult = formatCommandResult;
|
|
2567
|
+
exports.formatDebugEntriesAI = formatDebugEntriesAI;
|
|
2568
|
+
exports.formatDebugEntriesHuman = formatDebugEntriesHuman;
|
|
2569
|
+
exports.formatDebugEntryAI = formatDebugEntryAI;
|
|
2570
|
+
exports.formatDebugEntryHuman = formatDebugEntryHuman;
|
|
2571
|
+
exports.formatDebugOutput = formatDebugOutput;
|
|
2572
|
+
exports.formatDebugOutputs = formatDebugOutputs;
|
|
2573
|
+
exports.formatKeyValueTable = formatKeyValueTable;
|
|
2574
|
+
exports.formatRelativeTime = formatRelativeTime;
|
|
2575
|
+
exports.formatSize = formatSize;
|
|
2576
|
+
exports.formatTable = formatTable;
|
|
2577
|
+
exports.formatTimeline = formatTimeline;
|
|
2578
|
+
exports.formatTimelineNode = formatTimelineNode;
|
|
2579
|
+
exports.formatTimelineWithSummary = formatTimelineWithSummary;
|
|
2580
|
+
exports.formatTimestamp = formatTimestamp;
|
|
2581
|
+
exports.formatTiming = formatTiming;
|
|
2582
|
+
exports.formatTimingBreakdown = formatTimingBreakdown;
|
|
2583
|
+
exports.generateDevlinkSuggestions = generateDevlinkSuggestions;
|
|
2584
|
+
exports.generateGroupSuggestions = generateGroupSuggestions;
|
|
2585
|
+
exports.generateQuickActions = generateQuickActions;
|
|
2586
|
+
exports.getCommandInfo = getCommandInfo;
|
|
2587
|
+
exports.getContextCwd = getContextCwd;
|
|
2588
|
+
exports.groupByGroup = groupByGroup;
|
|
2589
|
+
exports.groupByNamespace = groupByNamespace;
|
|
2590
|
+
exports.hasAnsi = hasAnsi;
|
|
2591
|
+
exports.headline = headline;
|
|
2592
|
+
exports.indent = indent;
|
|
2593
|
+
exports.infoResult = infoResult;
|
|
2594
|
+
exports.isCommandAvailable = isCommandAvailable;
|
|
2595
|
+
exports.keyValue = keyValue;
|
|
2596
|
+
exports.mergeFlags = mergeFlags;
|
|
2597
|
+
exports.metricsList = metricsList;
|
|
2598
|
+
exports.muted = muted;
|
|
2599
|
+
exports.pad = pad;
|
|
2600
|
+
exports.parseBoolean = parseBoolean;
|
|
2601
|
+
exports.parseEnvFromRuntime = parseEnvFromRuntime;
|
|
2602
|
+
exports.parseFlagsFromInput = parseFlagsFromInput;
|
|
2603
|
+
exports.parseNumber = parseNumber;
|
|
2604
|
+
exports.parseNumberFlag = parseNumberFlag;
|
|
2605
|
+
exports.parseString = parseString;
|
|
2606
|
+
exports.safeColors = safeColors;
|
|
2607
|
+
exports.safeKeyValue = safeKeyValue;
|
|
2608
|
+
exports.safeSymbols = safeSymbols;
|
|
2609
|
+
exports.searchInLogs = searchInLogs;
|
|
2610
|
+
exports.section = section;
|
|
2611
|
+
exports.sectionHeader = sectionHeader;
|
|
2612
|
+
exports.shouldUseAIFormat = shouldUseAIFormat;
|
|
2613
|
+
exports.showError = showError;
|
|
2614
|
+
exports.showLoading = showLoading;
|
|
2615
|
+
exports.showSuccess = showSuccess;
|
|
2616
|
+
exports.sideBorderBox = sideBorderBox;
|
|
2617
|
+
exports.statusLine = statusLine;
|
|
2618
|
+
exports.stripAnsi = stripAnsi;
|
|
2619
|
+
exports.successResult = successResult;
|
|
2620
|
+
exports.supportsColor = supportsColor;
|
|
2621
|
+
exports.symbols = symbols;
|
|
2622
|
+
exports.table = table;
|
|
2623
|
+
exports.toPosixPath = toPosixPath;
|
|
2624
|
+
exports.truncate = truncate;
|
|
2625
|
+
exports.useLoader = useLoader;
|
|
2626
|
+
exports.validateSuggestions = validateSuggestions;
|
|
2627
|
+
exports.warningResult = warningResult;
|
|
2628
|
+
//# sourceMappingURL=index.cjs.map
|
|
2629
|
+
//# sourceMappingURL=index.cjs.map
|