reygent-code 1.0.1 → 1.1.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 +16 -5
- package/dist/cli.js +685 -584
- package/dist/cli.js.map +1 -1
- package/package.json +8 -2
package/dist/cli.js
CHANGED
|
@@ -5,7 +5,7 @@ import { Command } from "commander";
|
|
|
5
5
|
import { readFileSync as readFileSync12 } from "fs";
|
|
6
6
|
import { dirname as dirname7, join as join14 } from "path";
|
|
7
7
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
8
|
-
import
|
|
8
|
+
import chalk30 from "chalk";
|
|
9
9
|
|
|
10
10
|
// src/child-registry.ts
|
|
11
11
|
var activeChildProcesses = /* @__PURE__ */ new Set();
|
|
@@ -52,6 +52,9 @@ function isDebug() {
|
|
|
52
52
|
return debugEnabled || process.env.REYGENT_DEBUG === "1";
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
+
// src/model.ts
|
|
56
|
+
import chalk6 from "chalk";
|
|
57
|
+
|
|
55
58
|
// src/config.ts
|
|
56
59
|
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
|
|
57
60
|
import { join as join2 } from "path";
|
|
@@ -524,6 +527,7 @@ var SHORT_ALIASES = {
|
|
|
524
527
|
"claude-3-opus": "claude-3-opus-20240229"
|
|
525
528
|
};
|
|
526
529
|
var DEFAULT_MODEL = "claude-sonnet-4-5-20250929";
|
|
530
|
+
var vertexAiLoggedForClaude = false;
|
|
527
531
|
function extractTokenUsage(msg) {
|
|
528
532
|
const usageData = msg.usage;
|
|
529
533
|
const hasInput = usageData?.input_tokens !== void 0 || usageData?.cache_creation_input_tokens !== void 0 || usageData?.cache_read_input_tokens !== void 0 || msg.input_tokens !== void 0;
|
|
@@ -576,6 +580,18 @@ var claudeAdapter = {
|
|
|
576
580
|
if (options.autoApprove) {
|
|
577
581
|
args.push("--allowedTools", "Bash", "Edit", "Write", "Read", "Glob", "Grep");
|
|
578
582
|
}
|
|
583
|
+
const name = options.agentName;
|
|
584
|
+
const vertexProject = process.env.GOOGLE_CLOUD_PROJECT || process.env.GCLOUD_PROJECT;
|
|
585
|
+
const vertexRegion = process.env.GOOGLE_CLOUD_REGION;
|
|
586
|
+
const hasVertexConfig = !!vertexProject;
|
|
587
|
+
if (hasVertexConfig && !options.quiet && !vertexAiLoggedForClaude) {
|
|
588
|
+
const region = vertexRegion ?? "(using CLI default)";
|
|
589
|
+
process.stderr.write(
|
|
590
|
+
chalk2.gray(`[${name}] Vertex AI detected: project=${vertexProject}, region=${region}
|
|
591
|
+
`)
|
|
592
|
+
);
|
|
593
|
+
vertexAiLoggedForClaude = true;
|
|
594
|
+
}
|
|
579
595
|
const stdinMode = options.autoApprove === false ? "inherit" : "ignore";
|
|
580
596
|
const child = spawn("claude", args, {
|
|
581
597
|
stdio: [stdinMode, "pipe", "pipe"],
|
|
@@ -588,7 +604,6 @@ var claudeAdapter = {
|
|
|
588
604
|
let resultApiErrorStatus;
|
|
589
605
|
let resultUsage;
|
|
590
606
|
const textChunks = [];
|
|
591
|
-
const name = options.agentName;
|
|
592
607
|
const timeout = setTimeout(() => {
|
|
593
608
|
if (child.pid && process.platform !== "win32") {
|
|
594
609
|
try {
|
|
@@ -742,6 +757,7 @@ var SUPPORTED_MODELS2 = [
|
|
|
742
757
|
];
|
|
743
758
|
var SHORT_ALIASES2 = {};
|
|
744
759
|
var DEFAULT_MODEL2 = "gemini-2.5-pro";
|
|
760
|
+
var vertexAiLoggedForGemini = false;
|
|
745
761
|
var availabilityCache2 = null;
|
|
746
762
|
var geminiAdapter = {
|
|
747
763
|
name: "gemini",
|
|
@@ -776,6 +792,17 @@ var geminiAdapter = {
|
|
|
776
792
|
}
|
|
777
793
|
const name = options.agentName;
|
|
778
794
|
const stdinMode = options.autoApprove === false ? "inherit" : "ignore";
|
|
795
|
+
const vertexProject = process.env.GOOGLE_CLOUD_PROJECT || process.env.GCLOUD_PROJECT;
|
|
796
|
+
const vertexRegion = process.env.GOOGLE_CLOUD_REGION;
|
|
797
|
+
const hasVertexConfig = !!vertexProject;
|
|
798
|
+
if (hasVertexConfig && !options.quiet && !vertexAiLoggedForGemini) {
|
|
799
|
+
const region = vertexRegion ?? "(using CLI default)";
|
|
800
|
+
process.stderr.write(
|
|
801
|
+
chalk3.gray(`[${name}] Vertex AI detected: project=${vertexProject}, region=${region}
|
|
802
|
+
`)
|
|
803
|
+
);
|
|
804
|
+
vertexAiLoggedForGemini = true;
|
|
805
|
+
}
|
|
779
806
|
const child = spawn2("gemini", args, {
|
|
780
807
|
stdio: [stdinMode, "pipe", "pipe"],
|
|
781
808
|
env: { ...process.env, GEMINI_CLI_TRUST_WORKSPACE: "true" },
|
|
@@ -1194,6 +1221,7 @@ var SUPPORTED_MODELS5 = getProvider("claude").supportedModels;
|
|
|
1194
1221
|
var DEFAULT_MODEL5 = getProvider("claude").defaultModel;
|
|
1195
1222
|
var modelOverride = null;
|
|
1196
1223
|
var providerOverride = null;
|
|
1224
|
+
var warnedCustomModels = /* @__PURE__ */ new Set();
|
|
1197
1225
|
function setModelOverride(id) {
|
|
1198
1226
|
modelOverride = id;
|
|
1199
1227
|
}
|
|
@@ -1207,17 +1235,20 @@ function validateModel(id, providerName) {
|
|
|
1207
1235
|
if (name === "openrouter") return resolved;
|
|
1208
1236
|
const valid = provider.supportedModels.some((m) => m.id === resolved);
|
|
1209
1237
|
if (!valid) {
|
|
1210
|
-
const
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1238
|
+
const warningKey = `${name}:${resolved}`;
|
|
1239
|
+
if (!warnedCustomModels.has(warningKey)) {
|
|
1240
|
+
const list = provider.supportedModels.map((m) => ` ${m.id} \u2014 ${m.label}`).join("\n");
|
|
1241
|
+
const aliases = Object.entries(provider.shortAliases).map(([alias, full]) => ` ${alias} \u2192 ${full}`).join("\n");
|
|
1242
|
+
console.log(chalk6.yellow("Warning:"), `"${id}" not in ${name} supported models list. Using custom model.`);
|
|
1243
|
+
console.log(chalk6.gray("Supported models for"), chalk6.cyan(name) + chalk6.gray(":"));
|
|
1244
|
+
console.log(list);
|
|
1245
|
+
if (aliases) {
|
|
1246
|
+
console.log(chalk6.gray("\nShort aliases:"));
|
|
1247
|
+
console.log(aliases);
|
|
1248
|
+
}
|
|
1249
|
+
console.log("");
|
|
1250
|
+
warnedCustomModels.add(warningKey);
|
|
1251
|
+
}
|
|
1221
1252
|
}
|
|
1222
1253
|
return resolved;
|
|
1223
1254
|
}
|
|
@@ -1265,12 +1296,12 @@ function resolveTelemetryEnabled(override, config) {
|
|
|
1265
1296
|
|
|
1266
1297
|
// src/commands/agent.ts
|
|
1267
1298
|
import { select } from "@inquirer/prompts";
|
|
1268
|
-
import
|
|
1299
|
+
import chalk9 from "chalk";
|
|
1269
1300
|
|
|
1270
1301
|
// src/spec.ts
|
|
1271
1302
|
import { existsSync as existsSync4, readFileSync as readFileSync4 } from "fs";
|
|
1272
1303
|
import { basename as basename2, extname, resolve as resolve3 } from "path";
|
|
1273
|
-
import
|
|
1304
|
+
import chalk8 from "chalk";
|
|
1274
1305
|
|
|
1275
1306
|
// src/linear.ts
|
|
1276
1307
|
var LINEAR_URL_PATTERN = /^https:\/\/linear\.app\/[^/]+\/issue\/([A-Z]+-\d+)/;
|
|
@@ -1488,7 +1519,7 @@ function loadEnvFile() {
|
|
|
1488
1519
|
|
|
1489
1520
|
// src/chesstrace/index.ts
|
|
1490
1521
|
import { randomUUID } from "crypto";
|
|
1491
|
-
import
|
|
1522
|
+
import chalk7 from "chalk";
|
|
1492
1523
|
|
|
1493
1524
|
// src/chesstrace/events.ts
|
|
1494
1525
|
var TelemetryLevel = /* @__PURE__ */ ((TelemetryLevel2) => {
|
|
@@ -1679,7 +1710,7 @@ var Chesstrace = class {
|
|
|
1679
1710
|
try {
|
|
1680
1711
|
const deleted = await backend.prune(olderThan);
|
|
1681
1712
|
if (deleted > 0) {
|
|
1682
|
-
console.log(
|
|
1713
|
+
console.log(chalk7.gray(`Pruned ${deleted} event(s) older than ${retentionDays} days`));
|
|
1683
1714
|
}
|
|
1684
1715
|
} catch (err) {
|
|
1685
1716
|
this.config.onError?.(err, "auto-prune");
|
|
@@ -1859,7 +1890,7 @@ function readSpec(filePath) {
|
|
|
1859
1890
|
}
|
|
1860
1891
|
const ext = extname(resolved).toLowerCase();
|
|
1861
1892
|
if (ext !== ".md" && ext !== ".markdown") {
|
|
1862
|
-
console.log(
|
|
1893
|
+
console.log(chalk8.yellow("Warning:"), `${basename2(resolved)} is not a .md file`);
|
|
1863
1894
|
}
|
|
1864
1895
|
const content = readFileSync4(resolved, "utf-8");
|
|
1865
1896
|
if (!content.trim()) {
|
|
@@ -2418,7 +2449,7 @@ async function agentCommand(name, options) {
|
|
|
2418
2449
|
const found = agents.find((a) => a.name === name);
|
|
2419
2450
|
if (!found) {
|
|
2420
2451
|
const validNames = agents.map((a) => a.name).join(", ");
|
|
2421
|
-
console.log(
|
|
2452
|
+
console.log(chalk9.red.bold("Error:"), `Unknown agent "${name}". Valid agents: ${validNames}`);
|
|
2422
2453
|
process.exit(1);
|
|
2423
2454
|
}
|
|
2424
2455
|
agent = found;
|
|
@@ -2429,9 +2460,9 @@ async function agentCommand(name, options) {
|
|
|
2429
2460
|
if (!process.stdin.isTTY) {
|
|
2430
2461
|
const validNames = agents.map((a) => a.name);
|
|
2431
2462
|
const displayNames = validNames.length > 5 ? `${validNames.slice(0, 5).join(", ")}, ... (${validNames.length - 5} more)` : validNames.join(", ");
|
|
2432
|
-
console.log(
|
|
2463
|
+
console.log(chalk9.red.bold("Error:"), `Agent name required in non-interactive mode. Valid agents: ${displayNames}`);
|
|
2433
2464
|
if (validNames.length > 5) {
|
|
2434
|
-
console.log(
|
|
2465
|
+
console.log(chalk9.gray(" Run 'reygent list' to see all agents."));
|
|
2435
2466
|
}
|
|
2436
2467
|
process.exit(1);
|
|
2437
2468
|
}
|
|
@@ -2461,19 +2492,19 @@ ${spec.content}`;
|
|
|
2461
2492
|
const provider = getProvider(providerName);
|
|
2462
2493
|
const modelId = agent.model ? validateModel(agent.model, providerName) : await resolveModel(providerName);
|
|
2463
2494
|
console.log(
|
|
2464
|
-
|
|
2465
|
-
Starting session with ${agent.name} agent`) +
|
|
2495
|
+
chalk9.bold.cyan(`
|
|
2496
|
+
Starting session with ${agent.name} agent`) + chalk9.gray(` (${providerName}/${modelId})`) + "\n"
|
|
2466
2497
|
);
|
|
2467
2498
|
const exitCode = await provider.spawnInteractive(systemPrompt, modelId);
|
|
2468
2499
|
process.exit(exitCode);
|
|
2469
2500
|
} catch (err) {
|
|
2470
2501
|
if (err instanceof SpecError || err instanceof TaskError) {
|
|
2471
|
-
console.log(
|
|
2502
|
+
console.log(chalk9.red.bold("Error:"), err.message);
|
|
2472
2503
|
if (isDebug()) console.error(err.stack);
|
|
2473
2504
|
process.exit(1);
|
|
2474
2505
|
}
|
|
2475
2506
|
const message = err instanceof Error ? err.message : String(err);
|
|
2476
|
-
console.log(
|
|
2507
|
+
console.log(chalk9.red.bold("Internal error:"), message);
|
|
2477
2508
|
if (isDebug()) console.error(err instanceof Error ? err.stack : err);
|
|
2478
2509
|
process.exit(2);
|
|
2479
2510
|
}
|
|
@@ -2484,12 +2515,12 @@ Starting session with ${agent.name} agent`) + chalk8.gray(` (${providerName}/${m
|
|
|
2484
2515
|
import { createInterface as createInterface2 } from "readline";
|
|
2485
2516
|
import { writeFileSync } from "fs";
|
|
2486
2517
|
import { resolve as resolve4 } from "path";
|
|
2487
|
-
import
|
|
2518
|
+
import chalk12 from "chalk";
|
|
2488
2519
|
|
|
2489
2520
|
// src/knowledge/loader.ts
|
|
2490
2521
|
import { existsSync as existsSync7, readFileSync as readFileSync5, readdirSync as readdirSync2, statSync as statSync3 } from "fs";
|
|
2491
2522
|
import { join as join5 } from "path";
|
|
2492
|
-
import
|
|
2523
|
+
import chalk10 from "chalk";
|
|
2493
2524
|
import { marked } from "marked";
|
|
2494
2525
|
|
|
2495
2526
|
// src/test-env.ts
|
|
@@ -2517,7 +2548,7 @@ function readMarkdown(filePath) {
|
|
|
2517
2548
|
const content = readFileSync5(filePath, "utf-8");
|
|
2518
2549
|
if (!content || content.trim().length === 0) return "";
|
|
2519
2550
|
if (!validateMarkdown(content)) {
|
|
2520
|
-
console.warn(
|
|
2551
|
+
console.warn(chalk10.yellow(`\u26A0 Suspicious content detected in ${filePath}, skipping`));
|
|
2521
2552
|
return null;
|
|
2522
2553
|
}
|
|
2523
2554
|
return sanitizeMarkdown(content);
|
|
@@ -2598,7 +2629,7 @@ async function loadKnowledge(agentName, stage) {
|
|
|
2598
2629
|
const knowledgeDir = findKnowledgeDir();
|
|
2599
2630
|
if (!knowledgeDir) {
|
|
2600
2631
|
if (!isTestEnvironment() && process.env.REYGENT_DEBUG !== "knowledge") {
|
|
2601
|
-
console.warn(
|
|
2632
|
+
console.warn(chalk10.yellow("\u26A0 No knowledge directory found. Run 'reygent init' to create .reygent/knowledge/"));
|
|
2602
2633
|
}
|
|
2603
2634
|
return {
|
|
2604
2635
|
agentTips: "",
|
|
@@ -3189,7 +3220,7 @@ async function generateSpec(description, clarificationAnswers, onActivity) {
|
|
|
3189
3220
|
}
|
|
3190
3221
|
|
|
3191
3222
|
// src/live-status.ts
|
|
3192
|
-
import
|
|
3223
|
+
import chalk11 from "chalk";
|
|
3193
3224
|
import ora from "ora";
|
|
3194
3225
|
var TRACK_LENGTH = 4;
|
|
3195
3226
|
var PAW_POSITIONS = [0, 1, 2, 3, 2, 1];
|
|
@@ -3221,16 +3252,16 @@ function truncateToWidth(text, maxWidth) {
|
|
|
3221
3252
|
function buildAnimationFrame(position, label, elapsed, lastActivity) {
|
|
3222
3253
|
const track = Array.from(
|
|
3223
3254
|
{ length: TRACK_LENGTH },
|
|
3224
|
-
(_, i) => i === position ?
|
|
3255
|
+
(_, i) => i === position ? chalk11.yellowBright("\u{1F43E}") : chalk11.gray("\xB7")
|
|
3225
3256
|
).join(" ");
|
|
3226
|
-
const mainLine = `${track} ${
|
|
3257
|
+
const mainLine = `${track} ${chalk11.blue(label)} ${chalk11.gray(elapsed)}`;
|
|
3227
3258
|
if (lastActivity) {
|
|
3228
3259
|
const parts = [lastActivity.agent];
|
|
3229
3260
|
if (lastActivity.tool) parts.push(lastActivity.tool);
|
|
3230
3261
|
if (lastActivity.detail) parts.push(lastActivity.detail.replace(/[\r\n]+/g, " "));
|
|
3231
|
-
const activityText =
|
|
3262
|
+
const activityText = chalk11.cyan(parts.join(" \u2192 "));
|
|
3232
3263
|
const terminalWidth = process.stdout.columns || 120;
|
|
3233
|
-
const separator =
|
|
3264
|
+
const separator = chalk11.gray(" | ");
|
|
3234
3265
|
const combined = `${mainLine}${separator}${activityText}`;
|
|
3235
3266
|
return truncateToWidth(combined, terminalWidth - 2);
|
|
3236
3267
|
}
|
|
@@ -3349,6 +3380,35 @@ function createLiveStatus(label) {
|
|
|
3349
3380
|
};
|
|
3350
3381
|
}
|
|
3351
3382
|
|
|
3383
|
+
// src/format.ts
|
|
3384
|
+
function stripAnsi2(str) {
|
|
3385
|
+
return str.replace(/\x1b\[[0-9;]*m/g, "");
|
|
3386
|
+
}
|
|
3387
|
+
function wrapText(text, indent, maxWidth, continuationPrefix) {
|
|
3388
|
+
if (!text || text.trim().length === 0) return text || "";
|
|
3389
|
+
if (maxWidth <= 0) return text;
|
|
3390
|
+
if (indent < 0) indent = 0;
|
|
3391
|
+
const available = maxWidth - indent;
|
|
3392
|
+
if (available > 20 && stripAnsi2(text).length <= available) return text;
|
|
3393
|
+
const minAvailable = Math.max(available, 10);
|
|
3394
|
+
const words = text.split(" ");
|
|
3395
|
+
const wrappedLines = [];
|
|
3396
|
+
let currentLine = "";
|
|
3397
|
+
for (const word of words) {
|
|
3398
|
+
if (currentLine.length === 0) {
|
|
3399
|
+
currentLine = word;
|
|
3400
|
+
} else if (stripAnsi2(currentLine).length + 1 + stripAnsi2(word).length <= minAvailable) {
|
|
3401
|
+
currentLine += " " + word;
|
|
3402
|
+
} else {
|
|
3403
|
+
wrappedLines.push(currentLine);
|
|
3404
|
+
currentLine = word;
|
|
3405
|
+
}
|
|
3406
|
+
}
|
|
3407
|
+
if (currentLine) wrappedLines.push(currentLine);
|
|
3408
|
+
const pad = continuationPrefix ?? " ".repeat(indent);
|
|
3409
|
+
return wrappedLines.join("\n" + pad);
|
|
3410
|
+
}
|
|
3411
|
+
|
|
3352
3412
|
// src/commands/generate-spec.ts
|
|
3353
3413
|
async function prompt(question, fallback) {
|
|
3354
3414
|
const rl = createInterface2({ input: process.stdin, output: process.stdout });
|
|
@@ -3364,7 +3424,7 @@ async function generateSpecCommand(description, options) {
|
|
|
3364
3424
|
if (!description) {
|
|
3365
3425
|
description = await prompt("Feature description: ");
|
|
3366
3426
|
if (!description) {
|
|
3367
|
-
console.log(
|
|
3427
|
+
console.log(chalk12.red.bold("Error:"), "Description is required.");
|
|
3368
3428
|
process.exit(1);
|
|
3369
3429
|
}
|
|
3370
3430
|
}
|
|
@@ -3384,7 +3444,7 @@ async function generateSpecCommand(description, options) {
|
|
|
3384
3444
|
try {
|
|
3385
3445
|
result = await runClarification(description, clarificationAnswers, clarifyStatus.onActivity);
|
|
3386
3446
|
} catch (err) {
|
|
3387
|
-
clarifyStatus.fail(
|
|
3447
|
+
clarifyStatus.fail(chalk12.red("Failed to check clarification needs"));
|
|
3388
3448
|
if (err instanceof TaskError) {
|
|
3389
3449
|
throw err;
|
|
3390
3450
|
}
|
|
@@ -3392,66 +3452,76 @@ async function generateSpecCommand(description, options) {
|
|
|
3392
3452
|
throw new TaskError(`Clarification check failed: ${message}`);
|
|
3393
3453
|
}
|
|
3394
3454
|
if ("ready" in result && result.ready) {
|
|
3395
|
-
clarifyStatus.succeed(
|
|
3455
|
+
clarifyStatus.succeed(chalk12.green("No clarification needed"));
|
|
3396
3456
|
ready = true;
|
|
3397
3457
|
break;
|
|
3398
3458
|
}
|
|
3399
3459
|
if ("needsClarification" in result && result.needsClarification) {
|
|
3400
3460
|
clarifyStatus.stop();
|
|
3401
3461
|
resetTerminalForInput();
|
|
3402
|
-
console.log(
|
|
3462
|
+
console.log(chalk12.yellow("\n\u2501\u2501\u2501 Clarifying Questions \u2501\u2501\u2501\n"));
|
|
3403
3463
|
const answers = [];
|
|
3404
3464
|
const rl = createInterface2({
|
|
3405
3465
|
input: process.stdin,
|
|
3406
3466
|
output: process.stdout
|
|
3407
3467
|
});
|
|
3468
|
+
const termWidth = Math.max(process.stdout.columns || 80, 40);
|
|
3408
3469
|
try {
|
|
3409
3470
|
for (let i = 0; i < result.questions.length; i++) {
|
|
3410
3471
|
const question = result.questions[i];
|
|
3472
|
+
if (i === 0) {
|
|
3473
|
+
console.log();
|
|
3474
|
+
}
|
|
3475
|
+
const counter = chalk12.cyan(`Question ${i + 1} of ${result.questions.length}`);
|
|
3476
|
+
console.log(counter);
|
|
3477
|
+
const wrapped = wrapText(question, 2, termWidth, " ");
|
|
3478
|
+
console.log(` ${wrapped}`);
|
|
3411
3479
|
const answer = await new Promise((resolve5) => {
|
|
3412
|
-
rl.question(
|
|
3413
|
-
> `, resolve5);
|
|
3480
|
+
rl.question(chalk12.gray("> "), resolve5);
|
|
3414
3481
|
});
|
|
3415
3482
|
if (answer.trim().toLowerCase() === "abort" || answer.trim().toLowerCase() === "cancel") {
|
|
3416
|
-
console.log(
|
|
3483
|
+
console.log(chalk12.red("\nAborted."));
|
|
3417
3484
|
process.exit(0);
|
|
3418
3485
|
}
|
|
3419
3486
|
answers.push(`Q: ${question}
|
|
3420
3487
|
A: ${answer}`);
|
|
3488
|
+
if (i < result.questions.length - 1) {
|
|
3489
|
+
console.log();
|
|
3490
|
+
}
|
|
3421
3491
|
}
|
|
3422
3492
|
} finally {
|
|
3423
3493
|
rl.close();
|
|
3424
3494
|
}
|
|
3425
3495
|
clarificationAnswers = answers.join("\n\n");
|
|
3426
3496
|
if (attempts < maxAttempts) {
|
|
3427
|
-
console.log(
|
|
3497
|
+
console.log(chalk12.blue("\n\u2501\u2501\u2501 Re-checking with your answers \u2501\u2501\u2501\n"));
|
|
3428
3498
|
}
|
|
3429
3499
|
}
|
|
3430
3500
|
}
|
|
3431
3501
|
if (!ready && attempts >= maxAttempts) {
|
|
3432
|
-
console.log(
|
|
3502
|
+
console.log(chalk12.yellow("Max clarification rounds reached, generating spec with answers so far..."));
|
|
3433
3503
|
}
|
|
3434
3504
|
}
|
|
3435
3505
|
const genStatus = createLiveStatus("Generating spec...");
|
|
3436
3506
|
let markdown;
|
|
3437
3507
|
try {
|
|
3438
3508
|
markdown = await generateSpec(description, clarificationAnswers, genStatus.onActivity);
|
|
3439
|
-
genStatus.succeed(
|
|
3509
|
+
genStatus.succeed(chalk12.green("Spec generated"));
|
|
3440
3510
|
} catch (err) {
|
|
3441
|
-
genStatus.fail(
|
|
3511
|
+
genStatus.fail(chalk12.red("Failed to generate spec"));
|
|
3442
3512
|
throw err;
|
|
3443
3513
|
}
|
|
3444
3514
|
const outPath = resolve4(process.cwd(), output);
|
|
3445
3515
|
writeFileSync(outPath, markdown, "utf-8");
|
|
3446
|
-
console.log(
|
|
3516
|
+
console.log(chalk12.gray("Spec written to"), chalk12.cyan(outPath));
|
|
3447
3517
|
} catch (err) {
|
|
3448
3518
|
if (err instanceof TaskError) {
|
|
3449
|
-
console.log(
|
|
3519
|
+
console.log(chalk12.red.bold("Error:"), err.message);
|
|
3450
3520
|
if (isDebug()) console.error(err.stack);
|
|
3451
3521
|
process.exit(1);
|
|
3452
3522
|
}
|
|
3453
3523
|
const message = err instanceof Error ? err.message : String(err);
|
|
3454
|
-
console.log(
|
|
3524
|
+
console.log(chalk12.red.bold("Internal error:"), message);
|
|
3455
3525
|
if (isDebug()) console.error(err instanceof Error ? err.stack : err);
|
|
3456
3526
|
process.exit(2);
|
|
3457
3527
|
}
|
|
@@ -3459,7 +3529,7 @@ A: ${answer}`);
|
|
|
3459
3529
|
}
|
|
3460
3530
|
|
|
3461
3531
|
// src/commands/spec.ts
|
|
3462
|
-
import
|
|
3532
|
+
import chalk13 from "chalk";
|
|
3463
3533
|
import { select as select2 } from "@inquirer/prompts";
|
|
3464
3534
|
|
|
3465
3535
|
// src/cursor-aware-input.ts
|
|
@@ -3660,33 +3730,6 @@ async function pasteableInput(config, context) {
|
|
|
3660
3730
|
|
|
3661
3731
|
// src/commands/spec.ts
|
|
3662
3732
|
import { ExitPromptError } from "@inquirer/core";
|
|
3663
|
-
|
|
3664
|
-
// src/format.ts
|
|
3665
|
-
function stripAnsi2(str) {
|
|
3666
|
-
return str.replace(/\x1b\[[0-9;]*m/g, "");
|
|
3667
|
-
}
|
|
3668
|
-
function wrapText(text, indent, maxWidth, continuationPrefix) {
|
|
3669
|
-
const available = maxWidth - indent;
|
|
3670
|
-
if (available <= 20 || stripAnsi2(text).length <= available) return text;
|
|
3671
|
-
const words = text.split(" ");
|
|
3672
|
-
const wrappedLines = [];
|
|
3673
|
-
let currentLine = "";
|
|
3674
|
-
for (const word of words) {
|
|
3675
|
-
if (currentLine.length === 0) {
|
|
3676
|
-
currentLine = word;
|
|
3677
|
-
} else if (stripAnsi2(currentLine).length + 1 + stripAnsi2(word).length <= available) {
|
|
3678
|
-
currentLine += " " + word;
|
|
3679
|
-
} else {
|
|
3680
|
-
wrappedLines.push(currentLine);
|
|
3681
|
-
currentLine = word;
|
|
3682
|
-
}
|
|
3683
|
-
}
|
|
3684
|
-
if (currentLine) wrappedLines.push(currentLine);
|
|
3685
|
-
const pad = continuationPrefix ?? " ".repeat(indent);
|
|
3686
|
-
return wrappedLines.join("\n" + pad);
|
|
3687
|
-
}
|
|
3688
|
-
|
|
3689
|
-
// src/commands/spec.ts
|
|
3690
3733
|
var VALID_PROVIDERS = ["jira", "linear", "local"];
|
|
3691
3734
|
function inferProvider(source) {
|
|
3692
3735
|
if (/^https:\/\/linear\.app\//.test(source)) {
|
|
@@ -3703,7 +3746,7 @@ async function specCommand(source, options) {
|
|
|
3703
3746
|
if (options.source !== void 0) {
|
|
3704
3747
|
if (!VALID_PROVIDERS.includes(options.source)) {
|
|
3705
3748
|
console.log(
|
|
3706
|
-
|
|
3749
|
+
chalk13.red.bold("Error:"),
|
|
3707
3750
|
`Invalid source provider "${options.source}". Must be one of: ${VALID_PROVIDERS.join(", ")}`
|
|
3708
3751
|
);
|
|
3709
3752
|
process.exit(1);
|
|
@@ -3716,17 +3759,17 @@ async function specCommand(source, options) {
|
|
|
3716
3759
|
const isIssueKey = ISSUE_KEY_PATTERN.test(source);
|
|
3717
3760
|
if (provider === "local" && isLinearUrl2) {
|
|
3718
3761
|
console.log(
|
|
3719
|
-
|
|
3762
|
+
chalk13.yellow("Warning:"),
|
|
3720
3763
|
`Source "${source}" is a Linear URL, but --source=local treats it as a file path.`
|
|
3721
3764
|
);
|
|
3722
3765
|
} else if (provider === "linear" && hasMdExt) {
|
|
3723
3766
|
console.log(
|
|
3724
|
-
|
|
3767
|
+
chalk13.yellow("Warning:"),
|
|
3725
3768
|
`Source "${source}" ends in .md/.markdown, but --source=linear treats it as a Linear issue ID.`
|
|
3726
3769
|
);
|
|
3727
3770
|
} else if (provider === "jira" && hasMdExt) {
|
|
3728
3771
|
console.log(
|
|
3729
|
-
|
|
3772
|
+
chalk13.yellow("Warning:"),
|
|
3730
3773
|
`Source "${source}" ends in .md/.markdown, but --source=jira treats it as a Jira issue key.`
|
|
3731
3774
|
);
|
|
3732
3775
|
}
|
|
@@ -3737,7 +3780,7 @@ async function specCommand(source, options) {
|
|
|
3737
3780
|
if (!provider) {
|
|
3738
3781
|
if (!process.stdin.isTTY) {
|
|
3739
3782
|
console.log(
|
|
3740
|
-
|
|
3783
|
+
chalk13.red.bold("Error:"),
|
|
3741
3784
|
`Cannot determine provider for "${source}" in non-interactive mode. Use --source <jira|linear|local>.`
|
|
3742
3785
|
);
|
|
3743
3786
|
process.exit(1);
|
|
@@ -3768,7 +3811,7 @@ async function specCommand(source, options) {
|
|
|
3768
3811
|
if ("needsClarification" in result && result.needsClarification) {
|
|
3769
3812
|
status.stop();
|
|
3770
3813
|
resetTerminalForInput();
|
|
3771
|
-
console.log(
|
|
3814
|
+
console.log(chalk13.yellow("\nPlanner needs clarification:\n"));
|
|
3772
3815
|
const answers = [];
|
|
3773
3816
|
for (let i = 0; i < result.questions.length; i++) {
|
|
3774
3817
|
const question = result.questions[i];
|
|
@@ -3782,37 +3825,37 @@ async function specCommand(source, options) {
|
|
|
3782
3825
|
A: ${answer}`);
|
|
3783
3826
|
}
|
|
3784
3827
|
clarificationAnswers = answers.join("\n\n");
|
|
3785
|
-
console.log(
|
|
3828
|
+
console.log(chalk13.blue("\nRe-running planner with clarifications...\n"));
|
|
3786
3829
|
status.start();
|
|
3787
3830
|
} else {
|
|
3788
3831
|
plan = result;
|
|
3789
3832
|
}
|
|
3790
3833
|
}
|
|
3791
3834
|
if (!plan) {
|
|
3792
|
-
status.fail(
|
|
3835
|
+
status.fail(chalk13.red("Planner failed"));
|
|
3793
3836
|
throw new TaskError(`Planner: failed to create valid plan after ${maxAttempts} attempts`);
|
|
3794
3837
|
}
|
|
3795
|
-
status.succeed(
|
|
3838
|
+
status.succeed(chalk13.green("Plan created"));
|
|
3796
3839
|
const cols = process.stdout.columns || 80;
|
|
3797
|
-
console.log(
|
|
3798
|
-
for (const g of plan.goals) console.log(` ${
|
|
3799
|
-
console.log(
|
|
3800
|
-
for (const t of plan.tasks) console.log(` ${
|
|
3801
|
-
console.log(
|
|
3802
|
-
for (const c of plan.constraints) console.log(` ${
|
|
3803
|
-
console.log(
|
|
3804
|
-
for (const d of plan.dod) console.log(` ${
|
|
3840
|
+
console.log(chalk13.cyan("\nGoals:"));
|
|
3841
|
+
for (const g of plan.goals) console.log(` ${chalk13.gray("-")} ${wrapText(g, 4, cols)}`);
|
|
3842
|
+
console.log(chalk13.cyan("\nTasks:"));
|
|
3843
|
+
for (const t of plan.tasks) console.log(` ${chalk13.gray("-")} ${wrapText(t, 4, cols)}`);
|
|
3844
|
+
console.log(chalk13.cyan("\nConstraints:"));
|
|
3845
|
+
for (const c of plan.constraints) console.log(` ${chalk13.gray("-")} ${wrapText(c, 4, cols)}`);
|
|
3846
|
+
console.log(chalk13.cyan("\nDefinition of Done:"));
|
|
3847
|
+
for (const d of plan.dod) console.log(` ${chalk13.gray("-")} ${wrapText(d, 4, cols)}`);
|
|
3805
3848
|
} catch (err) {
|
|
3806
3849
|
if (err instanceof ExitPromptError) {
|
|
3807
3850
|
process.exit(0);
|
|
3808
3851
|
}
|
|
3809
3852
|
if (err instanceof SpecError || err instanceof TaskError) {
|
|
3810
|
-
console.log(
|
|
3853
|
+
console.log(chalk13.red.bold("Error:"), err.message);
|
|
3811
3854
|
if (isDebug()) console.error(err.stack);
|
|
3812
3855
|
process.exit(1);
|
|
3813
3856
|
}
|
|
3814
3857
|
const message = err instanceof Error ? err.message : String(err);
|
|
3815
|
-
console.log(
|
|
3858
|
+
console.log(chalk13.red.bold("Internal error:"), message);
|
|
3816
3859
|
if (isDebug()) console.error(err instanceof Error ? err.stack : err);
|
|
3817
3860
|
process.exit(2);
|
|
3818
3861
|
}
|
|
@@ -3822,12 +3865,12 @@ A: ${answer}`);
|
|
|
3822
3865
|
// src/commands/run.ts
|
|
3823
3866
|
import { createInterface as createInterface4 } from "readline";
|
|
3824
3867
|
import { join as join6 } from "path";
|
|
3825
|
-
import
|
|
3868
|
+
import chalk19 from "chalk";
|
|
3826
3869
|
import ora2 from "ora";
|
|
3827
3870
|
import { select as select3 } from "@inquirer/prompts";
|
|
3828
3871
|
|
|
3829
3872
|
// src/implement.ts
|
|
3830
|
-
import
|
|
3873
|
+
import chalk14 from "chalk";
|
|
3831
3874
|
function getFailureSummary(stdout, maxLen = 300) {
|
|
3832
3875
|
const trimmed = stdout.trim();
|
|
3833
3876
|
if (!trimmed) return "";
|
|
@@ -4030,14 +4073,14 @@ async function runImplement(spec, plan, options, retryOptions) {
|
|
|
4030
4073
|
dev = extractDevOutput(devResult.value.stdout);
|
|
4031
4074
|
} else {
|
|
4032
4075
|
const detail = formatExitDetail(devResult.value, devAgent.model);
|
|
4033
|
-
console.log(
|
|
4076
|
+
console.log(chalk14.red("dev agent failed:"), `exit code ${devResult.value.exitCode}${detail}`);
|
|
4034
4077
|
if (!devResult.value.errorMessage || devResult.value.errorMessage.length < 50) {
|
|
4035
4078
|
const summary = getFailureSummary(devResult.value.stdout);
|
|
4036
|
-
if (summary) console.log(
|
|
4079
|
+
if (summary) console.log(chalk14.gray(" \u21B3"), chalk14.gray(summary));
|
|
4037
4080
|
}
|
|
4038
4081
|
}
|
|
4039
4082
|
} else {
|
|
4040
|
-
console.log(
|
|
4083
|
+
console.log(chalk14.red("dev agent failed:"), devResult.reason);
|
|
4041
4084
|
}
|
|
4042
4085
|
}
|
|
4043
4086
|
if (runQE) {
|
|
@@ -4048,19 +4091,19 @@ async function runImplement(spec, plan, options, retryOptions) {
|
|
|
4048
4091
|
qe = extractQEOutput(qeResult.value.stdout);
|
|
4049
4092
|
} else {
|
|
4050
4093
|
const detail = formatExitDetail(qeResult.value, qeAgent.model);
|
|
4051
|
-
console.log(
|
|
4094
|
+
console.log(chalk14.red("qe agent failed:"), `exit code ${qeResult.value.exitCode}${detail}`);
|
|
4052
4095
|
if (!qeResult.value.errorMessage || qeResult.value.errorMessage.length < 50) {
|
|
4053
4096
|
const summary = getFailureSummary(qeResult.value.stdout);
|
|
4054
|
-
if (summary) console.log(
|
|
4097
|
+
if (summary) console.log(chalk14.gray(" \u21B3"), chalk14.gray(summary));
|
|
4055
4098
|
}
|
|
4056
4099
|
}
|
|
4057
4100
|
} else {
|
|
4058
|
-
console.log(
|
|
4101
|
+
console.log(chalk14.red("qe agent failed:"), qeResult.reason);
|
|
4059
4102
|
}
|
|
4060
4103
|
}
|
|
4061
4104
|
} else {
|
|
4062
4105
|
if (runDev) {
|
|
4063
|
-
console.log(
|
|
4106
|
+
console.log(chalk14.blue("Running dev agent (approve edits as prompted)..."));
|
|
4064
4107
|
try {
|
|
4065
4108
|
const devResult = await spawnAgent("dev", devPrompt, { ...options, provider: devAgent.provider, model: devAgent.model, stage: "implement" });
|
|
4066
4109
|
if (devResult.exitCode === 0) {
|
|
@@ -4069,18 +4112,18 @@ async function runImplement(spec, plan, options, retryOptions) {
|
|
|
4069
4112
|
usages.push({ agent: "dev", usage: devResult.usage });
|
|
4070
4113
|
if (devResult.exitCode !== 0) {
|
|
4071
4114
|
const detail = formatExitDetail(devResult);
|
|
4072
|
-
console.log(
|
|
4115
|
+
console.log(chalk14.red("dev agent failed:"), `exit code ${devResult.exitCode}${detail}`);
|
|
4073
4116
|
if (!devResult.errorMessage) {
|
|
4074
4117
|
const summary = getFailureSummary(devResult.stdout);
|
|
4075
|
-
if (summary) console.log(
|
|
4118
|
+
if (summary) console.log(chalk14.gray(" \u21B3"), chalk14.gray(summary));
|
|
4076
4119
|
}
|
|
4077
4120
|
}
|
|
4078
4121
|
} catch (err) {
|
|
4079
|
-
console.log(
|
|
4122
|
+
console.log(chalk14.red("dev agent failed:"), err);
|
|
4080
4123
|
}
|
|
4081
4124
|
}
|
|
4082
4125
|
if (runQE) {
|
|
4083
|
-
console.log(
|
|
4126
|
+
console.log(chalk14.blue("Running qe agent (approve edits as prompted)..."));
|
|
4084
4127
|
try {
|
|
4085
4128
|
const qeResult = await spawnAgent("qe", qePrompt, { ...options, provider: qeAgent.provider, model: qeAgent.model, stage: "implement" });
|
|
4086
4129
|
if (qeResult.exitCode === 0) {
|
|
@@ -4089,14 +4132,14 @@ async function runImplement(spec, plan, options, retryOptions) {
|
|
|
4089
4132
|
usages.push({ agent: "qe", usage: qeResult.usage });
|
|
4090
4133
|
if (qeResult.exitCode !== 0) {
|
|
4091
4134
|
const detail = formatExitDetail(qeResult);
|
|
4092
|
-
console.log(
|
|
4135
|
+
console.log(chalk14.red("qe agent failed:"), `exit code ${qeResult.exitCode}${detail}`);
|
|
4093
4136
|
if (!qeResult.errorMessage) {
|
|
4094
4137
|
const summary = getFailureSummary(qeResult.stdout);
|
|
4095
|
-
if (summary) console.log(
|
|
4138
|
+
if (summary) console.log(chalk14.gray(" \u21B3"), chalk14.gray(summary));
|
|
4096
4139
|
}
|
|
4097
4140
|
}
|
|
4098
4141
|
} catch (err) {
|
|
4099
|
-
console.log(
|
|
4142
|
+
console.log(chalk14.red("qe agent failed:"), err);
|
|
4100
4143
|
}
|
|
4101
4144
|
}
|
|
4102
4145
|
}
|
|
@@ -4748,7 +4791,7 @@ function detectTypeFromLinearLabels(labels) {
|
|
|
4748
4791
|
|
|
4749
4792
|
// src/pr-review.ts
|
|
4750
4793
|
import { execFile as execFile2 } from "child_process";
|
|
4751
|
-
import
|
|
4794
|
+
import chalk15 from "chalk";
|
|
4752
4795
|
|
|
4753
4796
|
// src/diff-split.ts
|
|
4754
4797
|
function estimateTokens(text) {
|
|
@@ -4974,11 +5017,11 @@ function formatPRReviewTerminal(output) {
|
|
|
4974
5017
|
const lines = [];
|
|
4975
5018
|
const cols = process.stdout.columns || 80;
|
|
4976
5019
|
lines.push("");
|
|
4977
|
-
lines.push(
|
|
5020
|
+
lines.push(chalk15.cyan.bold("Summary"));
|
|
4978
5021
|
lines.push(` ${wrapText(output.summary, 2, cols)}`);
|
|
4979
5022
|
lines.push("");
|
|
4980
5023
|
if (output.comments.length > 0) {
|
|
4981
|
-
lines.push(
|
|
5024
|
+
lines.push(chalk15.cyan.bold(`Comments (${output.comments.length}):`));
|
|
4982
5025
|
const byFile = /* @__PURE__ */ new Map();
|
|
4983
5026
|
for (const c of output.comments) {
|
|
4984
5027
|
const group = byFile.get(c.file) ?? [];
|
|
@@ -4988,22 +5031,22 @@ function formatPRReviewTerminal(output) {
|
|
|
4988
5031
|
const commentIndent = 6;
|
|
4989
5032
|
for (const [file, comments] of byFile) {
|
|
4990
5033
|
lines.push("");
|
|
4991
|
-
lines.push(` ${
|
|
5034
|
+
lines.push(` ${chalk15.bold(file)}`);
|
|
4992
5035
|
for (const c of comments) {
|
|
4993
5036
|
const lineRef = c.line !== null ? `:${c.line}` : "";
|
|
4994
5037
|
const prefix = lineRef ? `${lineRef} ` : "";
|
|
4995
5038
|
const wrapped = wrapText(prefix + c.comment, commentIndent, cols);
|
|
4996
|
-
const display = c.line !== null ?
|
|
4997
|
-
lines.push(` ${
|
|
5039
|
+
const display = c.line !== null ? chalk15.gray(`:${c.line}`) + " " + wrapped.slice(prefix.length) : wrapped;
|
|
5040
|
+
lines.push(` ${chalk15.yellow("\u2022")} ${display}`);
|
|
4998
5041
|
}
|
|
4999
5042
|
}
|
|
5000
5043
|
lines.push("");
|
|
5001
5044
|
}
|
|
5002
5045
|
if (output.recommendedActions.length > 0) {
|
|
5003
|
-
lines.push(
|
|
5046
|
+
lines.push(chalk15.cyan.bold("Recommended Actions:"));
|
|
5004
5047
|
lines.push("");
|
|
5005
5048
|
for (const action of output.recommendedActions) {
|
|
5006
|
-
lines.push(` ${
|
|
5049
|
+
lines.push(` ${chalk15.gray("-")} ${wrapText(action, 4, cols)}`);
|
|
5007
5050
|
}
|
|
5008
5051
|
}
|
|
5009
5052
|
return lines.join("\n");
|
|
@@ -5097,9 +5140,9 @@ async function resolvePRNumber(context) {
|
|
|
5097
5140
|
if (context.prCreate) {
|
|
5098
5141
|
return context.prCreate.prNumber;
|
|
5099
5142
|
}
|
|
5100
|
-
console.log(
|
|
5143
|
+
console.log(chalk15.blue("No PR number provided \u2014 detecting from current branch..."));
|
|
5101
5144
|
const detected = await detectPRFromBranch();
|
|
5102
|
-
console.log(
|
|
5145
|
+
console.log(chalk15.green(`Found PR #${detected.prNumber} on branch "${detected.branch}"`));
|
|
5103
5146
|
return detected.prNumber;
|
|
5104
5147
|
}
|
|
5105
5148
|
async function runPRReview(context, options) {
|
|
@@ -5138,7 +5181,7 @@ async function postPRReviewComment(context, review) {
|
|
|
5138
5181
|
}
|
|
5139
5182
|
|
|
5140
5183
|
// src/security-review.ts
|
|
5141
|
-
import
|
|
5184
|
+
import chalk16 from "chalk";
|
|
5142
5185
|
var SEVERITY_ORDER = {
|
|
5143
5186
|
LOW: 0,
|
|
5144
5187
|
MEDIUM: 1,
|
|
@@ -5258,27 +5301,27 @@ function extractSecurityReviewOutput(stdout) {
|
|
|
5258
5301
|
}
|
|
5259
5302
|
function formatFindings(findings, threshold) {
|
|
5260
5303
|
if (findings.length === 0) {
|
|
5261
|
-
return
|
|
5304
|
+
return chalk16.gray(" No findings.");
|
|
5262
5305
|
}
|
|
5263
5306
|
return findings.map((f) => {
|
|
5264
5307
|
const isBlocking = severityAtOrAbove(f.severity, threshold);
|
|
5265
|
-
const marker = isBlocking ?
|
|
5308
|
+
const marker = isBlocking ? chalk16.red.bold("!! ") : " ";
|
|
5266
5309
|
let severityLabel;
|
|
5267
5310
|
switch (f.severity) {
|
|
5268
5311
|
case "CRITICAL":
|
|
5269
|
-
severityLabel =
|
|
5312
|
+
severityLabel = chalk16.red.bold(`[${f.severity}]`);
|
|
5270
5313
|
break;
|
|
5271
5314
|
case "HIGH":
|
|
5272
|
-
severityLabel =
|
|
5315
|
+
severityLabel = chalk16.red(`[${f.severity}]`);
|
|
5273
5316
|
break;
|
|
5274
5317
|
case "MEDIUM":
|
|
5275
|
-
severityLabel =
|
|
5318
|
+
severityLabel = chalk16.yellow(`[${f.severity}]`);
|
|
5276
5319
|
break;
|
|
5277
5320
|
case "LOW":
|
|
5278
|
-
severityLabel =
|
|
5321
|
+
severityLabel = chalk16.blue(`[${f.severity}]`);
|
|
5279
5322
|
break;
|
|
5280
5323
|
}
|
|
5281
|
-
const loc = f.location ?
|
|
5324
|
+
const loc = f.location ? chalk16.gray(
|
|
5282
5325
|
` (${f.location.file}${f.location.line ? `:${f.location.line}` : ""})`
|
|
5283
5326
|
) : "";
|
|
5284
5327
|
const cols = process.stdout.columns || 80;
|
|
@@ -5307,7 +5350,7 @@ async function runSecurityReview(context, threshold, options) {
|
|
|
5307
5350
|
}
|
|
5308
5351
|
|
|
5309
5352
|
// src/usage.ts
|
|
5310
|
-
import
|
|
5353
|
+
import chalk17 from "chalk";
|
|
5311
5354
|
|
|
5312
5355
|
// src/pricing.ts
|
|
5313
5356
|
var PROVIDER_PRICING = {
|
|
@@ -5439,7 +5482,7 @@ function printCacheWarnings(tracker) {
|
|
|
5439
5482
|
const noCacheHit = (usage.cachedTokens ?? 0) === 0;
|
|
5440
5483
|
if (hasInput && noCacheHit) {
|
|
5441
5484
|
console.error(
|
|
5442
|
-
|
|
5485
|
+
chalk17.yellow("\u26A0") + chalk17.yellow(` [${agent}] Prompt caching appears inactive for ${provider} provider. `) + chalk17.yellow("Repeated context is not being cached \u2014 costs may be higher than expected.")
|
|
5443
5486
|
);
|
|
5444
5487
|
warned.add(agent);
|
|
5445
5488
|
}
|
|
@@ -5456,21 +5499,21 @@ function printUsageSummary(tracker) {
|
|
|
5456
5499
|
const totalSavings = entries.reduce((sum, e) => sum + calculateCacheSavings(e.usage), 0);
|
|
5457
5500
|
const byAgent = tracker.getByAgent();
|
|
5458
5501
|
console.log("");
|
|
5459
|
-
console.log(
|
|
5460
|
-
console.log(
|
|
5461
|
-
console.log(
|
|
5502
|
+
console.log(chalk17.bold.cyan("\u250C\u2500 Usage Summary"));
|
|
5503
|
+
console.log(chalk17.cyan("\u2502") + ` Total cost: ${chalk17.bold(formatCost(totalCost))}`);
|
|
5504
|
+
console.log(chalk17.cyan("\u2502") + ` Duration: ${formatDuration(totalDuration)}`);
|
|
5462
5505
|
if (totalInput > 0 || totalOutput > 0) {
|
|
5463
5506
|
const cachedSuffix = totalCached > 0 ? ` / ${formatTokenCount(totalCached)} cached` : "";
|
|
5464
|
-
console.log(
|
|
5507
|
+
console.log(chalk17.cyan("\u2502") + ` Tokens: ${formatTokenCount(totalInput)} in / ${formatTokenCount(totalOutput)} out${cachedSuffix}`);
|
|
5465
5508
|
}
|
|
5466
5509
|
if (totalSavings > 0 && Math.round(totalSavings * 100) >= 1) {
|
|
5467
|
-
console.log(
|
|
5510
|
+
console.log(chalk17.cyan("\u2502") + ` Cache saves: ${chalk17.green(formatCost(totalSavings))}`);
|
|
5468
5511
|
}
|
|
5469
|
-
console.log(
|
|
5470
|
-
console.log(
|
|
5512
|
+
console.log(chalk17.cyan("\u2502"));
|
|
5513
|
+
console.log(chalk17.cyan("\u2502") + ` By agent:`);
|
|
5471
5514
|
for (const [agent, stats] of byAgent) {
|
|
5472
5515
|
const callLabel = stats.calls === 1 ? "1 call" : `${stats.calls} calls`;
|
|
5473
|
-
const prefix =
|
|
5516
|
+
const prefix = chalk17.cyan("\u2502") + " ";
|
|
5474
5517
|
console.log(prefix + `${agent.padEnd(12)} ${formatCost(stats.cost).padStart(7)} (${callLabel})`);
|
|
5475
5518
|
if (stats.inputTokens > 0 || stats.outputTokens > 0) {
|
|
5476
5519
|
const tokenParts = [];
|
|
@@ -5479,30 +5522,30 @@ function printUsageSummary(tracker) {
|
|
|
5479
5522
|
if (stats.cachedTokens > 0) {
|
|
5480
5523
|
tokenParts.push(`${formatTokenCount(stats.cachedTokens)} cached`);
|
|
5481
5524
|
}
|
|
5482
|
-
console.log(prefix +
|
|
5525
|
+
console.log(prefix + chalk17.gray(` ${tokenParts.join(" / ")}`));
|
|
5483
5526
|
}
|
|
5484
5527
|
const agentSavings = stats.cachedTokens > 0 && stats.provider ? calculateCacheSavings({ cachedTokens: stats.cachedTokens, provider: stats.provider }) : 0;
|
|
5485
5528
|
const hitRate = stats.inputTokens > 0 && stats.cachedTokens > 0 ? Math.round(stats.cachedTokens / stats.inputTokens * 100) : 0;
|
|
5486
5529
|
if (agentSavings > 0 || hitRate > 0) {
|
|
5487
5530
|
const parts = [];
|
|
5488
|
-
if (agentSavings > 0) parts.push(
|
|
5489
|
-
if (hitRate > 0) parts.push(
|
|
5531
|
+
if (agentSavings > 0) parts.push(chalk17.green(formatCost(agentSavings) + " saved"));
|
|
5532
|
+
if (hitRate > 0) parts.push(chalk17.green(hitRate + "% hit"));
|
|
5490
5533
|
console.log(prefix + ` ${parts.join(" ")}`);
|
|
5491
5534
|
}
|
|
5492
5535
|
}
|
|
5493
|
-
console.log(
|
|
5536
|
+
console.log(chalk17.cyan("\u2514\u2500"));
|
|
5494
5537
|
printCacheWarnings(tracker);
|
|
5495
5538
|
}
|
|
5496
5539
|
function printVerboseUsage(tracker) {
|
|
5497
5540
|
const entries = tracker.getEntries();
|
|
5498
5541
|
if (entries.length === 0) return;
|
|
5499
5542
|
console.log("");
|
|
5500
|
-
console.log(
|
|
5543
|
+
console.log(chalk17.bold.cyan("\u250C\u2500 Detailed Usage") + chalk17.gray(" (--verbose)"));
|
|
5501
5544
|
for (const entry of entries) {
|
|
5502
5545
|
const { agent, stage, usage } = entry;
|
|
5503
5546
|
const tokens = usage.inputTokens || usage.outputTokens ? ` ${formatTokenCount(usage.inputTokens ?? 0)} in / ${formatTokenCount(usage.outputTokens ?? 0)} out` : "";
|
|
5504
5547
|
console.log(
|
|
5505
|
-
|
|
5548
|
+
chalk17.cyan("\u2502") + ` ${chalk17.bold(agent)} ${chalk17.gray(`(${stage})`)} ${formatCost(usage.costUsd ?? 0)} ${formatDuration(usage.durationMs ?? 0)} ${usage.numTurns ?? 0} turns${tokens}`
|
|
5506
5549
|
);
|
|
5507
5550
|
const hasCacheData = (usage.cachedTokens ?? 0) > 0 || (usage.cacheWriteTokens ?? 0) > 0 || (usage.cacheDiscount ?? 0) > 0;
|
|
5508
5551
|
if (hasCacheData) {
|
|
@@ -5514,11 +5557,11 @@ function printVerboseUsage(tracker) {
|
|
|
5514
5557
|
if (savings > 0) parts.push(`saved: ${formatCost(savings)}`);
|
|
5515
5558
|
if (usage.provider) parts.push(`provider: ${usage.provider}`);
|
|
5516
5559
|
console.log(
|
|
5517
|
-
|
|
5560
|
+
chalk17.cyan("\u2502") + ` ${chalk17.gray("cache: { " + parts.join(", ") + " }")}`
|
|
5518
5561
|
);
|
|
5519
5562
|
}
|
|
5520
5563
|
}
|
|
5521
|
-
console.log(
|
|
5564
|
+
console.log(chalk17.cyan("\u2514\u2500"));
|
|
5522
5565
|
}
|
|
5523
5566
|
|
|
5524
5567
|
// src/knowledge/analyzer.ts
|
|
@@ -5972,7 +6015,7 @@ import { existsSync as existsSync8, mkdirSync as mkdirSync2 } from "fs";
|
|
|
5972
6015
|
|
|
5973
6016
|
// src/retry-prompt.ts
|
|
5974
6017
|
import { createInterface as createInterface3 } from "readline";
|
|
5975
|
-
import
|
|
6018
|
+
import chalk18 from "chalk";
|
|
5976
6019
|
async function promptForRetry(options) {
|
|
5977
6020
|
const { taskName, attempt, maxRetries, autoApprove = false, telemetry } = options;
|
|
5978
6021
|
if (maxRetries === 0) {
|
|
@@ -6015,7 +6058,7 @@ async function promptForRetry(options) {
|
|
|
6015
6058
|
const rl = createInterface3({ input: process.stdin, output: process.stdout });
|
|
6016
6059
|
const answer = await new Promise((resolve5) => {
|
|
6017
6060
|
rl.question(
|
|
6018
|
-
|
|
6061
|
+
chalk18.yellow(`
|
|
6019
6062
|
${taskName} failed after ${maxRetries} retries. Continue retrying? (y/n) `),
|
|
6020
6063
|
resolve5
|
|
6021
6064
|
);
|
|
@@ -6038,7 +6081,7 @@ ${taskName} failed after ${maxRetries} retries. Continue retrying? (y/n) `),
|
|
|
6038
6081
|
}
|
|
6039
6082
|
throw new TaskError(`${taskName} failed - user declined to retry after ${maxRetries} attempts`);
|
|
6040
6083
|
}
|
|
6041
|
-
console.log(
|
|
6084
|
+
console.log(chalk18.blue("\nContinuing retries...\n"));
|
|
6042
6085
|
return true;
|
|
6043
6086
|
}
|
|
6044
6087
|
if (!autoApprove) {
|
|
@@ -6047,14 +6090,14 @@ ${taskName} failed after ${maxRetries} retries. Continue retrying? (y/n) `),
|
|
|
6047
6090
|
const attemptInfo = maxRetries > 0 ? `(attempt ${attempt}/${maxRetries})` : `(attempt ${attempt})`;
|
|
6048
6091
|
const answer = await new Promise((resolve5) => {
|
|
6049
6092
|
rl.question(
|
|
6050
|
-
|
|
6093
|
+
chalk18.yellow(`
|
|
6051
6094
|
${taskName} failed. Retry? ${attemptInfo} (y/n) `),
|
|
6052
6095
|
resolve5
|
|
6053
6096
|
);
|
|
6054
6097
|
});
|
|
6055
6098
|
rl.close();
|
|
6056
6099
|
if (answer.toLowerCase() !== "y" && answer.toLowerCase() !== "yes") {
|
|
6057
|
-
console.log(
|
|
6100
|
+
console.log(chalk18.red("Aborted by user."));
|
|
6058
6101
|
process.exit(1);
|
|
6059
6102
|
}
|
|
6060
6103
|
}
|
|
@@ -6218,7 +6261,7 @@ async function retryGate(opts) {
|
|
|
6218
6261
|
}
|
|
6219
6262
|
}
|
|
6220
6263
|
const attemptDisplay = maxRetries > 0 ? `${attempt}/${maxRetries}` : `${attempt}`;
|
|
6221
|
-
console.log(
|
|
6264
|
+
console.log(chalk19.yellow(`
|
|
6222
6265
|
Retrying ${gateName} (attempt ${attemptDisplay})...`));
|
|
6223
6266
|
const failureContext = {
|
|
6224
6267
|
gateName,
|
|
@@ -6242,7 +6285,7 @@ Retrying ${gateName} (attempt ${attemptDisplay})...`));
|
|
|
6242
6285
|
if (retryResult.qe && context.implement) {
|
|
6243
6286
|
context.implement.qe = retryResult.qe;
|
|
6244
6287
|
}
|
|
6245
|
-
status.succeed(
|
|
6288
|
+
status.succeed(chalk19.green("Retry implementation complete"));
|
|
6246
6289
|
const retryStatus = createLiveStatus(`re-running ${gateName}...`);
|
|
6247
6290
|
const { gate: gateResult, usage: gateUsage } = await gateRunner(attempt + 1);
|
|
6248
6291
|
const gateAgentName = gateName === "unit tests" ? "gate:unit-tests" : "gate:functional-tests";
|
|
@@ -6254,17 +6297,17 @@ Retrying ${gateName} (attempt ${attemptDisplay})...`));
|
|
|
6254
6297
|
context.gates.functionalTests = gateResult;
|
|
6255
6298
|
}
|
|
6256
6299
|
if (gateResult.passed) {
|
|
6257
|
-
retryStatus.succeed(
|
|
6300
|
+
retryStatus.succeed(chalk19.green(`${gateName} PASSED on retry ${attempt}`));
|
|
6258
6301
|
return gateResult;
|
|
6259
6302
|
}
|
|
6260
6303
|
const attemptDisplayFail = maxRetries > 0 ? `${attempt}/${maxRetries}` : `${attempt}`;
|
|
6261
|
-
retryStatus.fail(
|
|
6304
|
+
retryStatus.fail(chalk19.red(`${gateName} FAILED (retry ${attemptDisplayFail})`));
|
|
6262
6305
|
}
|
|
6263
6306
|
}
|
|
6264
6307
|
async function promptLinearSpec() {
|
|
6265
6308
|
loadEnvFile();
|
|
6266
6309
|
if (!process.env.LINEAR_API_KEY) {
|
|
6267
|
-
console.log(
|
|
6310
|
+
console.log(chalk19.red.bold("Error:"), "LINEAR_API_KEY not set. Add it to your .env file.");
|
|
6268
6311
|
process.exit(1);
|
|
6269
6312
|
}
|
|
6270
6313
|
resetTerminalForInput();
|
|
@@ -6287,7 +6330,7 @@ async function promptJiraSpec() {
|
|
|
6287
6330
|
if (!process.env.JIRA_EMAIL) missing.push("JIRA_EMAIL");
|
|
6288
6331
|
if (!process.env.JIRA_API_TOKEN) missing.push("JIRA_API_TOKEN");
|
|
6289
6332
|
if (missing.length > 0) {
|
|
6290
|
-
console.log(
|
|
6333
|
+
console.log(chalk19.red.bold("Error:"), `Missing env vars: ${missing.join(", ")}. Add them to your .env file.`);
|
|
6291
6334
|
process.exit(1);
|
|
6292
6335
|
}
|
|
6293
6336
|
resetTerminalForInput();
|
|
@@ -6352,7 +6395,7 @@ async function runCommand(options) {
|
|
|
6352
6395
|
createdReygentDir = true;
|
|
6353
6396
|
} catch (err) {
|
|
6354
6397
|
if (isDebug()) {
|
|
6355
|
-
console.error(
|
|
6398
|
+
console.error(chalk19.gray("Failed to create .reygent:"), err);
|
|
6356
6399
|
}
|
|
6357
6400
|
}
|
|
6358
6401
|
}
|
|
@@ -6365,12 +6408,12 @@ async function runCommand(options) {
|
|
|
6365
6408
|
await chesstrace.init(backend);
|
|
6366
6409
|
await chesstrace.startRun();
|
|
6367
6410
|
if (createdReygentDir) {
|
|
6368
|
-
console.log(
|
|
6411
|
+
console.log(chalk19.green("\u2713"), chalk19.gray("Created .reygent/ for local knowledge learning"));
|
|
6369
6412
|
console.log("");
|
|
6370
6413
|
}
|
|
6371
6414
|
} catch (err) {
|
|
6372
6415
|
if (isDebug()) {
|
|
6373
|
-
console.error(
|
|
6416
|
+
console.error(chalk19.gray("Telemetry init failed:"), err);
|
|
6374
6417
|
}
|
|
6375
6418
|
chesstrace = null;
|
|
6376
6419
|
}
|
|
@@ -6380,7 +6423,7 @@ async function runCommand(options) {
|
|
|
6380
6423
|
let specSource = options.spec;
|
|
6381
6424
|
if (!specSource) {
|
|
6382
6425
|
if (!process.stdin.isTTY) {
|
|
6383
|
-
console.log(
|
|
6426
|
+
console.log(chalk19.red.bold("Error:"), "--spec is required in non-interactive environments.");
|
|
6384
6427
|
await chesstrace?.close();
|
|
6385
6428
|
process.exit(1);
|
|
6386
6429
|
}
|
|
@@ -6388,32 +6431,32 @@ async function runCommand(options) {
|
|
|
6388
6431
|
}
|
|
6389
6432
|
const spec = await loadSpec(specSource);
|
|
6390
6433
|
if (options.dryRun) {
|
|
6391
|
-
console.log(
|
|
6434
|
+
console.log(chalk19.yellow.bold("[dry-run]"), "No changes will be made.\n");
|
|
6392
6435
|
console.log("");
|
|
6393
|
-
console.log(
|
|
6394
|
-
console.log(
|
|
6395
|
-
console.log(
|
|
6396
|
-
console.log(
|
|
6436
|
+
console.log(chalk19.bold.cyan("\u250C\u2500 Specification"));
|
|
6437
|
+
console.log(chalk19.cyan("\u2502"), chalk19.bold(spec.title));
|
|
6438
|
+
console.log(chalk19.cyan("\u2502"), chalk19.gray(`source: ${spec.source}`));
|
|
6439
|
+
console.log(chalk19.cyan("\u2514\u2500"));
|
|
6397
6440
|
console.log("");
|
|
6398
|
-
console.log(
|
|
6441
|
+
console.log(chalk19.bold.cyan("\u250C\u2500 Workflow Stages"));
|
|
6399
6442
|
for (let i = 0; i < PIPELINE.length; i++) {
|
|
6400
6443
|
const stage = PIPELINE[i];
|
|
6401
6444
|
const isLast = i === PIPELINE.length - 1;
|
|
6402
6445
|
const prefix = isLast ? "\u2514\u2500" : "\u251C\u2500";
|
|
6403
6446
|
const continuation = isLast ? " " : "\u2502 ";
|
|
6404
|
-
console.log(
|
|
6405
|
-
console.log(
|
|
6447
|
+
console.log(chalk19.cyan(prefix), chalk19.bold.white(stage.name));
|
|
6448
|
+
console.log(chalk19.cyan(continuation), chalk19.gray(stage.description));
|
|
6406
6449
|
let execInfo = "";
|
|
6407
6450
|
if (stage.execution.kind === "agent") {
|
|
6408
|
-
execInfo =
|
|
6451
|
+
execInfo = chalk19.blue(`agent: ${stage.execution.agent}`);
|
|
6409
6452
|
} else if (stage.execution.kind === "parallel") {
|
|
6410
|
-
execInfo =
|
|
6453
|
+
execInfo = chalk19.magenta(`parallel: ${stage.execution.agents.join(", ")}`);
|
|
6411
6454
|
} else if (stage.execution.kind === "gate") {
|
|
6412
|
-
execInfo =
|
|
6455
|
+
execInfo = chalk19.yellow(`gate: ${stage.execution.condition} (${stage.execution.agent})`);
|
|
6413
6456
|
}
|
|
6414
|
-
console.log(
|
|
6457
|
+
console.log(chalk19.cyan(continuation), execInfo);
|
|
6415
6458
|
if (!isLast) {
|
|
6416
|
-
console.log(
|
|
6459
|
+
console.log(chalk19.cyan("\u2502"));
|
|
6417
6460
|
}
|
|
6418
6461
|
}
|
|
6419
6462
|
console.log("");
|
|
@@ -6428,7 +6471,7 @@ async function runCommand(options) {
|
|
|
6428
6471
|
context = { spec, results: [] };
|
|
6429
6472
|
const threshold = options.securityThreshold.toUpperCase();
|
|
6430
6473
|
if (!VALID_SEVERITIES.has(threshold)) {
|
|
6431
|
-
console.log(
|
|
6474
|
+
console.log(chalk19.red.bold("Error:"), `Invalid --security-threshold "${options.securityThreshold}". Must be one of: CRITICAL, HIGH, MEDIUM, LOW`);
|
|
6432
6475
|
process.exit(1);
|
|
6433
6476
|
}
|
|
6434
6477
|
let autoApprove = options.autoApprove;
|
|
@@ -6507,7 +6550,7 @@ async function runCommand(options) {
|
|
|
6507
6550
|
{ makeAssumptions: true, ...withActivity(agentOptions, status, toolTracker) }
|
|
6508
6551
|
);
|
|
6509
6552
|
if ("needsClarification" in result2 && result2.needsClarification) {
|
|
6510
|
-
status.fail(
|
|
6553
|
+
status.fail(chalk19.red("Planner asked questions despite skip flag"));
|
|
6511
6554
|
const chesstrace2 = getChesstrace();
|
|
6512
6555
|
if (chesstrace2) {
|
|
6513
6556
|
try {
|
|
@@ -6539,7 +6582,7 @@ async function runCommand(options) {
|
|
|
6539
6582
|
if ("needsClarification" in result2 && result2.needsClarification) {
|
|
6540
6583
|
status.stop();
|
|
6541
6584
|
resetTerminalForInput();
|
|
6542
|
-
console.log(
|
|
6585
|
+
console.log(chalk19.yellow("\nPlanner needs clarification:\n"));
|
|
6543
6586
|
const answers = [];
|
|
6544
6587
|
for (let i = 0; i < result2.questions.length; i++) {
|
|
6545
6588
|
const question = result2.questions[i];
|
|
@@ -6565,14 +6608,14 @@ async function runCommand(options) {
|
|
|
6565
6608
|
A: ${answer}`);
|
|
6566
6609
|
}
|
|
6567
6610
|
clarificationAnswers = answers.join("\n\n");
|
|
6568
|
-
console.log(
|
|
6611
|
+
console.log(chalk19.blue("\nRe-running planner with clarifications...\n"));
|
|
6569
6612
|
status.start();
|
|
6570
6613
|
} else {
|
|
6571
6614
|
plan = result2;
|
|
6572
6615
|
}
|
|
6573
6616
|
}
|
|
6574
6617
|
if (!plan) {
|
|
6575
|
-
status.fail(
|
|
6618
|
+
status.fail(chalk19.red("Planner failed"));
|
|
6576
6619
|
const chesstrace2 = getChesstrace();
|
|
6577
6620
|
if (chesstrace2) {
|
|
6578
6621
|
try {
|
|
@@ -6590,17 +6633,17 @@ A: ${answer}`);
|
|
|
6590
6633
|
);
|
|
6591
6634
|
}
|
|
6592
6635
|
}
|
|
6593
|
-
status.succeed(
|
|
6636
|
+
status.succeed(chalk19.green("Plan created"));
|
|
6594
6637
|
context.plan = plan;
|
|
6595
6638
|
const cols = process.stdout.columns || 80;
|
|
6596
|
-
console.log(
|
|
6597
|
-
for (const g of plan.goals) console.log(` ${
|
|
6598
|
-
console.log(
|
|
6599
|
-
for (const t of plan.tasks) console.log(` ${
|
|
6600
|
-
console.log(
|
|
6601
|
-
for (const c of plan.constraints) console.log(` ${
|
|
6602
|
-
console.log(
|
|
6603
|
-
for (const d of plan.dod) console.log(` ${
|
|
6639
|
+
console.log(chalk19.cyan("\nGoals:"));
|
|
6640
|
+
for (const g of plan.goals) console.log(` ${chalk19.gray("-")} ${wrapText(g, 4, cols)}`);
|
|
6641
|
+
console.log(chalk19.cyan("\nTasks:"));
|
|
6642
|
+
for (const t of plan.tasks) console.log(` ${chalk19.gray("-")} ${wrapText(t, 4, cols)}`);
|
|
6643
|
+
console.log(chalk19.cyan("\nConstraints:"));
|
|
6644
|
+
for (const c of plan.constraints) console.log(` ${chalk19.gray("-")} ${wrapText(c, 4, cols)}`);
|
|
6645
|
+
console.log(chalk19.cyan("\nDefinition of Done:"));
|
|
6646
|
+
for (const d of plan.dod) console.log(` ${chalk19.gray("-")} ${wrapText(d, 4, cols)}`);
|
|
6604
6647
|
console.log();
|
|
6605
6648
|
context.results.push({
|
|
6606
6649
|
stage: stage.name,
|
|
@@ -6638,15 +6681,15 @@ A: ${answer}`);
|
|
|
6638
6681
|
let devSuccess = impl.dev !== null;
|
|
6639
6682
|
let qeSuccess = impl.qe !== null;
|
|
6640
6683
|
if (devSuccess && qeSuccess) {
|
|
6641
|
-
implStatus.succeed(
|
|
6684
|
+
implStatus.succeed(chalk19.green("Implementation complete"));
|
|
6642
6685
|
} else {
|
|
6643
|
-
implStatus.warn(
|
|
6686
|
+
implStatus.warn(chalk19.yellow("Implementation partially failed"));
|
|
6644
6687
|
}
|
|
6645
6688
|
if (impl.dev) {
|
|
6646
|
-
console.log(
|
|
6689
|
+
console.log(chalk19.gray("dev files:"), impl.dev.files.join(", ") || chalk19.gray("(none)"));
|
|
6647
6690
|
}
|
|
6648
6691
|
if (impl.qe) {
|
|
6649
|
-
console.log(
|
|
6692
|
+
console.log(chalk19.gray("qe test files:"), impl.qe.testFiles.join(", ") || chalk19.gray("(none)"));
|
|
6650
6693
|
}
|
|
6651
6694
|
let attempt = 0;
|
|
6652
6695
|
while (!devSuccess || !qeSuccess) {
|
|
@@ -6669,7 +6712,7 @@ A: ${answer}`);
|
|
|
6669
6712
|
if (!devSuccess) agentsToRetry.push("dev");
|
|
6670
6713
|
if (!qeSuccess) agentsToRetry.push("qe");
|
|
6671
6714
|
const attemptDisplay = maxRetries > 0 ? `${attempt}/${maxRetries}` : `${attempt}`;
|
|
6672
|
-
console.log(
|
|
6715
|
+
console.log(chalk19.yellow(`
|
|
6673
6716
|
Retrying ${agentsToRetry.join(" + ")} agent(s) (attempt ${attemptDisplay})...`));
|
|
6674
6717
|
const retryStatus = createLiveStatus(`re-running ${agentsToRetry.join(" + ")} agent(s)...`);
|
|
6675
6718
|
try {
|
|
@@ -6691,18 +6734,18 @@ Retrying ${agentsToRetry.join(" + ")} agent(s) (attempt ${attemptDisplay})...`))
|
|
|
6691
6734
|
qeSuccess = true;
|
|
6692
6735
|
}
|
|
6693
6736
|
if (devSuccess && qeSuccess) {
|
|
6694
|
-
retryStatus.succeed(
|
|
6737
|
+
retryStatus.succeed(chalk19.green("Implementation complete on retry"));
|
|
6695
6738
|
if (context.implement.dev) {
|
|
6696
|
-
console.log(
|
|
6739
|
+
console.log(chalk19.gray("dev files:"), context.implement.dev.files.join(", ") || chalk19.gray("(none)"));
|
|
6697
6740
|
}
|
|
6698
6741
|
if (context.implement.qe) {
|
|
6699
|
-
console.log(
|
|
6742
|
+
console.log(chalk19.gray("qe test files:"), context.implement.qe.testFiles.join(", ") || chalk19.gray("(none)"));
|
|
6700
6743
|
}
|
|
6701
6744
|
} else {
|
|
6702
|
-
retryStatus.warn(
|
|
6745
|
+
retryStatus.warn(chalk19.yellow(`Retry ${attempt} partially failed`));
|
|
6703
6746
|
}
|
|
6704
6747
|
} catch {
|
|
6705
|
-
retryStatus.fail(
|
|
6748
|
+
retryStatus.fail(chalk19.red(`Retry ${attempt} failed`));
|
|
6706
6749
|
}
|
|
6707
6750
|
}
|
|
6708
6751
|
context.results.push({
|
|
@@ -6738,7 +6781,7 @@ Retrying ${agentsToRetry.join(" + ")} agent(s) (attempt ${attemptDisplay})...`))
|
|
|
6738
6781
|
if (!context.gates) context.gates = {};
|
|
6739
6782
|
context.gates.unitTests = gateResult;
|
|
6740
6783
|
if (gateResult.passed) {
|
|
6741
|
-
unitStatus.succeed(
|
|
6784
|
+
unitStatus.succeed(chalk19.green("Unit tests PASSED"));
|
|
6742
6785
|
context.results.push({
|
|
6743
6786
|
stage: stage.name,
|
|
6744
6787
|
success: true,
|
|
@@ -6747,7 +6790,7 @@ Retrying ${agentsToRetry.join(" + ")} agent(s) (attempt ${attemptDisplay})...`))
|
|
|
6747
6790
|
emitStageEnd(chesstrace, stage.name, stageStartTime, true, void 0, toolTracker);
|
|
6748
6791
|
continue;
|
|
6749
6792
|
}
|
|
6750
|
-
unitStatus.fail(
|
|
6793
|
+
unitStatus.fail(chalk19.red("Unit tests FAILED"));
|
|
6751
6794
|
try {
|
|
6752
6795
|
gateResult = await retryGate({
|
|
6753
6796
|
gateName: "unit tests",
|
|
@@ -6799,7 +6842,7 @@ Retrying ${agentsToRetry.join(" + ")} agent(s) (attempt ${attemptDisplay})...`))
|
|
|
6799
6842
|
if (!context.gates) context.gates = {};
|
|
6800
6843
|
context.gates.functionalTests = gateResult;
|
|
6801
6844
|
if (gateResult.passed) {
|
|
6802
|
-
funcStatus.succeed(
|
|
6845
|
+
funcStatus.succeed(chalk19.green("Functional tests PASSED"));
|
|
6803
6846
|
context.results.push({
|
|
6804
6847
|
stage: stage.name,
|
|
6805
6848
|
success: true,
|
|
@@ -6808,7 +6851,7 @@ Retrying ${agentsToRetry.join(" + ")} agent(s) (attempt ${attemptDisplay})...`))
|
|
|
6808
6851
|
emitStageEnd(chesstrace, stage.name, stageStartTime, true, void 0, toolTracker);
|
|
6809
6852
|
continue;
|
|
6810
6853
|
}
|
|
6811
|
-
funcStatus.fail(
|
|
6854
|
+
funcStatus.fail(chalk19.red("Functional tests FAILED"));
|
|
6812
6855
|
console.log(gateResult.output);
|
|
6813
6856
|
try {
|
|
6814
6857
|
gateResult = await retryGate({
|
|
@@ -6860,12 +6903,12 @@ Retrying ${agentsToRetry.join(" + ")} agent(s) (attempt ${attemptDisplay})...`))
|
|
|
6860
6903
|
if (secUsage) tracker.record("security-review", stage.name, secUsage);
|
|
6861
6904
|
context.securityReview = output;
|
|
6862
6905
|
if (passed) {
|
|
6863
|
-
secStatus.succeed(
|
|
6906
|
+
secStatus.succeed(chalk19.green("Security review PASSED"));
|
|
6864
6907
|
} else {
|
|
6865
|
-
secStatus.fail(
|
|
6908
|
+
secStatus.fail(chalk19.red("Security review FAILED"));
|
|
6866
6909
|
}
|
|
6867
6910
|
console.log("");
|
|
6868
|
-
console.log(
|
|
6911
|
+
console.log(chalk19.cyan.bold(`Security Findings (${output.findings.length}):`));
|
|
6869
6912
|
console.log(formatFindings(output.findings, threshold));
|
|
6870
6913
|
console.log("");
|
|
6871
6914
|
if (passed) {
|
|
@@ -6877,7 +6920,7 @@ Retrying ${agentsToRetry.join(" + ")} agent(s) (attempt ${attemptDisplay})...`))
|
|
|
6877
6920
|
emitStageEnd(chesstrace, stage.name, stageStartTime, true, void 0, toolTracker);
|
|
6878
6921
|
continue;
|
|
6879
6922
|
}
|
|
6880
|
-
console.log(
|
|
6923
|
+
console.log(chalk19.yellow(`Findings at or above ${threshold} threshold`));
|
|
6881
6924
|
context.results.push({
|
|
6882
6925
|
stage: stage.name,
|
|
6883
6926
|
success: false,
|
|
@@ -6885,7 +6928,7 @@ Retrying ${agentsToRetry.join(" + ")} agent(s) (attempt ${attemptDisplay})...`))
|
|
|
6885
6928
|
});
|
|
6886
6929
|
emitStageEnd(chesstrace, stage.name, stageStartTime, false, void 0, toolTracker);
|
|
6887
6930
|
if (autoApprove) {
|
|
6888
|
-
console.log(
|
|
6931
|
+
console.log(chalk19.yellow("Auto-approved \u2014 bypassing security gate..."));
|
|
6889
6932
|
} else {
|
|
6890
6933
|
resetTerminalForInput();
|
|
6891
6934
|
const rl = createInterface4({
|
|
@@ -6894,16 +6937,16 @@ Retrying ${agentsToRetry.join(" + ")} agent(s) (attempt ${attemptDisplay})...`))
|
|
|
6894
6937
|
});
|
|
6895
6938
|
const answer = await new Promise((resolve5) => {
|
|
6896
6939
|
rl.question(
|
|
6897
|
-
|
|
6940
|
+
chalk19.yellow("\nSecurity review failed. Continue with PR creation anyway? (y/n) "),
|
|
6898
6941
|
resolve5
|
|
6899
6942
|
);
|
|
6900
6943
|
});
|
|
6901
6944
|
rl.close();
|
|
6902
6945
|
if (answer.toLowerCase() !== "y" && answer.toLowerCase() !== "yes") {
|
|
6903
|
-
console.log(
|
|
6946
|
+
console.log(chalk19.red("Aborted by user."));
|
|
6904
6947
|
process.exit(1);
|
|
6905
6948
|
}
|
|
6906
|
-
console.log(
|
|
6949
|
+
console.log(chalk19.yellow("Bypassed by user \u2014 continuing..."));
|
|
6907
6950
|
}
|
|
6908
6951
|
continue;
|
|
6909
6952
|
}
|
|
@@ -6942,12 +6985,12 @@ Retrying ${agentsToRetry.join(" + ")} agent(s) (attempt ${attemptDisplay})...`))
|
|
|
6942
6985
|
});
|
|
6943
6986
|
}
|
|
6944
6987
|
}
|
|
6945
|
-
const spinner = ora2(
|
|
6988
|
+
const spinner = ora2(chalk19.blue("creating pull request...")).start();
|
|
6946
6989
|
const prResult = await runPRCreate(context, { insecure: options.insecure, branchType });
|
|
6947
6990
|
context.prCreate = prResult;
|
|
6948
|
-
spinner.succeed(
|
|
6949
|
-
console.log(
|
|
6950
|
-
console.log(
|
|
6991
|
+
spinner.succeed(chalk19.green("PR created"));
|
|
6992
|
+
console.log(chalk19.gray("branch:"), chalk19.cyan(prResult.branch));
|
|
6993
|
+
console.log(chalk19.gray("PR:"), chalk19.blue(prResult.prUrl));
|
|
6951
6994
|
context.results.push({
|
|
6952
6995
|
stage: stage.name,
|
|
6953
6996
|
success: true,
|
|
@@ -6964,15 +7007,15 @@ Retrying ${agentsToRetry.join(" + ")} agent(s) (attempt ${attemptDisplay})...`))
|
|
|
6964
7007
|
);
|
|
6965
7008
|
context.prReview = reviewOutput;
|
|
6966
7009
|
if (prUsage) tracker.record("pr-review", stage.name, prUsage);
|
|
6967
|
-
prStatus.succeed(
|
|
7010
|
+
prStatus.succeed(chalk19.green("PR review complete"));
|
|
6968
7011
|
console.log(formatPRReviewTerminal(reviewOutput));
|
|
6969
|
-
const commentSpinner = ora2(
|
|
7012
|
+
const commentSpinner = ora2(chalk19.blue("posting review comment to PR...")).start();
|
|
6970
7013
|
try {
|
|
6971
7014
|
await postPRReviewComment(context, reviewOutput);
|
|
6972
|
-
commentSpinner.succeed(
|
|
7015
|
+
commentSpinner.succeed(chalk19.green("Review posted to PR"));
|
|
6973
7016
|
} catch (err) {
|
|
6974
7017
|
const msg = err instanceof Error ? err.message : String(err);
|
|
6975
|
-
commentSpinner.fail(
|
|
7018
|
+
commentSpinner.fail(chalk19.yellow(`Could not post review to PR: ${msg}`));
|
|
6976
7019
|
}
|
|
6977
7020
|
context.results.push({
|
|
6978
7021
|
stage: stage.name,
|
|
@@ -6987,7 +7030,7 @@ Retrying ${agentsToRetry.join(" + ")} agent(s) (attempt ${attemptDisplay})...`))
|
|
|
6987
7030
|
success: true,
|
|
6988
7031
|
output: "skipped"
|
|
6989
7032
|
};
|
|
6990
|
-
console.log(
|
|
7033
|
+
console.log(chalk19.gray(`[${stage.name}] skipped`));
|
|
6991
7034
|
context.results.push(result);
|
|
6992
7035
|
emitStageEnd(chesstrace, stage.name, stageStartTime, true, void 0, toolTracker);
|
|
6993
7036
|
}
|
|
@@ -7071,13 +7114,13 @@ Retrying ${agentsToRetry.join(" + ")} agent(s) (attempt ${attemptDisplay})...`))
|
|
|
7071
7114
|
process.exit(0);
|
|
7072
7115
|
}
|
|
7073
7116
|
if (err instanceof SpecError || err instanceof TaskError) {
|
|
7074
|
-
console.log(
|
|
7117
|
+
console.log(chalk19.red.bold("Error:"), err.message);
|
|
7075
7118
|
if (isDebug()) console.error(err.stack);
|
|
7076
7119
|
if (isTest) throw err;
|
|
7077
7120
|
process.exit(1);
|
|
7078
7121
|
}
|
|
7079
7122
|
const message = err instanceof Error ? err.message : String(err);
|
|
7080
|
-
console.log(
|
|
7123
|
+
console.log(chalk19.red.bold("Internal error:"), message);
|
|
7081
7124
|
if (isDebug()) console.error(err instanceof Error ? err.stack : err);
|
|
7082
7125
|
if (isTest) throw err;
|
|
7083
7126
|
process.exit(2);
|
|
@@ -7089,7 +7132,7 @@ import { existsSync as existsSync9, mkdirSync as mkdirSync3, writeFileSync as wr
|
|
|
7089
7132
|
import { join as join7 } from "path";
|
|
7090
7133
|
import { ExitPromptError as ExitPromptError2 } from "@inquirer/core";
|
|
7091
7134
|
import { select as select4 } from "@inquirer/prompts";
|
|
7092
|
-
import
|
|
7135
|
+
import chalk20 from "chalk";
|
|
7093
7136
|
import ora3 from "ora";
|
|
7094
7137
|
async function initCommand(options = { dryRun: false }) {
|
|
7095
7138
|
const targetDir = join7(process.cwd(), ".reygent");
|
|
@@ -7101,25 +7144,25 @@ async function initCommand(options = { dryRun: false }) {
|
|
|
7101
7144
|
model: DEFAULT_MODEL5
|
|
7102
7145
|
};
|
|
7103
7146
|
if (options.dryRun) {
|
|
7104
|
-
console.log(
|
|
7105
|
-
console.log(
|
|
7106
|
-
console.log(
|
|
7107
|
-
console.log(
|
|
7108
|
-
console.log(
|
|
7147
|
+
console.log(chalk20.yellow.bold("[dry-run]"), "No changes will be made.\n");
|
|
7148
|
+
console.log(chalk20.bold("Would create:"));
|
|
7149
|
+
console.log(chalk20.gray(" dir: "), chalk20.cyan(targetDir));
|
|
7150
|
+
console.log(chalk20.gray(" dir: "), chalk20.cyan(skillsDir));
|
|
7151
|
+
console.log(chalk20.gray(" file: "), chalk20.cyan(configPath));
|
|
7109
7152
|
console.log("");
|
|
7110
|
-
console.log(
|
|
7111
|
-
console.log(
|
|
7153
|
+
console.log(chalk20.bold("Config preview:"));
|
|
7154
|
+
console.log(chalk20.gray(JSON.stringify(defaultConfig, null, 2)));
|
|
7112
7155
|
console.log("");
|
|
7113
7156
|
return;
|
|
7114
7157
|
}
|
|
7115
7158
|
try {
|
|
7116
7159
|
if (existsSync9(targetDir)) {
|
|
7117
|
-
console.log(
|
|
7118
|
-
console.log(
|
|
7160
|
+
console.log(chalk20.yellow.bold("Warning:"), `.reygent folder already exists`);
|
|
7161
|
+
console.log(chalk20.gray(` Path: ${targetDir}
|
|
7119
7162
|
`));
|
|
7120
7163
|
if (existsSync9(configPath)) {
|
|
7121
7164
|
if (!process.stdin.isTTY) {
|
|
7122
|
-
console.log(
|
|
7165
|
+
console.log(chalk20.red.bold("Error:"), "Cannot prompt in non-interactive mode. Use --dry-run to preview or remove existing .reygent/ first.");
|
|
7123
7166
|
process.exit(1);
|
|
7124
7167
|
}
|
|
7125
7168
|
resetTerminalForInput();
|
|
@@ -7132,16 +7175,16 @@ async function initCommand(options = { dryRun: false }) {
|
|
|
7132
7175
|
]
|
|
7133
7176
|
});
|
|
7134
7177
|
if (action === "cancel") {
|
|
7135
|
-
console.log(
|
|
7178
|
+
console.log(chalk20.gray("No changes made.\n"));
|
|
7136
7179
|
return;
|
|
7137
7180
|
}
|
|
7138
7181
|
if (action === "edit") {
|
|
7139
|
-
console.log(
|
|
7182
|
+
console.log(chalk20.cyan("Run"), chalk20.bold("reygent config"), chalk20.cyan("to edit your configuration.\n"));
|
|
7140
7183
|
return;
|
|
7141
7184
|
}
|
|
7142
|
-
console.log(
|
|
7185
|
+
console.log(chalk20.cyan("Resetting config to defaults...\n"));
|
|
7143
7186
|
} else {
|
|
7144
|
-
console.log(
|
|
7187
|
+
console.log(chalk20.cyan("No config.json found. Creating default config...\n"));
|
|
7145
7188
|
}
|
|
7146
7189
|
}
|
|
7147
7190
|
const spinnerText = existsSync9(targetDir) ? "Writing config" : "Creating .reygent folder";
|
|
@@ -7168,24 +7211,24 @@ knowledge/success-patterns.md
|
|
|
7168
7211
|
# - knowledge/agents/*.md (curated agent tips)
|
|
7169
7212
|
`;
|
|
7170
7213
|
writeFileSync2(gitignorePath, gitignoreContent, "utf-8");
|
|
7171
|
-
spinner.succeed(
|
|
7214
|
+
spinner.succeed(chalk20.green("Initialized .reygent folder"));
|
|
7172
7215
|
console.log("");
|
|
7173
|
-
console.log(
|
|
7174
|
-
console.log(
|
|
7175
|
-
console.log(
|
|
7176
|
-
console.log(
|
|
7177
|
-
console.log(
|
|
7178
|
-
console.log(
|
|
7216
|
+
console.log(chalk20.bold("Next steps:"));
|
|
7217
|
+
console.log(chalk20.gray(" \u2022 Edit"), chalk20.cyan(".reygent/config.json"), chalk20.gray("to customize agents"));
|
|
7218
|
+
console.log(chalk20.gray(" \u2022 Add custom agents to the"), chalk20.cyan("agents"), chalk20.gray("array"));
|
|
7219
|
+
console.log(chalk20.gray(" \u2022 Add skills to"), chalk20.cyan(".reygent/skills/"), chalk20.gray("(each in its own folder with SKILL.md)"));
|
|
7220
|
+
console.log(chalk20.gray(" \u2022 Populate"), chalk20.cyan(".reygent/knowledge/"), chalk20.gray("with project conventions"));
|
|
7221
|
+
console.log(chalk20.gray(" \u2022 Run"), chalk20.cyan("reygent agent <name>"), chalk20.gray("to use your local config"));
|
|
7179
7222
|
console.log("");
|
|
7180
7223
|
} catch (err) {
|
|
7181
7224
|
const message = err instanceof Error ? err.message : String(err);
|
|
7182
|
-
spinner.fail(
|
|
7225
|
+
spinner.fail(chalk20.red(`Failed: ${message}`));
|
|
7183
7226
|
if (isDebug()) console.error(err instanceof Error ? err.stack : err);
|
|
7184
7227
|
process.exit(2);
|
|
7185
7228
|
}
|
|
7186
7229
|
} catch (err) {
|
|
7187
7230
|
if (err instanceof ExitPromptError2) {
|
|
7188
|
-
console.log(
|
|
7231
|
+
console.log(chalk20.yellow("\nInitialization cancelled."));
|
|
7189
7232
|
process.exit(0);
|
|
7190
7233
|
}
|
|
7191
7234
|
throw err;
|
|
@@ -7196,7 +7239,7 @@ knowledge/success-patterns.md
|
|
|
7196
7239
|
import { existsSync as existsSync11, mkdirSync as mkdirSync5, writeFileSync as writeFileSync3, rmSync, readdirSync as readdirSync4, statSync as statSync5, readFileSync as readFileSync8 } from "fs";
|
|
7197
7240
|
import { join as join9, dirname as dirname4 } from "path";
|
|
7198
7241
|
import { fileURLToPath } from "url";
|
|
7199
|
-
import
|
|
7242
|
+
import chalk21 from "chalk";
|
|
7200
7243
|
import ora4 from "ora";
|
|
7201
7244
|
|
|
7202
7245
|
// src/registry.ts
|
|
@@ -7352,33 +7395,33 @@ async function listAction() {
|
|
|
7352
7395
|
try {
|
|
7353
7396
|
const skills = await listRemoteSkills();
|
|
7354
7397
|
const installed = getInstalledSkillNames();
|
|
7355
|
-
spinner.succeed(
|
|
7398
|
+
spinner.succeed(chalk21.green(`Found ${skills.length} skill${skills.length !== 1 ? "s" : ""}`));
|
|
7356
7399
|
console.log("");
|
|
7357
7400
|
if (skills.length === 0) {
|
|
7358
|
-
console.log(
|
|
7401
|
+
console.log(chalk21.gray(" No skills available in registry."));
|
|
7359
7402
|
console.log("");
|
|
7360
7403
|
return;
|
|
7361
7404
|
}
|
|
7362
7405
|
for (const skill of skills) {
|
|
7363
|
-
const badge = installed.has(skill.name) ?
|
|
7364
|
-
const version = skill.version ?
|
|
7365
|
-
console.log(` ${
|
|
7406
|
+
const badge = installed.has(skill.name) ? chalk21.green(" [installed]") : "";
|
|
7407
|
+
const version = skill.version ? chalk21.gray(` v${skill.version}`) : "";
|
|
7408
|
+
console.log(` ${chalk21.bold.cyan(skill.name)}${version}${badge}`);
|
|
7366
7409
|
console.log(` ${skill.description}`);
|
|
7367
7410
|
if (skill.license) {
|
|
7368
|
-
console.log(` ${
|
|
7411
|
+
console.log(` ${chalk21.gray(`License: ${skill.license}`)}`);
|
|
7369
7412
|
}
|
|
7370
7413
|
console.log("");
|
|
7371
7414
|
}
|
|
7372
7415
|
} catch (err) {
|
|
7373
7416
|
const message = err instanceof Error ? err.message : String(err);
|
|
7374
|
-
spinner.fail(
|
|
7417
|
+
spinner.fail(chalk21.red(`Failed to fetch skills: ${message}`));
|
|
7375
7418
|
if (isDebug()) console.error(err instanceof Error ? err.stack : err);
|
|
7376
7419
|
process.exit(2);
|
|
7377
7420
|
}
|
|
7378
7421
|
}
|
|
7379
7422
|
async function addAction(name, options) {
|
|
7380
7423
|
if (!validateSkillName(name)) {
|
|
7381
|
-
console.log(
|
|
7424
|
+
console.log(chalk21.red.bold("Error:"), `Invalid skill name "${name}"`);
|
|
7382
7425
|
process.exit(1);
|
|
7383
7426
|
}
|
|
7384
7427
|
let targetBase;
|
|
@@ -7387,15 +7430,15 @@ async function addAction(name, options) {
|
|
|
7387
7430
|
} else {
|
|
7388
7431
|
const localSkillsDir = resolveSkillsDir("local");
|
|
7389
7432
|
if (!localSkillsDir) {
|
|
7390
|
-
console.log(
|
|
7391
|
-
console.log(
|
|
7433
|
+
console.log(chalk21.red.bold("Error:"), "No .reygent/ directory found.");
|
|
7434
|
+
console.log(chalk21.gray(" Run"), chalk21.cyan("reygent init"), chalk21.gray("first, or use"), chalk21.cyan("--global"));
|
|
7392
7435
|
process.exit(1);
|
|
7393
7436
|
}
|
|
7394
7437
|
targetBase = localSkillsDir;
|
|
7395
7438
|
}
|
|
7396
7439
|
const targetDir = join9(targetBase, name);
|
|
7397
7440
|
if (existsSync11(targetDir)) {
|
|
7398
|
-
console.log(
|
|
7441
|
+
console.log(chalk21.red.bold("Error:"), `Skill "${name}" already installed at ${targetDir}`);
|
|
7399
7442
|
process.exit(1);
|
|
7400
7443
|
}
|
|
7401
7444
|
const spinner = ora4(`Installing ${name}...`).start();
|
|
@@ -7406,9 +7449,9 @@ async function addAction(name, options) {
|
|
|
7406
7449
|
const compatible = checkCompatibility(manifest.compatibility, version);
|
|
7407
7450
|
if (!compatible) {
|
|
7408
7451
|
spinner.warn(
|
|
7409
|
-
|
|
7452
|
+
chalk21.yellow(`Skill "${name}" requires ${manifest.compatibility}, you have v${version}`)
|
|
7410
7453
|
);
|
|
7411
|
-
console.log(
|
|
7454
|
+
console.log(chalk21.yellow(" Installing anyway \u2014 some features may not work.\n"));
|
|
7412
7455
|
spinner.start(`Downloading ${name}...`);
|
|
7413
7456
|
}
|
|
7414
7457
|
spinner.text = `Downloading ${name}...`;
|
|
@@ -7420,21 +7463,21 @@ async function addAction(name, options) {
|
|
|
7420
7463
|
mkdirSync5(fileDir, { recursive: true });
|
|
7421
7464
|
writeFileSync3(filePath, file.content, "utf-8");
|
|
7422
7465
|
}
|
|
7423
|
-
spinner.succeed(
|
|
7466
|
+
spinner.succeed(chalk21.green(`Installed "${name}" (${files.length} files)`));
|
|
7424
7467
|
console.log("");
|
|
7425
|
-
console.log(
|
|
7426
|
-
console.log(
|
|
7468
|
+
console.log(chalk21.gray(" Location:"), chalk21.cyan(targetDir));
|
|
7469
|
+
console.log(chalk21.gray(" Usage: "), chalk21.cyan(`reygent agent ${name}`));
|
|
7427
7470
|
console.log("");
|
|
7428
7471
|
} catch (err) {
|
|
7429
7472
|
const message = err instanceof Error ? err.message : String(err);
|
|
7430
|
-
spinner.fail(
|
|
7473
|
+
spinner.fail(chalk21.red(`Failed to install "${name}": ${message}`));
|
|
7431
7474
|
if (isDebug()) console.error(err instanceof Error ? err.stack : err);
|
|
7432
7475
|
process.exit(2);
|
|
7433
7476
|
}
|
|
7434
7477
|
}
|
|
7435
7478
|
async function removeAction(name, options) {
|
|
7436
7479
|
if (!validateSkillName(name)) {
|
|
7437
|
-
console.log(
|
|
7480
|
+
console.log(chalk21.red.bold("Error:"), `Invalid skill name "${name}"`);
|
|
7438
7481
|
process.exit(1);
|
|
7439
7482
|
}
|
|
7440
7483
|
let targetBase;
|
|
@@ -7443,22 +7486,22 @@ async function removeAction(name, options) {
|
|
|
7443
7486
|
} else {
|
|
7444
7487
|
const localSkillsDir = resolveSkillsDir("local");
|
|
7445
7488
|
if (!localSkillsDir) {
|
|
7446
|
-
console.log(
|
|
7489
|
+
console.log(chalk21.red.bold("Error:"), "No .reygent/ directory found.");
|
|
7447
7490
|
process.exit(1);
|
|
7448
7491
|
}
|
|
7449
7492
|
targetBase = localSkillsDir;
|
|
7450
7493
|
}
|
|
7451
7494
|
const targetDir = join9(targetBase, name);
|
|
7452
7495
|
if (!existsSync11(targetDir)) {
|
|
7453
|
-
console.log(
|
|
7496
|
+
console.log(chalk21.red.bold("Error:"), `Skill "${name}" not found at ${targetDir}`);
|
|
7454
7497
|
process.exit(1);
|
|
7455
7498
|
}
|
|
7456
7499
|
try {
|
|
7457
7500
|
rmSync(targetDir, { recursive: true, force: true });
|
|
7458
|
-
console.log(
|
|
7501
|
+
console.log(chalk21.green(`Removed "${name}" from ${targetDir}`));
|
|
7459
7502
|
} catch (err) {
|
|
7460
7503
|
const message = err instanceof Error ? err.message : String(err);
|
|
7461
|
-
console.log(
|
|
7504
|
+
console.log(chalk21.red.bold("Error:"), `Failed to remove "${name}": ${message}`);
|
|
7462
7505
|
if (isDebug()) console.error(err instanceof Error ? err.stack : err);
|
|
7463
7506
|
process.exit(1);
|
|
7464
7507
|
}
|
|
@@ -7473,7 +7516,7 @@ function registerSkillsCommand(program2) {
|
|
|
7473
7516
|
// src/commands/review-work.ts
|
|
7474
7517
|
import { execFile as execFile3 } from "child_process";
|
|
7475
7518
|
import { request as httpsRequest2 } from "https";
|
|
7476
|
-
import
|
|
7519
|
+
import chalk22 from "chalk";
|
|
7477
7520
|
import ora5 from "ora";
|
|
7478
7521
|
|
|
7479
7522
|
// src/spec-prefix.ts
|
|
@@ -7826,7 +7869,7 @@ async function reviewWorkCommand(options) {
|
|
|
7826
7869
|
try {
|
|
7827
7870
|
await exec3("git", ["rev-parse", "--is-inside-work-tree"]);
|
|
7828
7871
|
} catch {
|
|
7829
|
-
console.log(
|
|
7872
|
+
console.log(chalk22.red.bold("Error:"), "Not inside a git repository.");
|
|
7830
7873
|
process.exit(1);
|
|
7831
7874
|
}
|
|
7832
7875
|
loadEnvFile();
|
|
@@ -7837,9 +7880,9 @@ async function reviewWorkCommand(options) {
|
|
|
7837
7880
|
const parsed = parseSpecWithPrefix(options.spec);
|
|
7838
7881
|
const loaded = await loadSpec(parsed.identifier, parsed.provider);
|
|
7839
7882
|
spec = { title: loaded.title, content: loaded.content };
|
|
7840
|
-
spinner.succeed(
|
|
7883
|
+
spinner.succeed(chalk22.green(`Spec loaded: ${loaded.title}`));
|
|
7841
7884
|
} catch (err) {
|
|
7842
|
-
spinner.fail(
|
|
7885
|
+
spinner.fail(chalk22.red("Failed to load spec"));
|
|
7843
7886
|
throw err;
|
|
7844
7887
|
}
|
|
7845
7888
|
}
|
|
@@ -7848,14 +7891,14 @@ async function reviewWorkCommand(options) {
|
|
|
7848
7891
|
const branch = await getCurrentBranch();
|
|
7849
7892
|
const defaultBranch = await getDefaultBranch();
|
|
7850
7893
|
console.log(
|
|
7851
|
-
|
|
7894
|
+
chalk22.gray(` Platform: ${remote.platform}`) + chalk22.gray(` | Branch: ${branch}`) + chalk22.gray(` | Base: ${defaultBranch}`)
|
|
7852
7895
|
);
|
|
7853
7896
|
console.log();
|
|
7854
7897
|
if (remote.platform === "github") {
|
|
7855
7898
|
const spinner = ora5("Checking for open PR...").start();
|
|
7856
7899
|
const prNumber = await detectGitHubPR();
|
|
7857
7900
|
if (prNumber !== null) {
|
|
7858
|
-
spinner.succeed(
|
|
7901
|
+
spinner.succeed(chalk22.green(`Found PR #${prNumber}`));
|
|
7859
7902
|
const context = {
|
|
7860
7903
|
spec: spec ? { source: "markdown", title: spec.title, content: spec.content } : { source: "markdown", title: "Review", content: "" },
|
|
7861
7904
|
prCreate: {
|
|
@@ -7869,19 +7912,19 @@ async function reviewWorkCommand(options) {
|
|
|
7869
7912
|
console.log();
|
|
7870
7913
|
const prReviewStatus = createLiveStatus("Running PR review...");
|
|
7871
7914
|
const { output } = await runPRReview(context, { quiet: true, onActivity: prReviewStatus.onActivity });
|
|
7872
|
-
prReviewStatus.succeed(
|
|
7915
|
+
prReviewStatus.succeed(chalk22.green("Review complete"));
|
|
7873
7916
|
console.log(formatPRReviewTerminal(output));
|
|
7874
7917
|
console.log();
|
|
7875
7918
|
const postSpinner = ora5("Posting review comment to PR...").start();
|
|
7876
7919
|
try {
|
|
7877
7920
|
await postPRReviewComment(context, output);
|
|
7878
|
-
postSpinner.succeed(
|
|
7921
|
+
postSpinner.succeed(chalk22.green(`Review posted to PR #${prNumber}`));
|
|
7879
7922
|
} catch (err) {
|
|
7880
7923
|
const msg = err instanceof Error ? err.message : String(err);
|
|
7881
|
-
postSpinner.fail(
|
|
7924
|
+
postSpinner.fail(chalk22.red(`Failed to post comment: ${msg}`));
|
|
7882
7925
|
}
|
|
7883
7926
|
} else {
|
|
7884
|
-
spinner.info(
|
|
7927
|
+
spinner.info(chalk22.yellow("No open PR found for this branch"));
|
|
7885
7928
|
console.log();
|
|
7886
7929
|
const reviewStatus = createLiveStatus("Running review...");
|
|
7887
7930
|
let output;
|
|
@@ -7890,15 +7933,15 @@ async function reviewWorkCommand(options) {
|
|
|
7890
7933
|
} catch (err) {
|
|
7891
7934
|
if (err instanceof TaskError && err.message.includes("no changes found")) {
|
|
7892
7935
|
reviewStatus.stop();
|
|
7893
|
-
console.log(
|
|
7936
|
+
console.log(chalk22.yellow("No changes found against"), chalk22.bold(defaultBranch));
|
|
7894
7937
|
return;
|
|
7895
7938
|
}
|
|
7896
7939
|
throw err;
|
|
7897
7940
|
}
|
|
7898
|
-
reviewStatus.succeed(
|
|
7941
|
+
reviewStatus.succeed(chalk22.green("Review complete"));
|
|
7899
7942
|
console.log(formatPRReviewTerminal(output));
|
|
7900
7943
|
console.log();
|
|
7901
|
-
console.log(
|
|
7944
|
+
console.log(chalk22.gray("No PR found \u2014 review printed to console only."));
|
|
7902
7945
|
}
|
|
7903
7946
|
} else {
|
|
7904
7947
|
const spinner = ora5("Checking for open MR...").start();
|
|
@@ -7908,16 +7951,16 @@ async function reviewWorkCommand(options) {
|
|
|
7908
7951
|
} catch (err) {
|
|
7909
7952
|
if (isDebug()) {
|
|
7910
7953
|
const msg = err instanceof Error ? err.message : String(err);
|
|
7911
|
-
console.error(
|
|
7954
|
+
console.error(chalk22.gray(`[debug] Token resolution failed: ${msg}`));
|
|
7912
7955
|
}
|
|
7913
|
-
spinner.info(
|
|
7956
|
+
spinner.info(chalk22.yellow("Could not resolve GitLab token \u2014 skipping MR detection"));
|
|
7914
7957
|
token = "";
|
|
7915
7958
|
}
|
|
7916
7959
|
const mrIid = token ? await detectGitLabMR(remote, token, branch, options.insecure) : null;
|
|
7917
7960
|
if (mrIid !== null) {
|
|
7918
|
-
spinner.succeed(
|
|
7961
|
+
spinner.succeed(chalk22.green(`Found MR !${mrIid}`));
|
|
7919
7962
|
} else {
|
|
7920
|
-
spinner.info(
|
|
7963
|
+
spinner.info(chalk22.yellow("No open MR found for this branch"));
|
|
7921
7964
|
}
|
|
7922
7965
|
console.log();
|
|
7923
7966
|
const glReviewStatus = createLiveStatus("Running review...");
|
|
@@ -7927,12 +7970,12 @@ async function reviewWorkCommand(options) {
|
|
|
7927
7970
|
} catch (err) {
|
|
7928
7971
|
if (err instanceof TaskError && err.message.includes("no changes found")) {
|
|
7929
7972
|
glReviewStatus.stop();
|
|
7930
|
-
console.log(
|
|
7973
|
+
console.log(chalk22.yellow("No changes found against"), chalk22.bold(defaultBranch));
|
|
7931
7974
|
return;
|
|
7932
7975
|
}
|
|
7933
7976
|
throw err;
|
|
7934
7977
|
}
|
|
7935
|
-
glReviewStatus.succeed(
|
|
7978
|
+
glReviewStatus.succeed(chalk22.green("Review complete"));
|
|
7936
7979
|
console.log(formatPRReviewTerminal(output));
|
|
7937
7980
|
console.log();
|
|
7938
7981
|
if (mrIid !== null && token) {
|
|
@@ -7940,13 +7983,13 @@ async function reviewWorkCommand(options) {
|
|
|
7940
7983
|
try {
|
|
7941
7984
|
const body = formatPRReviewOutput(output) + "\n\n---\n*Review by [reygent](https://github.com/andrewevans0102/reygent)*";
|
|
7942
7985
|
await postGitLabComment(remote, token, mrIid, body, options.insecure);
|
|
7943
|
-
postSpinner.succeed(
|
|
7986
|
+
postSpinner.succeed(chalk22.green(`Review posted to MR !${mrIid}`));
|
|
7944
7987
|
} catch (err) {
|
|
7945
7988
|
const msg = err instanceof Error ? err.message : String(err);
|
|
7946
|
-
postSpinner.fail(
|
|
7989
|
+
postSpinner.fail(chalk22.red(`Failed to post comment: ${msg}`));
|
|
7947
7990
|
}
|
|
7948
7991
|
} else {
|
|
7949
|
-
console.log(
|
|
7992
|
+
console.log(chalk22.gray("No MR found \u2014 review printed to console only."));
|
|
7950
7993
|
}
|
|
7951
7994
|
}
|
|
7952
7995
|
} catch (err) {
|
|
@@ -7954,12 +7997,12 @@ async function reviewWorkCommand(options) {
|
|
|
7954
7997
|
process.exit(0);
|
|
7955
7998
|
}
|
|
7956
7999
|
if (err instanceof SpecError || err instanceof SpecPrefixError || err instanceof TaskError) {
|
|
7957
|
-
console.log(
|
|
8000
|
+
console.log(chalk22.red.bold("Error:"), err.message);
|
|
7958
8001
|
if (isDebug()) console.error(err.stack);
|
|
7959
8002
|
process.exit(1);
|
|
7960
8003
|
}
|
|
7961
8004
|
const message = err instanceof Error ? err.message : String(err);
|
|
7962
|
-
console.log(
|
|
8005
|
+
console.log(chalk22.red.bold("Internal error:"), message);
|
|
7963
8006
|
if (isDebug()) console.error(err instanceof Error ? err.stack : err);
|
|
7964
8007
|
process.exit(2);
|
|
7965
8008
|
}
|
|
@@ -7968,7 +8011,7 @@ async function reviewWorkCommand(options) {
|
|
|
7968
8011
|
// src/commands/review-comments.ts
|
|
7969
8012
|
import { execFile as execFile4 } from "child_process";
|
|
7970
8013
|
import { request as httpsRequest3 } from "https";
|
|
7971
|
-
import
|
|
8014
|
+
import chalk23 from "chalk";
|
|
7972
8015
|
import { select as select5 } from "@inquirer/prompts";
|
|
7973
8016
|
var PRIMARY_SECURITY_KEYWORDS = [
|
|
7974
8017
|
"xss",
|
|
@@ -8237,21 +8280,21 @@ async function fetchGitLabComments(remote, token, mrIid, insecure) {
|
|
|
8237
8280
|
function displayCommentSummary(comments) {
|
|
8238
8281
|
const securityCount = comments.filter((c) => c.isSecurity).length;
|
|
8239
8282
|
const generalCount = comments.length - securityCount;
|
|
8240
|
-
console.log(
|
|
8283
|
+
console.log(chalk23.bold(` ${comments.length} review comment(s) found`));
|
|
8241
8284
|
if (securityCount > 0) {
|
|
8242
8285
|
console.log(
|
|
8243
|
-
|
|
8286
|
+
chalk23.yellow(` \u26A0 ${securityCount} security-related`) + chalk23.gray(` | ${generalCount} general`)
|
|
8244
8287
|
);
|
|
8245
8288
|
}
|
|
8246
8289
|
console.log();
|
|
8247
8290
|
for (const c of comments) {
|
|
8248
|
-
const location = c.path ?
|
|
8249
|
-
const tag = c.isSecurity ?
|
|
8250
|
-
console.log(` ${tag}${
|
|
8291
|
+
const location = c.path ? chalk23.cyan(` ${c.path}${c.line ? `:${c.line}` : ""}`) : chalk23.gray(" (general)");
|
|
8292
|
+
const tag = c.isSecurity ? chalk23.bgYellow.black(" SEC ") + " " : "";
|
|
8293
|
+
console.log(` ${tag}${chalk23.bold(c.author)} ${location}`);
|
|
8251
8294
|
const cols = process.stdout.columns || 80;
|
|
8252
8295
|
const preview = c.body.length > 200 ? c.body.slice(0, 200) + "..." : c.body;
|
|
8253
8296
|
for (const line of preview.split("\n")) {
|
|
8254
|
-
console.log(
|
|
8297
|
+
console.log(chalk23.gray(` ${wrapText(line, 4, cols)}`));
|
|
8255
8298
|
}
|
|
8256
8299
|
console.log();
|
|
8257
8300
|
}
|
|
@@ -8377,23 +8420,23 @@ async function generatePlan(comments, includedDiffs, excludedFiles, feedback) {
|
|
|
8377
8420
|
}
|
|
8378
8421
|
function displayPlan(plan) {
|
|
8379
8422
|
const cols = process.stdout.columns || 80;
|
|
8380
|
-
console.log(
|
|
8381
|
-
console.log(
|
|
8423
|
+
console.log(chalk23.bold("\n Plan to Address Review Comments\n"));
|
|
8424
|
+
console.log(chalk23.bold.blue(" Goals:"));
|
|
8382
8425
|
for (const g of plan.goals) {
|
|
8383
8426
|
console.log(` - ${wrapText(g, 6, cols)}`);
|
|
8384
8427
|
}
|
|
8385
8428
|
console.log();
|
|
8386
|
-
console.log(
|
|
8429
|
+
console.log(chalk23.bold.blue(" Tasks:"));
|
|
8387
8430
|
for (const t of plan.tasks) {
|
|
8388
8431
|
console.log(` - ${wrapText(t, 6, cols)}`);
|
|
8389
8432
|
}
|
|
8390
8433
|
console.log();
|
|
8391
|
-
console.log(
|
|
8434
|
+
console.log(chalk23.bold.blue(" Constraints:"));
|
|
8392
8435
|
for (const c of plan.constraints) {
|
|
8393
8436
|
console.log(` - ${wrapText(c, 6, cols)}`);
|
|
8394
8437
|
}
|
|
8395
8438
|
console.log();
|
|
8396
|
-
console.log(
|
|
8439
|
+
console.log(chalk23.bold.blue(" Definition of Done:"));
|
|
8397
8440
|
for (const d of plan.dod) {
|
|
8398
8441
|
console.log(` - ${wrapText(d, 6, cols)}`);
|
|
8399
8442
|
}
|
|
@@ -8460,9 +8503,9 @@ async function executeWithDevAgent(comments, plan, autoApprove, onActivity, user
|
|
|
8460
8503
|
const parsed = JSON.parse(extractJSON(result.stdout));
|
|
8461
8504
|
if (parsed.files && parsed.files.length > 0) {
|
|
8462
8505
|
console.log();
|
|
8463
|
-
console.log(
|
|
8506
|
+
console.log(chalk23.bold(" Files modified:"));
|
|
8464
8507
|
for (const f of parsed.files) {
|
|
8465
|
-
console.log(` - ${
|
|
8508
|
+
console.log(` - ${chalk23.cyan(f)}`);
|
|
8466
8509
|
}
|
|
8467
8510
|
}
|
|
8468
8511
|
} catch {
|
|
@@ -8474,7 +8517,7 @@ async function reviewCommentsCommand(options) {
|
|
|
8474
8517
|
try {
|
|
8475
8518
|
await exec4("git", ["rev-parse", "--is-inside-work-tree"]);
|
|
8476
8519
|
} catch {
|
|
8477
|
-
console.log(
|
|
8520
|
+
console.log(chalk23.red.bold("Error:"), "Not inside a git repository.");
|
|
8478
8521
|
process.exit(1);
|
|
8479
8522
|
}
|
|
8480
8523
|
loadEnvFile();
|
|
@@ -8483,7 +8526,7 @@ async function reviewCommentsCommand(options) {
|
|
|
8483
8526
|
const branch = await getCurrentBranch2();
|
|
8484
8527
|
const defaultBranch = await getDefaultBranch2();
|
|
8485
8528
|
console.log(
|
|
8486
|
-
|
|
8529
|
+
chalk23.gray(` Platform: ${remote.platform}`) + chalk23.gray(` | Branch: ${branch}`) + chalk23.gray(` | Base: ${defaultBranch}`)
|
|
8487
8530
|
);
|
|
8488
8531
|
console.log();
|
|
8489
8532
|
let comments = [];
|
|
@@ -8491,20 +8534,20 @@ async function reviewCommentsCommand(options) {
|
|
|
8491
8534
|
const spinner = createLiveStatus("checking for open PR...");
|
|
8492
8535
|
const prNumber = await detectGitHubPR2();
|
|
8493
8536
|
if (prNumber === null) {
|
|
8494
|
-
spinner.fail(
|
|
8537
|
+
spinner.fail(chalk23.red("No open PR found for this branch"));
|
|
8495
8538
|
console.log();
|
|
8496
|
-
console.log(
|
|
8539
|
+
console.log(chalk23.yellow("Cannot pull review comments without a PR or MR."));
|
|
8497
8540
|
process.exit(1);
|
|
8498
8541
|
}
|
|
8499
|
-
spinner.succeed(
|
|
8542
|
+
spinner.succeed(chalk23.green(`Found PR #${prNumber}`));
|
|
8500
8543
|
console.log();
|
|
8501
8544
|
const commentSpinner = createLiveStatus("fetching review comments...");
|
|
8502
8545
|
comments = await fetchGitHubComments();
|
|
8503
8546
|
if (comments.length === 0) {
|
|
8504
|
-
commentSpinner.info(
|
|
8547
|
+
commentSpinner.info(chalk23.yellow("No review comments found on this PR"));
|
|
8505
8548
|
return;
|
|
8506
8549
|
}
|
|
8507
|
-
commentSpinner.succeed(
|
|
8550
|
+
commentSpinner.succeed(chalk23.green(`Fetched ${comments.length} comment(s)`));
|
|
8508
8551
|
} else {
|
|
8509
8552
|
const spinner = createLiveStatus("checking for open MR...");
|
|
8510
8553
|
let token;
|
|
@@ -8513,29 +8556,29 @@ async function reviewCommentsCommand(options) {
|
|
|
8513
8556
|
} catch (err) {
|
|
8514
8557
|
if (isDebug()) {
|
|
8515
8558
|
const msg = err instanceof Error ? err.message : String(err);
|
|
8516
|
-
console.error(
|
|
8559
|
+
console.error(chalk23.gray(`[debug] Token resolution failed: ${msg}`));
|
|
8517
8560
|
}
|
|
8518
|
-
spinner.fail(
|
|
8561
|
+
spinner.fail(chalk23.red("Could not resolve GitLab token"));
|
|
8519
8562
|
console.log();
|
|
8520
|
-
console.log(
|
|
8563
|
+
console.log(chalk23.yellow("Cannot pull review comments without a PR or MR."));
|
|
8521
8564
|
process.exit(1);
|
|
8522
8565
|
}
|
|
8523
8566
|
const mrIid = await detectGitLabMR2(remote, token, branch, options.insecure);
|
|
8524
8567
|
if (mrIid === null) {
|
|
8525
|
-
spinner.fail(
|
|
8568
|
+
spinner.fail(chalk23.red("No open MR found for this branch"));
|
|
8526
8569
|
console.log();
|
|
8527
|
-
console.log(
|
|
8570
|
+
console.log(chalk23.yellow("Cannot pull review comments without a PR or MR."));
|
|
8528
8571
|
process.exit(1);
|
|
8529
8572
|
}
|
|
8530
|
-
spinner.succeed(
|
|
8573
|
+
spinner.succeed(chalk23.green(`Found MR !${mrIid}`));
|
|
8531
8574
|
console.log();
|
|
8532
8575
|
const commentSpinner = createLiveStatus("fetching review comments...");
|
|
8533
8576
|
comments = await fetchGitLabComments(remote, token, mrIid, options.insecure);
|
|
8534
8577
|
if (comments.length === 0) {
|
|
8535
|
-
commentSpinner.info(
|
|
8578
|
+
commentSpinner.info(chalk23.yellow("No review comments found on this MR"));
|
|
8536
8579
|
return;
|
|
8537
8580
|
}
|
|
8538
|
-
commentSpinner.succeed(
|
|
8581
|
+
commentSpinner.succeed(chalk23.green(`Fetched ${comments.length} comment(s)`));
|
|
8539
8582
|
}
|
|
8540
8583
|
const classified = classifyComments(comments);
|
|
8541
8584
|
console.log();
|
|
@@ -8545,7 +8588,7 @@ async function reviewCommentsCommand(options) {
|
|
|
8545
8588
|
let includedDiffs = [];
|
|
8546
8589
|
let excludedFiles = [];
|
|
8547
8590
|
if (!rawDiff.trim()) {
|
|
8548
|
-
diffSpinner.warn(
|
|
8591
|
+
diffSpinner.warn(chalk23.yellow("No diff found against base branch"));
|
|
8549
8592
|
} else {
|
|
8550
8593
|
const fileDiffs = splitDiffByFile(rawDiff);
|
|
8551
8594
|
const reservedTokens = estimateTokens(formatCommentBlock(classified)) + RESERVED_PROMPT_TOKENS;
|
|
@@ -8575,16 +8618,16 @@ async function reviewCommentsCommand(options) {
|
|
|
8575
8618
|
}
|
|
8576
8619
|
}
|
|
8577
8620
|
if (excludedFiles.length > 0) {
|
|
8578
|
-
diffSpinner.succeed(
|
|
8621
|
+
diffSpinner.succeed(chalk23.green(`Diff loaded (${includedDiffs.length} files included, ${excludedFiles.length} excluded for size)`));
|
|
8579
8622
|
} else {
|
|
8580
|
-
diffSpinner.succeed(
|
|
8623
|
+
diffSpinner.succeed(chalk23.green("Diff loaded"));
|
|
8581
8624
|
}
|
|
8582
8625
|
}
|
|
8583
8626
|
let plan;
|
|
8584
8627
|
{
|
|
8585
8628
|
const planSpinner = createLiveStatus("generating plan...");
|
|
8586
8629
|
plan = await generatePlan(classified, includedDiffs, excludedFiles);
|
|
8587
|
-
planSpinner.succeed(
|
|
8630
|
+
planSpinner.succeed(chalk23.green("Plan generated"));
|
|
8588
8631
|
}
|
|
8589
8632
|
displayPlan(plan);
|
|
8590
8633
|
let userInstructions;
|
|
@@ -8611,7 +8654,7 @@ async function reviewCommentsCommand(options) {
|
|
|
8611
8654
|
if (feedback.trim()) {
|
|
8612
8655
|
const planSpinner = createLiveStatus("regenerating plan...");
|
|
8613
8656
|
plan = await generatePlan(classified, includedDiffs, excludedFiles, feedback);
|
|
8614
|
-
planSpinner.succeed(
|
|
8657
|
+
planSpinner.succeed(chalk23.green("Plan regenerated"));
|
|
8615
8658
|
displayPlan(plan);
|
|
8616
8659
|
}
|
|
8617
8660
|
} else if (action === "instructions") {
|
|
@@ -8623,14 +8666,14 @@ async function reviewCommentsCommand(options) {
|
|
|
8623
8666
|
userInstructions = userInstructions ? `${userInstructions}
|
|
8624
8667
|
|
|
8625
8668
|
${extra.trim()}` : extra.trim();
|
|
8626
|
-
console.log(
|
|
8669
|
+
console.log(chalk23.green(" Instructions saved. They will be included when executing."));
|
|
8627
8670
|
const displayText = userInstructions.length > 200 ? userInstructions.slice(0, 200) + "..." : userInstructions;
|
|
8628
|
-
console.log(
|
|
8671
|
+
console.log(chalk23.gray(` Current instructions:
|
|
8629
8672
|
${displayText.split("\n").join("\n ")}`));
|
|
8630
8673
|
console.log();
|
|
8631
8674
|
}
|
|
8632
8675
|
} else {
|
|
8633
|
-
console.log(
|
|
8676
|
+
console.log(chalk23.yellow("\n Rejected. No changes made.\n"));
|
|
8634
8677
|
return;
|
|
8635
8678
|
}
|
|
8636
8679
|
}
|
|
@@ -8638,7 +8681,7 @@ ${extra.trim()}` : extra.trim();
|
|
|
8638
8681
|
console.log();
|
|
8639
8682
|
const execStatus = createLiveStatus("addressing review comments...");
|
|
8640
8683
|
await executeWithDevAgent(classified, plan, true, execStatus.onActivity, userInstructions);
|
|
8641
|
-
execStatus.succeed(
|
|
8684
|
+
execStatus.succeed(chalk23.green("Dev agent finished"));
|
|
8642
8685
|
console.log();
|
|
8643
8686
|
const pushSpinner = createLiveStatus("committing and pushing...");
|
|
8644
8687
|
const trace = getChesstrace();
|
|
@@ -8664,12 +8707,12 @@ ${extra.trim()}` : extra.trim();
|
|
|
8664
8707
|
trace.emit(Events.GIT_PUSH, { branch });
|
|
8665
8708
|
} catch {
|
|
8666
8709
|
}
|
|
8667
|
-
pushSpinner.succeed(
|
|
8710
|
+
pushSpinner.succeed(chalk23.green("Changes pushed."));
|
|
8668
8711
|
} else {
|
|
8669
|
-
pushSpinner.warn(
|
|
8712
|
+
pushSpinner.warn(chalk23.yellow("No changes were made by the dev agent."));
|
|
8670
8713
|
}
|
|
8671
8714
|
} catch {
|
|
8672
|
-
pushSpinner.warn(
|
|
8715
|
+
pushSpinner.warn(chalk23.yellow("Nothing to commit or push."));
|
|
8673
8716
|
}
|
|
8674
8717
|
} else {
|
|
8675
8718
|
let retryCount = 0;
|
|
@@ -8688,7 +8731,7 @@ ${extra.trim()}` : extra.trim();
|
|
|
8688
8731
|
trace.emit(Events.GIT_ERROR, { operation: "commit", error: retryMsg, retriesExhausted: maxRetries });
|
|
8689
8732
|
} catch {
|
|
8690
8733
|
}
|
|
8691
|
-
pushSpinner.fail(
|
|
8734
|
+
pushSpinner.fail(chalk23.red(`Commit failed after ${maxRetries} retries: ${retryMsg}`));
|
|
8692
8735
|
}
|
|
8693
8736
|
}
|
|
8694
8737
|
}
|
|
@@ -8705,30 +8748,30 @@ ${extra.trim()}` : extra.trim();
|
|
|
8705
8748
|
trace.emit(Events.GIT_PUSH, { branch });
|
|
8706
8749
|
} catch {
|
|
8707
8750
|
}
|
|
8708
|
-
pushSpinner.succeed(
|
|
8751
|
+
pushSpinner.succeed(chalk23.green("Changes committed and pushed."));
|
|
8709
8752
|
} catch (pushErr) {
|
|
8710
8753
|
const pushMsg = pushErr instanceof Error ? pushErr.message : String(pushErr);
|
|
8711
8754
|
try {
|
|
8712
8755
|
trace.emit(Events.GIT_ERROR, { operation: "push", error: pushMsg });
|
|
8713
8756
|
} catch {
|
|
8714
8757
|
}
|
|
8715
|
-
pushSpinner.fail(
|
|
8758
|
+
pushSpinner.fail(chalk23.red(`Push failed: ${pushMsg}`));
|
|
8716
8759
|
}
|
|
8717
8760
|
}
|
|
8718
8761
|
console.log();
|
|
8719
|
-
console.log(
|
|
8762
|
+
console.log(chalk23.green.bold(" Done!"), chalk23.gray("Review comments addressed."));
|
|
8720
8763
|
console.log();
|
|
8721
8764
|
} catch (err) {
|
|
8722
8765
|
if (err instanceof Error && err.name === "ExitPromptError") {
|
|
8723
8766
|
process.exit(0);
|
|
8724
8767
|
}
|
|
8725
8768
|
if (err instanceof TaskError) {
|
|
8726
|
-
console.log(
|
|
8769
|
+
console.log(chalk23.red.bold("Error:"), err.message);
|
|
8727
8770
|
if (isDebug()) console.error(err.stack);
|
|
8728
8771
|
process.exit(1);
|
|
8729
8772
|
}
|
|
8730
8773
|
const message = err instanceof Error ? err.message : String(err);
|
|
8731
|
-
console.log(
|
|
8774
|
+
console.log(chalk23.red.bold("Internal error:"), message);
|
|
8732
8775
|
if (isDebug()) console.error(err instanceof Error ? err.stack : err);
|
|
8733
8776
|
process.exit(2);
|
|
8734
8777
|
}
|
|
@@ -8739,22 +8782,22 @@ ${extra.trim()}` : extra.trim();
|
|
|
8739
8782
|
import { existsSync as existsSync12, readFileSync as readFileSync9, writeFileSync as writeFileSync4, mkdirSync as mkdirSync6, lstatSync, renameSync, unlinkSync } from "fs";
|
|
8740
8783
|
import { join as join10, dirname as dirname5 } from "path";
|
|
8741
8784
|
import { randomBytes } from "crypto";
|
|
8742
|
-
import
|
|
8785
|
+
import chalk24 from "chalk";
|
|
8743
8786
|
import { select as select6, confirm } from "@inquirer/prompts";
|
|
8744
8787
|
var AGENT_CATEGORIES = [
|
|
8745
8788
|
{
|
|
8746
8789
|
label: "Development",
|
|
8747
|
-
color:
|
|
8790
|
+
color: chalk24.blue,
|
|
8748
8791
|
roles: ["developer", "general"]
|
|
8749
8792
|
},
|
|
8750
8793
|
{
|
|
8751
8794
|
label: "Testing & Review",
|
|
8752
|
-
color:
|
|
8795
|
+
color: chalk24.magenta,
|
|
8753
8796
|
roles: ["quality-engineer", "security-reviewer", "reviewer"]
|
|
8754
8797
|
},
|
|
8755
8798
|
{
|
|
8756
8799
|
label: "Planning",
|
|
8757
|
-
color:
|
|
8800
|
+
color: chalk24.yellow,
|
|
8758
8801
|
roles: ["planner"]
|
|
8759
8802
|
}
|
|
8760
8803
|
];
|
|
@@ -8785,7 +8828,7 @@ function categorizeAgents(agents) {
|
|
|
8785
8828
|
if (remaining.length > 0) {
|
|
8786
8829
|
groups.push({
|
|
8787
8830
|
label: "Other",
|
|
8788
|
-
color:
|
|
8831
|
+
color: chalk24.gray,
|
|
8789
8832
|
agentIndices: remaining
|
|
8790
8833
|
});
|
|
8791
8834
|
}
|
|
@@ -8793,14 +8836,14 @@ function categorizeAgents(agents) {
|
|
|
8793
8836
|
}
|
|
8794
8837
|
function roleBadge(role) {
|
|
8795
8838
|
const badges = {
|
|
8796
|
-
"developer":
|
|
8797
|
-
"general":
|
|
8798
|
-
"quality-engineer":
|
|
8799
|
-
"security-reviewer":
|
|
8800
|
-
"reviewer":
|
|
8801
|
-
"planner":
|
|
8839
|
+
"developer": chalk24.bgBlue.white,
|
|
8840
|
+
"general": chalk24.bgBlue.white,
|
|
8841
|
+
"quality-engineer": chalk24.bgMagenta.white,
|
|
8842
|
+
"security-reviewer": chalk24.bgRed.white,
|
|
8843
|
+
"reviewer": chalk24.bgMagenta.white,
|
|
8844
|
+
"planner": chalk24.bgYellow.black
|
|
8802
8845
|
};
|
|
8803
|
-
const colorFn = badges[role] ??
|
|
8846
|
+
const colorFn = badges[role] ?? chalk24.bgGray.white;
|
|
8804
8847
|
return colorFn(` ${role} `);
|
|
8805
8848
|
}
|
|
8806
8849
|
async function configCommand() {
|
|
@@ -8808,7 +8851,7 @@ async function configCommand() {
|
|
|
8808
8851
|
await runConfig();
|
|
8809
8852
|
} catch (err) {
|
|
8810
8853
|
if (err && typeof err === "object" && "name" in err && err.name === "ExitPromptError") {
|
|
8811
|
-
console.log(
|
|
8854
|
+
console.log(chalk24.yellow("\nConfiguration cancelled."));
|
|
8812
8855
|
process.exit(0);
|
|
8813
8856
|
}
|
|
8814
8857
|
throw err;
|
|
@@ -8816,23 +8859,23 @@ async function configCommand() {
|
|
|
8816
8859
|
}
|
|
8817
8860
|
async function runConfig() {
|
|
8818
8861
|
if (!process.stdin.isTTY) {
|
|
8819
|
-
console.log(
|
|
8820
|
-
console.log(
|
|
8862
|
+
console.log(chalk24.red.bold("Error:"), "config command requires interactive mode.");
|
|
8863
|
+
console.log(chalk24.gray(" Edit"), chalk24.cyan(".reygent/config.json"), chalk24.gray("or"), chalk24.cyan("~/.reygent/config.json"), chalk24.gray("directly."));
|
|
8821
8864
|
process.exit(1);
|
|
8822
8865
|
}
|
|
8823
8866
|
const scope = await select6({
|
|
8824
8867
|
message: "Configuration scope:",
|
|
8825
8868
|
choices: [
|
|
8826
|
-
{ name: `Local ${
|
|
8827
|
-
{ name: `Global ${
|
|
8869
|
+
{ name: `Local ${chalk24.gray("\u2014 .reygent/config.json (this project)")}`, value: "local" },
|
|
8870
|
+
{ name: `Global ${chalk24.gray("\u2014 ~/.reygent/config.json (all projects)")}`, value: "global" }
|
|
8828
8871
|
]
|
|
8829
8872
|
});
|
|
8830
8873
|
let configPath;
|
|
8831
8874
|
if (scope === "local") {
|
|
8832
8875
|
const configDir = findLocalConfigDir(process.cwd());
|
|
8833
8876
|
if (!configDir) {
|
|
8834
|
-
console.log(
|
|
8835
|
-
console.log(
|
|
8877
|
+
console.log(chalk24.red.bold("Error:"), "No .reygent/ directory found.");
|
|
8878
|
+
console.log(chalk24.gray(" Run"), chalk24.cyan("reygent init"), chalk24.gray("first."));
|
|
8836
8879
|
console.log("");
|
|
8837
8880
|
process.exit(1);
|
|
8838
8881
|
}
|
|
@@ -8850,15 +8893,15 @@ async function runConfig() {
|
|
|
8850
8893
|
rawConfig = JSON.parse(content);
|
|
8851
8894
|
} catch (err) {
|
|
8852
8895
|
if (err instanceof SyntaxError) {
|
|
8853
|
-
console.log(
|
|
8854
|
-
console.log(
|
|
8896
|
+
console.log(chalk24.red.bold("Error:"), `Invalid JSON in ${configPath}`);
|
|
8897
|
+
console.log(chalk24.gray(" Parse error:"), err.message);
|
|
8855
8898
|
process.exit(2);
|
|
8856
8899
|
}
|
|
8857
8900
|
if (err && typeof err === "object" && "code" in err && err.code === "EACCES") {
|
|
8858
|
-
console.log(
|
|
8901
|
+
console.log(chalk24.red.bold("Error:"), `Permission denied: ${configPath}`);
|
|
8859
8902
|
process.exit(2);
|
|
8860
8903
|
}
|
|
8861
|
-
console.log(
|
|
8904
|
+
console.log(chalk24.red.bold("Error:"), `Failed to read ${configPath}`);
|
|
8862
8905
|
if (isDebug()) console.error(err);
|
|
8863
8906
|
process.exit(2);
|
|
8864
8907
|
}
|
|
@@ -8877,15 +8920,15 @@ async function runConfig() {
|
|
|
8877
8920
|
}
|
|
8878
8921
|
const currentProvider = rawConfig.provider ?? "(not set)";
|
|
8879
8922
|
const currentModel = rawConfig.model ?? "(not set)";
|
|
8880
|
-
console.log(
|
|
8881
|
-
console.log(
|
|
8882
|
-
console.log(
|
|
8883
|
-
console.log(
|
|
8923
|
+
console.log(chalk24.bold("Current config:"));
|
|
8924
|
+
console.log(chalk24.gray(" Scope: "), chalk24.cyan(scope));
|
|
8925
|
+
console.log(chalk24.gray(" Provider:"), chalk24.cyan(currentProvider));
|
|
8926
|
+
console.log(chalk24.gray(" Model: "), chalk24.cyan(currentModel));
|
|
8884
8927
|
console.log("");
|
|
8885
8928
|
const providerChoices = PROVIDER_NAMES.map((name) => {
|
|
8886
8929
|
const status = availability[name];
|
|
8887
|
-
const badge = status?.available ?
|
|
8888
|
-
const hint = !status?.available && status?.reason ?
|
|
8930
|
+
const badge = status?.available ? chalk24.green("\u2713") : chalk24.red("\u2717");
|
|
8931
|
+
const hint = !status?.available && status?.reason ? chalk24.gray(` \u2014 ${status.reason}`) : "";
|
|
8889
8932
|
return {
|
|
8890
8933
|
name: `${badge} ${name}${hint}`,
|
|
8891
8934
|
value: name
|
|
@@ -8899,14 +8942,14 @@ async function runConfig() {
|
|
|
8899
8942
|
});
|
|
8900
8943
|
if (!availability[selectedProvider]?.available) {
|
|
8901
8944
|
const reason = availability[selectedProvider]?.reason ?? "unknown reason";
|
|
8902
|
-
console.log(
|
|
8945
|
+
console.log(chalk24.yellow("\u26A0"), chalk24.yellow(`Provider ${selectedProvider} is unavailable (${reason})`));
|
|
8903
8946
|
resetTerminalForInput();
|
|
8904
8947
|
const proceed = await confirm({
|
|
8905
8948
|
message: "Continue with this provider anyway?",
|
|
8906
8949
|
default: false
|
|
8907
8950
|
});
|
|
8908
8951
|
if (!proceed) {
|
|
8909
|
-
console.log(
|
|
8952
|
+
console.log(chalk24.yellow("\nConfiguration cancelled."));
|
|
8910
8953
|
process.exit(0);
|
|
8911
8954
|
}
|
|
8912
8955
|
}
|
|
@@ -8924,30 +8967,59 @@ async function runConfig() {
|
|
|
8924
8967
|
name: `${m.id} \u2014 ${m.label}`,
|
|
8925
8968
|
value: m.id
|
|
8926
8969
|
}));
|
|
8927
|
-
|
|
8970
|
+
modelChoices.push({
|
|
8971
|
+
name: chalk24.gray("Custom model (enter manually)"),
|
|
8972
|
+
value: "__custom__"
|
|
8973
|
+
});
|
|
8974
|
+
const modelSelection = await select6({
|
|
8928
8975
|
message: "Default model:",
|
|
8929
8976
|
choices: modelChoices,
|
|
8930
8977
|
default: rawConfig.model ?? provider.defaultModel
|
|
8931
8978
|
});
|
|
8979
|
+
if (modelSelection === "__custom__") {
|
|
8980
|
+
resetTerminalForInput();
|
|
8981
|
+
selectedModel = await pasteableInput({
|
|
8982
|
+
message: "Enter model ID:",
|
|
8983
|
+
default: rawConfig.model ?? provider.defaultModel
|
|
8984
|
+
});
|
|
8985
|
+
if (selectedProvider === "claude") {
|
|
8986
|
+
if (!selectedModel.startsWith("claude-") && !selectedModel.includes("projects/")) {
|
|
8987
|
+
console.log(chalk24.yellow("\u26A0"), chalk24.yellow("Model ID doesn't look like Claude format. Expected: claude-{family}-{version} or Vertex AI full resource name."));
|
|
8988
|
+
console.log(chalk24.gray(" Examples: claude-opus-4-6, projects/PROJECT/locations/REGION/publishers/anthropic/models/MODEL"));
|
|
8989
|
+
}
|
|
8990
|
+
} else if (selectedProvider === "gemini") {
|
|
8991
|
+
if (!selectedModel.startsWith("gemini-") && !selectedModel.includes("projects/")) {
|
|
8992
|
+
console.log(chalk24.yellow("\u26A0"), chalk24.yellow("Model ID doesn't look like Gemini format. Expected: gemini-{version}-{variant} or Vertex AI full resource name."));
|
|
8993
|
+
console.log(chalk24.gray(" Examples: gemini-2.5-pro, projects/PROJECT/locations/REGION/publishers/google/models/MODEL"));
|
|
8994
|
+
}
|
|
8995
|
+
} else if (selectedProvider === "codex") {
|
|
8996
|
+
if (!selectedModel.startsWith("gpt-")) {
|
|
8997
|
+
console.log(chalk24.yellow("\u26A0"), chalk24.yellow("Model ID doesn't look like Codex format. Expected: gpt-{version}"));
|
|
8998
|
+
console.log(chalk24.gray(" Examples: gpt-5.4, gpt-6.0"));
|
|
8999
|
+
}
|
|
9000
|
+
}
|
|
9001
|
+
} else {
|
|
9002
|
+
selectedModel = modelSelection;
|
|
9003
|
+
}
|
|
8932
9004
|
}
|
|
8933
9005
|
const updatedAgents = [...agents];
|
|
8934
9006
|
const categorized = categorizeAgents(agents);
|
|
8935
9007
|
for (const group of categorized) {
|
|
8936
9008
|
console.log("");
|
|
8937
|
-
console.log(group.color(
|
|
9009
|
+
console.log(group.color(chalk24.bold(`\u2500\u2500 ${group.label} \u2500\u2500`)));
|
|
8938
9010
|
for (const agentIndex of group.agentIndices) {
|
|
8939
9011
|
const agent = updatedAgents[agentIndex];
|
|
8940
9012
|
const agentProvider = agent.provider ?? selectedProvider;
|
|
8941
9013
|
const agentModel = agent.model ?? selectedModel;
|
|
8942
9014
|
console.log("");
|
|
8943
|
-
console.log(
|
|
8944
|
-
console.log(
|
|
9015
|
+
console.log(chalk24.bold(agent.name), roleBadge(agent.role));
|
|
9016
|
+
console.log(chalk24.gray(` ${agent.description}`));
|
|
8945
9017
|
console.log(
|
|
8946
|
-
|
|
8947
|
-
agent.tools.map((t) =>
|
|
9018
|
+
chalk24.gray(" Tools:"),
|
|
9019
|
+
agent.tools.map((t) => chalk24.cyan(t)).join(chalk24.gray(", "))
|
|
8948
9020
|
);
|
|
8949
|
-
console.log(
|
|
8950
|
-
console.log(
|
|
9021
|
+
console.log(chalk24.gray(" Provider:"), chalk24.cyan(agentProvider));
|
|
9022
|
+
console.log(chalk24.gray(" Model: "), chalk24.cyan(agentModel));
|
|
8951
9023
|
const hasOverride = agent.provider !== void 0 || agent.model !== void 0;
|
|
8952
9024
|
resetTerminalForInput();
|
|
8953
9025
|
const action = await select6({
|
|
@@ -8974,7 +9046,7 @@ async function runConfig() {
|
|
|
8974
9046
|
});
|
|
8975
9047
|
if (!availability[agentProviderChoice]?.available) {
|
|
8976
9048
|
const reason = availability[agentProviderChoice]?.reason ?? "unknown reason";
|
|
8977
|
-
console.log(
|
|
9049
|
+
console.log(chalk24.yellow("\u26A0"), chalk24.yellow(`Provider ${agentProviderChoice} is unavailable (${reason})`));
|
|
8978
9050
|
resetTerminalForInput();
|
|
8979
9051
|
const proceed = await confirm({
|
|
8980
9052
|
message: "Continue with this provider anyway?",
|
|
@@ -8998,11 +9070,40 @@ async function runConfig() {
|
|
|
8998
9070
|
name: `${m.id} \u2014 ${m.label}`,
|
|
8999
9071
|
value: m.id
|
|
9000
9072
|
}));
|
|
9001
|
-
|
|
9073
|
+
agentModelChoices.push({
|
|
9074
|
+
name: chalk24.gray("Custom model (enter manually)"),
|
|
9075
|
+
value: "__custom__"
|
|
9076
|
+
});
|
|
9077
|
+
const agentModelSelection = await select6({
|
|
9002
9078
|
message: `Model for ${agent.name}:`,
|
|
9003
9079
|
choices: agentModelChoices,
|
|
9004
9080
|
default: agent.model ?? agentProviderAdapter.defaultModel
|
|
9005
9081
|
});
|
|
9082
|
+
if (agentModelSelection === "__custom__") {
|
|
9083
|
+
resetTerminalForInput();
|
|
9084
|
+
agentModelChoice = await pasteableInput({
|
|
9085
|
+
message: `Enter model ID for ${agent.name}:`,
|
|
9086
|
+
default: agent.model ?? agentProviderAdapter.defaultModel
|
|
9087
|
+
});
|
|
9088
|
+
if (agentProviderChoice === "claude") {
|
|
9089
|
+
if (!agentModelChoice.startsWith("claude-") && !agentModelChoice.includes("projects/")) {
|
|
9090
|
+
console.log(chalk24.yellow("\u26A0"), chalk24.yellow("Model ID doesn't look like Claude format. Expected: claude-{family}-{version} or Vertex AI full resource name."));
|
|
9091
|
+
console.log(chalk24.gray(" Examples: claude-opus-4-6, projects/PROJECT/locations/REGION/publishers/anthropic/models/MODEL"));
|
|
9092
|
+
}
|
|
9093
|
+
} else if (agentProviderChoice === "gemini") {
|
|
9094
|
+
if (!agentModelChoice.startsWith("gemini-") && !agentModelChoice.includes("projects/")) {
|
|
9095
|
+
console.log(chalk24.yellow("\u26A0"), chalk24.yellow("Model ID doesn't look like Gemini format. Expected: gemini-{version}-{variant} or Vertex AI full resource name."));
|
|
9096
|
+
console.log(chalk24.gray(" Examples: gemini-2.5-pro, projects/PROJECT/locations/REGION/publishers/google/models/MODEL"));
|
|
9097
|
+
}
|
|
9098
|
+
} else if (agentProviderChoice === "codex") {
|
|
9099
|
+
if (!agentModelChoice.startsWith("gpt-")) {
|
|
9100
|
+
console.log(chalk24.yellow("\u26A0"), chalk24.yellow("Model ID doesn't look like Codex format. Expected: gpt-{version}"));
|
|
9101
|
+
console.log(chalk24.gray(" Examples: gpt-5.4, gpt-6.0"));
|
|
9102
|
+
}
|
|
9103
|
+
}
|
|
9104
|
+
} else {
|
|
9105
|
+
agentModelChoice = agentModelSelection;
|
|
9106
|
+
}
|
|
9006
9107
|
}
|
|
9007
9108
|
updatedAgents[agentIndex] = { ...agent, provider: agentProviderChoice, model: agentModelChoice };
|
|
9008
9109
|
}
|
|
@@ -9044,24 +9145,24 @@ async function runConfig() {
|
|
|
9044
9145
|
}
|
|
9045
9146
|
} catch (err) {
|
|
9046
9147
|
const message = err instanceof Error ? err.message : String(err);
|
|
9047
|
-
console.log(
|
|
9148
|
+
console.log(chalk24.red.bold("Error:"), `Failed to write config: ${message}`);
|
|
9048
9149
|
if (isDebug()) console.error(err instanceof Error ? err.stack : err);
|
|
9049
9150
|
process.exit(2);
|
|
9050
9151
|
}
|
|
9051
9152
|
console.log("");
|
|
9052
|
-
console.log(
|
|
9053
|
-
console.log(
|
|
9054
|
-
console.log(
|
|
9055
|
-
console.log(
|
|
9056
|
-
console.log(
|
|
9153
|
+
console.log(chalk24.green.bold("\u2713"), chalk24.bold("Config updated"));
|
|
9154
|
+
console.log(chalk24.gray(" Scope: "), chalk24.cyan(scope));
|
|
9155
|
+
console.log(chalk24.gray(" File: "), chalk24.gray(configPath));
|
|
9156
|
+
console.log(chalk24.gray(" Provider:"), chalk24.cyan(selectedProvider));
|
|
9157
|
+
console.log(chalk24.gray(" Model: "), chalk24.cyan(selectedModel));
|
|
9057
9158
|
const overriddenAgents = updatedAgents.filter((a) => a.provider || a.model);
|
|
9058
9159
|
if (overriddenAgents.length > 0) {
|
|
9059
|
-
console.log(
|
|
9160
|
+
console.log(chalk24.gray(" Agent overrides:"));
|
|
9060
9161
|
for (const a of overriddenAgents) {
|
|
9061
9162
|
const parts = [];
|
|
9062
9163
|
if (a.provider) parts.push(`provider=${a.provider}`);
|
|
9063
9164
|
if (a.model) parts.push(`model=${a.model}`);
|
|
9064
|
-
console.log(
|
|
9165
|
+
console.log(chalk24.gray(` ${a.name}:`), chalk24.cyan(parts.join(", ")));
|
|
9065
9166
|
}
|
|
9066
9167
|
}
|
|
9067
9168
|
console.log("");
|
|
@@ -9070,7 +9171,7 @@ async function runConfig() {
|
|
|
9070
9171
|
// src/commands/telemetry.ts
|
|
9071
9172
|
import { statSync as statSync6 } from "fs";
|
|
9072
9173
|
import { writeFileSync as writeFileSync5 } from "fs";
|
|
9073
|
-
import
|
|
9174
|
+
import chalk25 from "chalk";
|
|
9074
9175
|
import ora6 from "ora";
|
|
9075
9176
|
import Table from "cli-table3";
|
|
9076
9177
|
import { join as join11 } from "path";
|
|
@@ -9121,7 +9222,7 @@ async function statusCommand() {
|
|
|
9121
9222
|
const config = loadConfig();
|
|
9122
9223
|
const telemetryConfig = config.telemetry;
|
|
9123
9224
|
if (!telemetryConfig) {
|
|
9124
|
-
spinner.fail(
|
|
9225
|
+
spinner.fail(chalk25.red("Telemetry configuration not found"));
|
|
9125
9226
|
return;
|
|
9126
9227
|
}
|
|
9127
9228
|
const backendType = telemetryConfig.backend === "sqlite" ? "local" : "local";
|
|
@@ -9131,20 +9232,20 @@ async function statusCommand() {
|
|
|
9131
9232
|
const dbPath = backend.getDbPath();
|
|
9132
9233
|
const dbSize = getDbSize(dbPath);
|
|
9133
9234
|
await backend.close();
|
|
9134
|
-
spinner.succeed(
|
|
9235
|
+
spinner.succeed(chalk25.green("Telemetry status loaded"));
|
|
9135
9236
|
console.log();
|
|
9136
|
-
console.log(
|
|
9137
|
-
console.log(` Enabled: ${telemetryConfig.enabled === void 0 ?
|
|
9138
|
-
console.log(` Level: ${
|
|
9139
|
-
console.log(` Backend: ${
|
|
9140
|
-
console.log(` Retention: ${
|
|
9237
|
+
console.log(chalk25.bold("Telemetry Configuration"));
|
|
9238
|
+
console.log(` Enabled: ${telemetryConfig.enabled === void 0 ? chalk25.yellow("unset (will prompt)") : telemetryConfig.enabled ? chalk25.green("yes") : chalk25.red("no")}`);
|
|
9239
|
+
console.log(` Level: ${chalk25.cyan(telemetryConfig.level)}`);
|
|
9240
|
+
console.log(` Backend: ${chalk25.cyan(telemetryConfig.backend)}`);
|
|
9241
|
+
console.log(` Retention: ${chalk25.cyan(`${telemetryConfig.retention} days`)}`);
|
|
9141
9242
|
console.log();
|
|
9142
|
-
console.log(
|
|
9143
|
-
console.log(` Database: ${
|
|
9144
|
-
console.log(` Size: ${
|
|
9145
|
-
console.log(` Runs: ${
|
|
9243
|
+
console.log(chalk25.bold("Storage"));
|
|
9244
|
+
console.log(` Database: ${chalk25.gray(dbPath)}`);
|
|
9245
|
+
console.log(` Size: ${chalk25.cyan(formatBytes(dbSize))}`);
|
|
9246
|
+
console.log(` Runs: ${chalk25.cyan(runs.length.toString())}`);
|
|
9146
9247
|
} catch (err) {
|
|
9147
|
-
spinner.fail(
|
|
9248
|
+
spinner.fail(chalk25.red(`Failed to load telemetry status: ${err.message}`));
|
|
9148
9249
|
process.exit(1);
|
|
9149
9250
|
}
|
|
9150
9251
|
}
|
|
@@ -9161,25 +9262,25 @@ async function runsCommand(options) {
|
|
|
9161
9262
|
if (options.limit) {
|
|
9162
9263
|
const parsed = Number.parseInt(options.limit, 10);
|
|
9163
9264
|
if (isNaN(parsed) || parsed < 1) {
|
|
9164
|
-
spinner.fail(
|
|
9265
|
+
spinner.fail(chalk25.red(`Invalid limit: ${options.limit}. Must be positive integer.`));
|
|
9165
9266
|
process.exit(1);
|
|
9166
9267
|
}
|
|
9167
9268
|
limit = parsed;
|
|
9168
9269
|
}
|
|
9169
9270
|
const runs = allRuns.slice(0, limit);
|
|
9170
|
-
spinner.succeed(
|
|
9271
|
+
spinner.succeed(chalk25.green(`Loaded ${runs.length} run(s)`));
|
|
9171
9272
|
if (runs.length === 0) {
|
|
9172
|
-
console.log(
|
|
9273
|
+
console.log(chalk25.yellow("\nNo telemetry runs found"));
|
|
9173
9274
|
return;
|
|
9174
9275
|
}
|
|
9175
9276
|
console.log();
|
|
9176
9277
|
const table = new Table({
|
|
9177
9278
|
head: [
|
|
9178
|
-
|
|
9179
|
-
|
|
9180
|
-
|
|
9181
|
-
|
|
9182
|
-
|
|
9279
|
+
chalk25.cyan("Run ID"),
|
|
9280
|
+
chalk25.cyan("Start Time"),
|
|
9281
|
+
chalk25.cyan("Duration"),
|
|
9282
|
+
chalk25.cyan("Events"),
|
|
9283
|
+
chalk25.cyan("Categories")
|
|
9183
9284
|
],
|
|
9184
9285
|
colWidths: [38, 20, 12, 10, 30]
|
|
9185
9286
|
});
|
|
@@ -9195,13 +9296,13 @@ async function runsCommand(options) {
|
|
|
9195
9296
|
}
|
|
9196
9297
|
console.log(table.toString());
|
|
9197
9298
|
} catch (err) {
|
|
9198
|
-
spinner.fail(
|
|
9299
|
+
spinner.fail(chalk25.red(`Failed to load runs: ${err.message}`));
|
|
9199
9300
|
process.exit(1);
|
|
9200
9301
|
}
|
|
9201
9302
|
}
|
|
9202
9303
|
async function showCommand(runId) {
|
|
9203
9304
|
if (!isValidUuid(runId)) {
|
|
9204
|
-
console.error(
|
|
9305
|
+
console.error(chalk25.red(`Invalid run ID format: ${runId}. Must be valid UUID.`));
|
|
9205
9306
|
process.exit(1);
|
|
9206
9307
|
}
|
|
9207
9308
|
const spinner = ora6(`Loading events for run ${runId}...`).start();
|
|
@@ -9213,28 +9314,28 @@ async function showCommand(runId) {
|
|
|
9213
9314
|
const events = await backend.query({ runId });
|
|
9214
9315
|
await backend.close();
|
|
9215
9316
|
if (events.length === 0) {
|
|
9216
|
-
spinner.fail(
|
|
9317
|
+
spinner.fail(chalk25.yellow(`No events found for run ${runId}`));
|
|
9217
9318
|
return;
|
|
9218
9319
|
}
|
|
9219
|
-
spinner.succeed(
|
|
9320
|
+
spinner.succeed(chalk25.green(`Loaded ${events.length} event(s) for run ${runId}`));
|
|
9220
9321
|
console.log();
|
|
9221
|
-
console.log(
|
|
9222
|
-
console.log(
|
|
9322
|
+
console.log(chalk25.bold(`Events for run ${runId}`));
|
|
9323
|
+
console.log(chalk25.gray(`Total events: ${events.length}`));
|
|
9223
9324
|
console.log();
|
|
9224
9325
|
for (const event of events) {
|
|
9225
9326
|
const timestamp = formatTimestamp(event.timestamp);
|
|
9226
|
-
const category =
|
|
9227
|
-
const eventName =
|
|
9327
|
+
const category = chalk25.cyan(`[${event.category}]`);
|
|
9328
|
+
const eventName = chalk25.bold(event.event);
|
|
9228
9329
|
const dataStr = Object.keys(event.data).length > 0 ? JSON.stringify(event.data, null, 2) : "";
|
|
9229
|
-
console.log(`${
|
|
9330
|
+
console.log(`${chalk25.gray(timestamp)} ${category} ${eventName}`);
|
|
9230
9331
|
if (dataStr) {
|
|
9231
|
-
const grayData = dataStr.split("\n").map((line) =>
|
|
9332
|
+
const grayData = dataStr.split("\n").map((line) => chalk25.gray(line)).join("\n");
|
|
9232
9333
|
console.log(grayData);
|
|
9233
9334
|
}
|
|
9234
9335
|
console.log();
|
|
9235
9336
|
}
|
|
9236
9337
|
} catch (err) {
|
|
9237
|
-
spinner.fail(
|
|
9338
|
+
spinner.fail(chalk25.red(`Failed to load events: ${err.message}`));
|
|
9238
9339
|
process.exit(1);
|
|
9239
9340
|
}
|
|
9240
9341
|
}
|
|
@@ -9254,7 +9355,7 @@ function exportCsv(events) {
|
|
|
9254
9355
|
}
|
|
9255
9356
|
async function exportCommand(runId, options) {
|
|
9256
9357
|
if (!isValidUuid(runId)) {
|
|
9257
|
-
console.error(
|
|
9358
|
+
console.error(chalk25.red(`Invalid run ID format: ${runId}. Must be valid UUID.`));
|
|
9258
9359
|
process.exit(1);
|
|
9259
9360
|
}
|
|
9260
9361
|
const format = options.format ?? "json";
|
|
@@ -9267,20 +9368,20 @@ async function exportCommand(runId, options) {
|
|
|
9267
9368
|
const events = await backend.query({ runId });
|
|
9268
9369
|
await backend.close();
|
|
9269
9370
|
if (events.length === 0) {
|
|
9270
|
-
spinner.fail(
|
|
9371
|
+
spinner.fail(chalk25.yellow(`No events found for run ${runId}`));
|
|
9271
9372
|
return;
|
|
9272
9373
|
}
|
|
9273
9374
|
const data = format === "json" ? exportJson(events) : exportCsv(events);
|
|
9274
9375
|
if (options.output) {
|
|
9275
9376
|
writeFileSync5(options.output, data, "utf-8");
|
|
9276
|
-
spinner.succeed(
|
|
9377
|
+
spinner.succeed(chalk25.green(`Exported ${events.length} events to ${options.output}`));
|
|
9277
9378
|
} else {
|
|
9278
|
-
spinner.succeed(
|
|
9379
|
+
spinner.succeed(chalk25.green(`Exported ${events.length} events`));
|
|
9279
9380
|
console.log();
|
|
9280
9381
|
console.log(data);
|
|
9281
9382
|
}
|
|
9282
9383
|
} catch (err) {
|
|
9283
|
-
spinner.fail(
|
|
9384
|
+
spinner.fail(chalk25.red(`Failed to export run: ${err.message}`));
|
|
9284
9385
|
process.exit(1);
|
|
9285
9386
|
}
|
|
9286
9387
|
}
|
|
@@ -9296,9 +9397,9 @@ async function pruneCommand(options) {
|
|
|
9296
9397
|
const olderThan = Date.now() - days * 24 * 60 * 60 * 1e3;
|
|
9297
9398
|
const deleted = await backend.prune(olderThan);
|
|
9298
9399
|
await backend.close();
|
|
9299
|
-
spinner.succeed(
|
|
9400
|
+
spinner.succeed(chalk25.green(`Pruned ${deleted} event(s) older than ${days} days`));
|
|
9300
9401
|
} catch (err) {
|
|
9301
|
-
spinner.fail(
|
|
9402
|
+
spinner.fail(chalk25.red(`Failed to prune events: ${err.message}`));
|
|
9302
9403
|
process.exit(1);
|
|
9303
9404
|
}
|
|
9304
9405
|
}
|
|
@@ -9316,9 +9417,9 @@ async function enableCommand() {
|
|
|
9316
9417
|
config.telemetry.enabled = true;
|
|
9317
9418
|
writeFileSync5(configPath, JSON.stringify(config, null, 2), "utf-8");
|
|
9318
9419
|
const scope = localConfigDir ? "local" : "global";
|
|
9319
|
-
spinner.succeed(
|
|
9420
|
+
spinner.succeed(chalk25.green(`Telemetry enabled (${scope} config)`));
|
|
9320
9421
|
} catch (err) {
|
|
9321
|
-
spinner.fail(
|
|
9422
|
+
spinner.fail(chalk25.red(`Failed to enable telemetry: ${err.message}`));
|
|
9322
9423
|
process.exit(1);
|
|
9323
9424
|
}
|
|
9324
9425
|
}
|
|
@@ -9336,9 +9437,9 @@ async function disableCommand() {
|
|
|
9336
9437
|
config.telemetry.enabled = false;
|
|
9337
9438
|
writeFileSync5(configPath, JSON.stringify(config, null, 2), "utf-8");
|
|
9338
9439
|
const scope = localConfigDir ? "local" : "global";
|
|
9339
|
-
spinner.succeed(
|
|
9440
|
+
spinner.succeed(chalk25.green(`Telemetry disabled (${scope} config)`));
|
|
9340
9441
|
} catch (err) {
|
|
9341
|
-
spinner.fail(
|
|
9442
|
+
spinner.fail(chalk25.red(`Failed to disable telemetry: ${err.message}`));
|
|
9342
9443
|
process.exit(1);
|
|
9343
9444
|
}
|
|
9344
9445
|
}
|
|
@@ -9356,7 +9457,7 @@ function registerTelemetryCommand(program2) {
|
|
|
9356
9457
|
}
|
|
9357
9458
|
|
|
9358
9459
|
// src/commands/analyze.ts
|
|
9359
|
-
import
|
|
9460
|
+
import chalk26 from "chalk";
|
|
9360
9461
|
import ora7 from "ora";
|
|
9361
9462
|
|
|
9362
9463
|
// src/telemetry-path.ts
|
|
@@ -9422,8 +9523,8 @@ async function getBackend() {
|
|
|
9422
9523
|
}
|
|
9423
9524
|
function checkTelemetryEnabled(config) {
|
|
9424
9525
|
if (!config.telemetry?.enabled) {
|
|
9425
|
-
console.log(
|
|
9426
|
-
console.log(
|
|
9526
|
+
console.log(chalk26.yellow("\nTelemetry is disabled. Enable with:"));
|
|
9527
|
+
console.log(chalk26.cyan(" reygent telemetry enable\n"));
|
|
9427
9528
|
process.exit(1);
|
|
9428
9529
|
}
|
|
9429
9530
|
}
|
|
@@ -9439,27 +9540,27 @@ async function analyzeFailures(options) {
|
|
|
9439
9540
|
const pipelineEvents = filterEvents(allEvents, { event: Events.PIPELINE_END });
|
|
9440
9541
|
await backend.close();
|
|
9441
9542
|
if (errorEvents.length === 0) {
|
|
9442
|
-
spinner.succeed(
|
|
9443
|
-
console.log(
|
|
9543
|
+
spinner.succeed(chalk26.green("No failures found"));
|
|
9544
|
+
console.log(chalk26.yellow("\nNo error events in telemetry data"));
|
|
9444
9545
|
return;
|
|
9445
9546
|
}
|
|
9446
9547
|
const totalRuns = new Set(pipelineEvents.map((e) => e.runId)).size;
|
|
9447
9548
|
const days = Math.floor((Date.now() - since) / (24 * 60 * 60 * 1e3));
|
|
9448
|
-
spinner.succeed(
|
|
9549
|
+
spinner.succeed(chalk26.green(`Analyzed ${errorEvents.length} error(s) from ${totalRuns} run(s)`));
|
|
9449
9550
|
console.log();
|
|
9450
|
-
console.log(
|
|
9551
|
+
console.log(chalk26.bold(`Failure Analysis (last ${days} days, ${totalRuns} runs)`));
|
|
9451
9552
|
console.log();
|
|
9452
9553
|
const patternGroups = groupBy(errorEvents, (e) => e.event);
|
|
9453
9554
|
const sortedPatterns = Array.from(patternGroups.entries()).sort((a, b) => b[1].length - a[1].length);
|
|
9454
9555
|
const limit = options.limit ? Number.parseInt(options.limit, 10) : sortedPatterns.length;
|
|
9455
9556
|
const topPatterns = sortedPatterns.slice(0, limit);
|
|
9456
|
-
console.log(
|
|
9557
|
+
console.log(chalk26.bold("Top Failure Patterns:"));
|
|
9457
9558
|
console.log();
|
|
9458
9559
|
for (let i = 0; i < topPatterns.length; i++) {
|
|
9459
9560
|
const [eventName, events] = topPatterns[i];
|
|
9460
9561
|
const agentGroups = groupBy(events, (e) => e.data.agent || "unknown");
|
|
9461
9562
|
const mostRecent = events.reduce((a, b) => a.timestamp > b.timestamp ? a : b);
|
|
9462
|
-
console.log(
|
|
9563
|
+
console.log(chalk26.cyan(`${i + 1}. ${eventName}`) + chalk26.gray(` (${events.length} occurrences)`));
|
|
9463
9564
|
const agentSummary = Array.from(agentGroups.entries()).map(([agent, events2]) => `${agent} (${events2.length})`).join(", ");
|
|
9464
9565
|
console.log(` Agents: ${agentSummary}`);
|
|
9465
9566
|
const messages = events.map((e) => e.data.message).filter(Boolean);
|
|
@@ -9470,7 +9571,7 @@ async function analyzeFailures(options) {
|
|
|
9470
9571
|
console.log(` Most recent: run ${mostRecent.runId.substring(0, 8)} (${formatRelativeTime(mostRecent.timestamp)})`);
|
|
9471
9572
|
console.log();
|
|
9472
9573
|
}
|
|
9473
|
-
console.log(
|
|
9574
|
+
console.log(chalk26.bold("Recommendations:"));
|
|
9474
9575
|
const recommendations = [];
|
|
9475
9576
|
const parseErrors = errorEvents.filter((e) => e.event === Events.ERROR_PARSE);
|
|
9476
9577
|
if (parseErrors.length > 0) {
|
|
@@ -9496,7 +9597,7 @@ async function analyzeFailures(options) {
|
|
|
9496
9597
|
}
|
|
9497
9598
|
}
|
|
9498
9599
|
if (recommendations.length === 0) {
|
|
9499
|
-
console.log(
|
|
9600
|
+
console.log(chalk26.gray(" No specific recommendations"));
|
|
9500
9601
|
} else {
|
|
9501
9602
|
for (const rec of recommendations) {
|
|
9502
9603
|
console.log(rec);
|
|
@@ -9510,7 +9611,7 @@ async function analyzeFailures(options) {
|
|
|
9510
9611
|
const patterns = analyzeFailurePatterns(analysisBackend, since);
|
|
9511
9612
|
await analysisBackend.close();
|
|
9512
9613
|
if (patterns.length === 0) {
|
|
9513
|
-
updateSpinner.info(
|
|
9614
|
+
updateSpinner.info(chalk26.yellow("No recurring patterns to add"));
|
|
9514
9615
|
} else {
|
|
9515
9616
|
let addedCount = 0;
|
|
9516
9617
|
const limit2 = options.limit ? Number.parseInt(options.limit, 10) : 5;
|
|
@@ -9524,13 +9625,13 @@ async function analyzeFailures(options) {
|
|
|
9524
9625
|
addedCount++;
|
|
9525
9626
|
}
|
|
9526
9627
|
}
|
|
9527
|
-
updateSpinner.succeed(
|
|
9528
|
-
console.log(
|
|
9628
|
+
updateSpinner.succeed(chalk26.green(`Added ${addedCount} failure pattern(s) to knowledge base`));
|
|
9629
|
+
console.log(chalk26.gray(` See .reygent/knowledge/common-failures.md`));
|
|
9529
9630
|
console.log();
|
|
9530
9631
|
}
|
|
9531
9632
|
} catch (err) {
|
|
9532
9633
|
const errMsg = err instanceof Error ? err.message : String(err);
|
|
9533
|
-
updateSpinner.fail(
|
|
9634
|
+
updateSpinner.fail(chalk26.red(`Failed to update knowledge: ${errMsg}`));
|
|
9534
9635
|
if (process.env.REYGENT_DEBUG === "1" || process.env.REYGENT_DEBUG === "telemetry") {
|
|
9535
9636
|
console.error("[debug:telemetry] analyzeFailures knowledge update error:", err);
|
|
9536
9637
|
}
|
|
@@ -9538,7 +9639,7 @@ async function analyzeFailures(options) {
|
|
|
9538
9639
|
}
|
|
9539
9640
|
} catch (err) {
|
|
9540
9641
|
const errMsg = err instanceof Error ? err.message : String(err);
|
|
9541
|
-
spinner.fail(
|
|
9642
|
+
spinner.fail(chalk26.red(`Failed to analyze failures: ${errMsg}`));
|
|
9542
9643
|
if (process.env.REYGENT_DEBUG === "1" || process.env.REYGENT_DEBUG === "telemetry") {
|
|
9543
9644
|
console.error("[debug:telemetry] analyzeFailures error:", err);
|
|
9544
9645
|
}
|
|
@@ -9560,14 +9661,14 @@ async function analyzeSuccess(options) {
|
|
|
9560
9661
|
const successfulRuns = pipelineEvents.filter((e) => e.data.success === true);
|
|
9561
9662
|
const days = Math.floor((Date.now() - since) / (24 * 60 * 60 * 1e3));
|
|
9562
9663
|
if (successfulRuns.length === 0) {
|
|
9563
|
-
spinner.succeed(
|
|
9664
|
+
spinner.succeed(chalk26.yellow("No successful runs found"));
|
|
9564
9665
|
return;
|
|
9565
9666
|
}
|
|
9566
|
-
spinner.succeed(
|
|
9667
|
+
spinner.succeed(chalk26.green(`Analyzed ${successfulRuns.length} successful run(s)`));
|
|
9567
9668
|
console.log();
|
|
9568
|
-
console.log(
|
|
9669
|
+
console.log(chalk26.bold(`Success Analysis (last ${days} days, ${successfulRuns.length} successful runs)`));
|
|
9569
9670
|
console.log();
|
|
9570
|
-
console.log(
|
|
9671
|
+
console.log(chalk26.bold("Agent Performance:"));
|
|
9571
9672
|
console.log();
|
|
9572
9673
|
const agentStats = /* @__PURE__ */ new Map();
|
|
9573
9674
|
for (const spawn4 of agentSpawnEvents) {
|
|
@@ -9609,7 +9710,7 @@ async function analyzeSuccess(options) {
|
|
|
9609
9710
|
const stageAgents = new Set(stageEvents.map((e) => e.data.agent));
|
|
9610
9711
|
if (!stageAgents.has(agent)) continue;
|
|
9611
9712
|
}
|
|
9612
|
-
console.log(
|
|
9713
|
+
console.log(chalk26.cyan(`${agent}:`));
|
|
9613
9714
|
console.log(` Runs: ${stats.completions}`);
|
|
9614
9715
|
console.log(` Success rate: ${formatPercent(successRate)} (${stats.successes} success, ${stats.completions - stats.successes} failures)`);
|
|
9615
9716
|
console.log(` Avg duration: ${formatDuration3(avgDuration)}`);
|
|
@@ -9617,7 +9718,7 @@ async function analyzeSuccess(options) {
|
|
|
9617
9718
|
console.log(` Model distribution: ${modelDist}`);
|
|
9618
9719
|
console.log();
|
|
9619
9720
|
}
|
|
9620
|
-
console.log(
|
|
9721
|
+
console.log(chalk26.bold("Recommendations:"));
|
|
9621
9722
|
const recommendations = [];
|
|
9622
9723
|
const sortedAgents = Array.from(agentStats.entries()).filter(([_, stats]) => stats.completions > 0).map(([agent, stats]) => ({
|
|
9623
9724
|
agent,
|
|
@@ -9631,7 +9732,7 @@ async function analyzeSuccess(options) {
|
|
|
9631
9732
|
}
|
|
9632
9733
|
}
|
|
9633
9734
|
if (recommendations.length === 0) {
|
|
9634
|
-
console.log(
|
|
9735
|
+
console.log(chalk26.gray(" No specific recommendations"));
|
|
9635
9736
|
} else {
|
|
9636
9737
|
for (const rec of recommendations) {
|
|
9637
9738
|
console.log(rec);
|
|
@@ -9646,7 +9747,7 @@ async function analyzeSuccess(options) {
|
|
|
9646
9747
|
const patterns = analyzeSuccessPatterns(analysisBackend, since, minRate);
|
|
9647
9748
|
await analysisBackend.close();
|
|
9648
9749
|
if (patterns.length === 0) {
|
|
9649
|
-
updateSpinner.info(
|
|
9750
|
+
updateSpinner.info(chalk26.yellow("No high-success patterns to add"));
|
|
9650
9751
|
} else {
|
|
9651
9752
|
let addedCount = 0;
|
|
9652
9753
|
const limit = 5;
|
|
@@ -9657,13 +9758,13 @@ async function analyzeSuccess(options) {
|
|
|
9657
9758
|
});
|
|
9658
9759
|
addedCount++;
|
|
9659
9760
|
}
|
|
9660
|
-
updateSpinner.succeed(
|
|
9661
|
-
console.log(
|
|
9761
|
+
updateSpinner.succeed(chalk26.green(`Added ${addedCount} success pattern(s) to knowledge base`));
|
|
9762
|
+
console.log(chalk26.gray(` See .reygent/knowledge/success-patterns.md`));
|
|
9662
9763
|
console.log();
|
|
9663
9764
|
}
|
|
9664
9765
|
} catch (err) {
|
|
9665
9766
|
const errMsg = err instanceof Error ? err.message : String(err);
|
|
9666
|
-
updateSpinner.fail(
|
|
9767
|
+
updateSpinner.fail(chalk26.red(`Failed to update knowledge: ${errMsg}`));
|
|
9667
9768
|
if (process.env.REYGENT_DEBUG === "1" || process.env.REYGENT_DEBUG === "telemetry") {
|
|
9668
9769
|
console.error("[debug:telemetry] analyzeSuccess knowledge update error:", err);
|
|
9669
9770
|
}
|
|
@@ -9671,7 +9772,7 @@ async function analyzeSuccess(options) {
|
|
|
9671
9772
|
}
|
|
9672
9773
|
} catch (err) {
|
|
9673
9774
|
const errMsg = err instanceof Error ? err.message : String(err);
|
|
9674
|
-
spinner.fail(
|
|
9775
|
+
spinner.fail(chalk26.red(`Failed to analyze success: ${errMsg}`));
|
|
9675
9776
|
if (process.env.REYGENT_DEBUG === "1" || process.env.REYGENT_DEBUG === "telemetry") {
|
|
9676
9777
|
console.error("[debug:telemetry] analyzeSuccess error:", err);
|
|
9677
9778
|
}
|
|
@@ -9690,18 +9791,18 @@ async function analyzeCosts(options) {
|
|
|
9690
9791
|
const pipelineEvents = filterEvents(allEvents, { event: Events.PIPELINE_END });
|
|
9691
9792
|
await backend.close();
|
|
9692
9793
|
if (costEvents.length === 0) {
|
|
9693
|
-
spinner.succeed(
|
|
9694
|
-
console.log(
|
|
9695
|
-
console.log(
|
|
9794
|
+
spinner.succeed(chalk26.yellow("No cost data found"));
|
|
9795
|
+
console.log(chalk26.gray("\nEnable verbose telemetry to track costs:"));
|
|
9796
|
+
console.log(chalk26.cyan(" reygent run --telemetry-level verbose\n"));
|
|
9696
9797
|
return;
|
|
9697
9798
|
}
|
|
9698
9799
|
const totalRuns = new Set(pipelineEvents.map((e) => e.runId)).size;
|
|
9699
9800
|
const successfulRuns = pipelineEvents.filter((e) => e.data.success === true).length;
|
|
9700
9801
|
const failedRuns = totalRuns - successfulRuns;
|
|
9701
9802
|
const days = Math.floor((Date.now() - since) / (24 * 60 * 60 * 1e3));
|
|
9702
|
-
spinner.succeed(
|
|
9803
|
+
spinner.succeed(chalk26.green(`Analyzed ${costEvents.length} cost event(s)`));
|
|
9703
9804
|
console.log();
|
|
9704
|
-
console.log(
|
|
9805
|
+
console.log(chalk26.bold(`Cost Analysis (last ${days} days, ${totalRuns} runs)`));
|
|
9705
9806
|
console.log();
|
|
9706
9807
|
const totalCost = costEvents.reduce((sum, e) => sum + e.data.costUsd, 0);
|
|
9707
9808
|
const successRunIds = new Set(
|
|
@@ -9709,12 +9810,12 @@ async function analyzeCosts(options) {
|
|
|
9709
9810
|
);
|
|
9710
9811
|
const successCost = costEvents.filter((e) => successRunIds.has(e.runId)).reduce((sum, e) => sum + e.data.costUsd, 0);
|
|
9711
9812
|
const failedCost = totalCost - successCost;
|
|
9712
|
-
console.log(
|
|
9813
|
+
console.log(chalk26.bold("Total Spend:"), chalk26.cyan(formatCost2(totalCost)));
|
|
9713
9814
|
console.log(`Successful runs: ${formatCost2(successCost)} (${formatPercent(successCost / totalCost)})`);
|
|
9714
9815
|
console.log(`Failed runs: ${formatCost2(failedCost)} (${formatPercent(failedCost / totalCost)} - wasted)`);
|
|
9715
9816
|
console.log();
|
|
9716
9817
|
if (options.byAgent) {
|
|
9717
|
-
console.log(
|
|
9818
|
+
console.log(chalk26.bold("Cost by Agent:"));
|
|
9718
9819
|
const agentCosts = /* @__PURE__ */ new Map();
|
|
9719
9820
|
for (const event of costEvents) {
|
|
9720
9821
|
const agent = event.data.agent || "unknown";
|
|
@@ -9732,7 +9833,7 @@ async function analyzeCosts(options) {
|
|
|
9732
9833
|
}
|
|
9733
9834
|
console.log();
|
|
9734
9835
|
} else {
|
|
9735
|
-
console.log(
|
|
9836
|
+
console.log(chalk26.bold("Cost by Stage:"));
|
|
9736
9837
|
const stageCosts = /* @__PURE__ */ new Map();
|
|
9737
9838
|
for (const event of costEvents) {
|
|
9738
9839
|
const stage = event.data.stage ?? "unknown";
|
|
@@ -9751,7 +9852,7 @@ async function analyzeCosts(options) {
|
|
|
9751
9852
|
console.log();
|
|
9752
9853
|
}
|
|
9753
9854
|
if (failedRuns > 0 && options.showRuns) {
|
|
9754
|
-
console.log(
|
|
9855
|
+
console.log(chalk26.bold("Expensive Failures (top 3):"));
|
|
9755
9856
|
const failedRunIds = new Set(
|
|
9756
9857
|
pipelineEvents.filter((e) => e.data.success !== true).map((e) => e.runId)
|
|
9757
9858
|
);
|
|
@@ -9776,7 +9877,7 @@ async function analyzeCosts(options) {
|
|
|
9776
9877
|
}
|
|
9777
9878
|
console.log();
|
|
9778
9879
|
}
|
|
9779
|
-
console.log(
|
|
9880
|
+
console.log(chalk26.bold("Optimization Opportunities:"));
|
|
9780
9881
|
const recommendations = [];
|
|
9781
9882
|
if (failedCost > 0) {
|
|
9782
9883
|
const wastePercent = failedCost / totalCost * 100;
|
|
@@ -9795,7 +9896,7 @@ async function analyzeCosts(options) {
|
|
|
9795
9896
|
Potential Savings: ${formatCost2(monthlySavings)}/month (${formatPercent(potentialSavings / totalCost)})`);
|
|
9796
9897
|
}
|
|
9797
9898
|
if (recommendations.length === 0) {
|
|
9798
|
-
console.log(
|
|
9899
|
+
console.log(chalk26.gray(" No specific recommendations"));
|
|
9799
9900
|
} else {
|
|
9800
9901
|
for (const rec of recommendations) {
|
|
9801
9902
|
console.log(rec);
|
|
@@ -9803,7 +9904,7 @@ Potential Savings: ${formatCost2(monthlySavings)}/month (${formatPercent(potenti
|
|
|
9803
9904
|
}
|
|
9804
9905
|
console.log();
|
|
9805
9906
|
} catch (err) {
|
|
9806
|
-
spinner.fail(
|
|
9907
|
+
spinner.fail(chalk26.red(`Failed to analyze costs: ${err.message}`));
|
|
9807
9908
|
process.exit(1);
|
|
9808
9909
|
}
|
|
9809
9910
|
}
|
|
@@ -9821,13 +9922,13 @@ async function analyzeAgents(options) {
|
|
|
9821
9922
|
const costEvents = filterEvents(allEvents, { event: Events.USAGE_COST });
|
|
9822
9923
|
await backend.close();
|
|
9823
9924
|
if (agentSpawnEvents.length === 0) {
|
|
9824
|
-
spinner.succeed(
|
|
9925
|
+
spinner.succeed(chalk26.yellow("No agent data found"));
|
|
9825
9926
|
return;
|
|
9826
9927
|
}
|
|
9827
9928
|
const days = Math.floor((Date.now() - since) / (24 * 60 * 60 * 1e3));
|
|
9828
|
-
spinner.succeed(
|
|
9929
|
+
spinner.succeed(chalk26.green(`Analyzed ${agentSpawnEvents.length} agent spawn(s)`));
|
|
9829
9930
|
console.log();
|
|
9830
|
-
console.log(
|
|
9931
|
+
console.log(chalk26.bold(`Agent Performance Analysis (last ${days} days)`));
|
|
9831
9932
|
console.log();
|
|
9832
9933
|
const agentStats = /* @__PURE__ */ new Map();
|
|
9833
9934
|
for (const spawn4 of agentSpawnEvents) {
|
|
@@ -9881,8 +9982,8 @@ async function analyzeAgents(options) {
|
|
|
9881
9982
|
if (options.agent) {
|
|
9882
9983
|
const requestedStats = agentStats.get(options.agent);
|
|
9883
9984
|
if (!requestedStats) {
|
|
9884
|
-
spinner.warn(
|
|
9885
|
-
console.log(
|
|
9985
|
+
spinner.warn(chalk26.yellow(`Agent "${options.agent}" not found in telemetry data`));
|
|
9986
|
+
console.log(chalk26.gray(`
|
|
9886
9987
|
Available agents: ${Array.from(agentStats.keys()).join(", ")}`));
|
|
9887
9988
|
return;
|
|
9888
9989
|
}
|
|
@@ -9894,7 +9995,7 @@ Available agents: ${Array.from(agentStats.keys()).join(", ")}`));
|
|
|
9894
9995
|
const successRate = stats.completions > 0 ? stats.successes / stats.completions : 0;
|
|
9895
9996
|
const avgDuration = stats.completions > 0 ? stats.totalDuration / stats.completions : 0;
|
|
9896
9997
|
const avgCost = stats.completions > 0 ? stats.totalCost / stats.completions : 0;
|
|
9897
|
-
console.log(
|
|
9998
|
+
console.log(chalk26.bold.cyan(agent + ":"));
|
|
9898
9999
|
console.log(` Runs: ${stats.completions}`);
|
|
9899
10000
|
console.log(` Success rate: ${formatPercent(successRate)} (${stats.successes} success, ${stats.failures} failures)`);
|
|
9900
10001
|
console.log(` Avg duration: ${formatDuration3(avgDuration)}`);
|
|
@@ -9944,7 +10045,7 @@ Available agents: ${Array.from(agentStats.keys()).join(", ")}`));
|
|
|
9944
10045
|
}
|
|
9945
10046
|
console.log();
|
|
9946
10047
|
}
|
|
9947
|
-
console.log(
|
|
10048
|
+
console.log(chalk26.bold("Recommendations:"));
|
|
9948
10049
|
const recommendations = [];
|
|
9949
10050
|
for (const [agent, stats] of agentStats) {
|
|
9950
10051
|
if (stats.completions > 0) {
|
|
@@ -9963,7 +10064,7 @@ Available agents: ${Array.from(agentStats.keys()).join(", ")}`));
|
|
|
9963
10064
|
recommendations.push(`\u2022 ${sortedBySuccess[0].agent}: Best performer (${formatPercent(sortedBySuccess[0].successRate)} success)`);
|
|
9964
10065
|
}
|
|
9965
10066
|
if (recommendations.length === 0) {
|
|
9966
|
-
console.log(
|
|
10067
|
+
console.log(chalk26.gray(" No specific recommendations"));
|
|
9967
10068
|
} else {
|
|
9968
10069
|
for (const rec of recommendations) {
|
|
9969
10070
|
console.log(rec);
|
|
@@ -9971,7 +10072,7 @@ Available agents: ${Array.from(agentStats.keys()).join(", ")}`));
|
|
|
9971
10072
|
}
|
|
9972
10073
|
console.log();
|
|
9973
10074
|
} catch (err) {
|
|
9974
|
-
spinner.fail(
|
|
10075
|
+
spinner.fail(chalk26.red(`Failed to analyze agents: ${err.message}`));
|
|
9975
10076
|
process.exit(1);
|
|
9976
10077
|
}
|
|
9977
10078
|
}
|
|
@@ -9984,7 +10085,7 @@ function registerAnalyzeCommand(program2) {
|
|
|
9984
10085
|
}
|
|
9985
10086
|
|
|
9986
10087
|
// src/commands/last.ts
|
|
9987
|
-
import
|
|
10088
|
+
import chalk27 from "chalk";
|
|
9988
10089
|
import ora8 from "ora";
|
|
9989
10090
|
import Table2 from "cli-table3";
|
|
9990
10091
|
function formatTimestamp2(timestamp) {
|
|
@@ -10007,8 +10108,8 @@ function formatCost3(usd) {
|
|
|
10007
10108
|
}
|
|
10008
10109
|
function checkTelemetryEnabled2(config) {
|
|
10009
10110
|
if (!config.telemetry?.enabled) {
|
|
10010
|
-
console.log(
|
|
10011
|
-
console.log(
|
|
10111
|
+
console.log(chalk27.yellow("\nTelemetry disabled. Enable with:"));
|
|
10112
|
+
console.log(chalk27.cyan(" reygent telemetry enable\n"));
|
|
10012
10113
|
process.exit(1);
|
|
10013
10114
|
}
|
|
10014
10115
|
}
|
|
@@ -10025,11 +10126,11 @@ function displaySummary(runId, events) {
|
|
|
10025
10126
|
const totalCost = costEvents.reduce((sum, e) => sum + e.data.costUsd, 0);
|
|
10026
10127
|
const agents = [...new Set(agentSpawns.map((e) => e.data.agent))];
|
|
10027
10128
|
console.log();
|
|
10028
|
-
console.log(
|
|
10129
|
+
console.log(chalk27.bold("Latest Run Summary"));
|
|
10029
10130
|
console.log();
|
|
10030
|
-
console.log(` Run ID: ${
|
|
10031
|
-
console.log(` Status: ${success ?
|
|
10032
|
-
console.log(` Started: ${
|
|
10131
|
+
console.log(` Run ID: ${chalk27.cyan(runId.substring(0, 8))}`);
|
|
10132
|
+
console.log(` Status: ${success ? chalk27.green("Success") : chalk27.red("Failed")}`);
|
|
10133
|
+
console.log(` Started: ${chalk27.gray(formatTimestamp2(startTime))}`);
|
|
10033
10134
|
console.log(` Duration: ${formatDuration4(duration)}`);
|
|
10034
10135
|
console.log(` Agents: ${agents.join(", ") || "none"}`);
|
|
10035
10136
|
if (totalCost > 0) {
|
|
@@ -10037,7 +10138,7 @@ function displaySummary(runId, events) {
|
|
|
10037
10138
|
}
|
|
10038
10139
|
if (errorEvents.length > 0) {
|
|
10039
10140
|
console.log();
|
|
10040
|
-
console.log(
|
|
10141
|
+
console.log(chalk27.red(` Errors: ${errorEvents.length} error(s)`));
|
|
10041
10142
|
const errorSummary = errorEvents.slice(0, 3).map((e) => {
|
|
10042
10143
|
const msg = e.data.message || e.event;
|
|
10043
10144
|
return ` \u2022 ${msg}`;
|
|
@@ -10051,14 +10152,14 @@ function displaySummary(runId, events) {
|
|
|
10051
10152
|
}
|
|
10052
10153
|
function displayVerbose(runId, events) {
|
|
10053
10154
|
console.log();
|
|
10054
|
-
console.log(
|
|
10155
|
+
console.log(chalk27.bold(`Detailed Event Log (${events.length} events)`));
|
|
10055
10156
|
console.log();
|
|
10056
10157
|
const table = new Table2({
|
|
10057
10158
|
head: [
|
|
10058
|
-
|
|
10059
|
-
|
|
10060
|
-
|
|
10061
|
-
|
|
10159
|
+
chalk27.cyan("Time"),
|
|
10160
|
+
chalk27.cyan("Category"),
|
|
10161
|
+
chalk27.cyan("Event"),
|
|
10162
|
+
chalk27.cyan("Details")
|
|
10062
10163
|
],
|
|
10063
10164
|
colWidths: [20, 15, 30, 50],
|
|
10064
10165
|
wordWrap: true
|
|
@@ -10067,10 +10168,10 @@ function displayVerbose(runId, events) {
|
|
|
10067
10168
|
const timestamp = formatTimestamp2(event.timestamp);
|
|
10068
10169
|
const details = Object.keys(event.data).length > 0 ? JSON.stringify(event.data).substring(0, 100) : "";
|
|
10069
10170
|
table.push([
|
|
10070
|
-
|
|
10171
|
+
chalk27.gray(timestamp),
|
|
10071
10172
|
event.category,
|
|
10072
10173
|
event.event,
|
|
10073
|
-
|
|
10174
|
+
chalk27.gray(details)
|
|
10074
10175
|
]);
|
|
10075
10176
|
}
|
|
10076
10177
|
console.log(table.toString());
|
|
@@ -10080,7 +10181,7 @@ function displayOutput(events) {
|
|
|
10080
10181
|
const pipelineEnd = events.find((e) => e.event === Events.PIPELINE_END);
|
|
10081
10182
|
const agentCompletes = events.filter((e) => e.event === Events.AGENT_COMPLETE);
|
|
10082
10183
|
console.log();
|
|
10083
|
-
console.log(
|
|
10184
|
+
console.log(chalk27.bold("Run Output"));
|
|
10084
10185
|
console.log();
|
|
10085
10186
|
if (pipelineEnd?.data.output) {
|
|
10086
10187
|
console.log(pipelineEnd.data.output);
|
|
@@ -10089,23 +10190,23 @@ function displayOutput(events) {
|
|
|
10089
10190
|
const agent = complete.data.agent;
|
|
10090
10191
|
const output = complete.data.output;
|
|
10091
10192
|
if (output) {
|
|
10092
|
-
console.log(
|
|
10193
|
+
console.log(chalk27.cyan(`[${agent}]`));
|
|
10093
10194
|
console.log(output);
|
|
10094
10195
|
console.log();
|
|
10095
10196
|
}
|
|
10096
10197
|
}
|
|
10097
10198
|
} else {
|
|
10098
|
-
console.log(
|
|
10199
|
+
console.log(chalk27.yellow("No output captured"));
|
|
10099
10200
|
}
|
|
10100
10201
|
console.log();
|
|
10101
10202
|
}
|
|
10102
10203
|
function displayErrors(events) {
|
|
10103
10204
|
const errorEvents = events.filter((e) => e.category === "error");
|
|
10104
10205
|
console.log();
|
|
10105
|
-
console.log(
|
|
10206
|
+
console.log(chalk27.bold(`Errors (${errorEvents.length})`));
|
|
10106
10207
|
console.log();
|
|
10107
10208
|
if (errorEvents.length === 0) {
|
|
10108
|
-
console.log(
|
|
10209
|
+
console.log(chalk27.green("No errors in this run"));
|
|
10109
10210
|
console.log();
|
|
10110
10211
|
return;
|
|
10111
10212
|
}
|
|
@@ -10113,10 +10214,10 @@ function displayErrors(events) {
|
|
|
10113
10214
|
const timestamp = formatTimestamp2(error.timestamp);
|
|
10114
10215
|
const message = error.data.message || "Unknown error";
|
|
10115
10216
|
const agent = error.data.agent || "unknown";
|
|
10116
|
-
console.log(
|
|
10217
|
+
console.log(chalk27.gray(timestamp) + chalk27.red(` [${error.event}]`) + ` ${agent}`);
|
|
10117
10218
|
console.log(` ${message}`);
|
|
10118
10219
|
if (error.data.stack) {
|
|
10119
|
-
console.log(
|
|
10220
|
+
console.log(chalk27.gray(` ${error.data.stack}`));
|
|
10120
10221
|
}
|
|
10121
10222
|
console.log();
|
|
10122
10223
|
}
|
|
@@ -10140,8 +10241,8 @@ async function lastCommandImpl(options, testBackend) {
|
|
|
10140
10241
|
}
|
|
10141
10242
|
const runs = await backend.listRuns();
|
|
10142
10243
|
if (runs.length === 0) {
|
|
10143
|
-
spinner.fail(
|
|
10144
|
-
console.log(
|
|
10244
|
+
spinner.fail(chalk27.yellow("No telemetry runs found"));
|
|
10245
|
+
console.log(chalk27.gray("\nRun a reygent command to generate telemetry data"));
|
|
10145
10246
|
if (!testBackend) {
|
|
10146
10247
|
await backend.close();
|
|
10147
10248
|
}
|
|
@@ -10152,7 +10253,7 @@ async function lastCommandImpl(options, testBackend) {
|
|
|
10152
10253
|
if (!testBackend) {
|
|
10153
10254
|
await backend.close();
|
|
10154
10255
|
}
|
|
10155
|
-
spinner.succeed(
|
|
10256
|
+
spinner.succeed(chalk27.green(`Loaded latest run: ${latestRun.runId.substring(0, 8)}`));
|
|
10156
10257
|
if (options.json) {
|
|
10157
10258
|
displayJson(latestRun.runId, events);
|
|
10158
10259
|
} else if (options.output) {
|
|
@@ -10165,7 +10266,7 @@ async function lastCommandImpl(options, testBackend) {
|
|
|
10165
10266
|
displaySummary(latestRun.runId, events);
|
|
10166
10267
|
}
|
|
10167
10268
|
} catch (err) {
|
|
10168
|
-
spinner.fail(
|
|
10269
|
+
spinner.fail(chalk27.red(`Failed to load latest run: ${err.message}`));
|
|
10169
10270
|
process.exit(1);
|
|
10170
10271
|
}
|
|
10171
10272
|
}
|
|
@@ -10179,7 +10280,7 @@ function registerLastCommand(program2) {
|
|
|
10179
10280
|
// src/commands/knowledge.ts
|
|
10180
10281
|
import { join as join12 } from "path";
|
|
10181
10282
|
import { execSync } from "child_process";
|
|
10182
|
-
import
|
|
10283
|
+
import chalk28 from "chalk";
|
|
10183
10284
|
import ora9 from "ora";
|
|
10184
10285
|
import Table3 from "cli-table3";
|
|
10185
10286
|
import { select as select7, confirm as confirm2 } from "@inquirer/prompts";
|
|
@@ -10222,22 +10323,22 @@ function registerKnowledgeCommand(program2) {
|
|
|
10222
10323
|
async function listCommand() {
|
|
10223
10324
|
const knowledgeDir = findKnowledgeDir();
|
|
10224
10325
|
if (!knowledgeDir) {
|
|
10225
|
-
console.log(
|
|
10326
|
+
console.log(chalk28.yellow("No .reygent/knowledge/ directory found."));
|
|
10226
10327
|
console.log(
|
|
10227
|
-
|
|
10328
|
+
chalk28.gray("Run from a project with .reygent/ or create one with:")
|
|
10228
10329
|
);
|
|
10229
|
-
console.log(
|
|
10330
|
+
console.log(chalk28.cyan(" reygent init"));
|
|
10230
10331
|
return;
|
|
10231
10332
|
}
|
|
10232
10333
|
const files = listKnowledgeFiles();
|
|
10233
10334
|
if (files.length === 0) {
|
|
10234
|
-
console.log(
|
|
10335
|
+
console.log(chalk28.yellow("No knowledge files found."));
|
|
10235
10336
|
return;
|
|
10236
10337
|
}
|
|
10237
|
-
console.log(
|
|
10338
|
+
console.log(chalk28.bold("\nKnowledge Files:"));
|
|
10238
10339
|
console.log();
|
|
10239
10340
|
const table = new Table3({
|
|
10240
|
-
head: [
|
|
10341
|
+
head: [chalk28.cyan("File"), chalk28.cyan("Type")],
|
|
10241
10342
|
colWidths: [40, 30]
|
|
10242
10343
|
});
|
|
10243
10344
|
for (const file of files) {
|
|
@@ -10246,13 +10347,13 @@ async function listCommand() {
|
|
|
10246
10347
|
}
|
|
10247
10348
|
console.log(table.toString());
|
|
10248
10349
|
console.log();
|
|
10249
|
-
console.log(
|
|
10250
|
-
console.log(
|
|
10350
|
+
console.log(chalk28.gray(`View file: ${chalk28.white("reygent knowledge show <file>")}`));
|
|
10351
|
+
console.log(chalk28.gray(`Search: ${chalk28.white("reygent knowledge search <query>")}`));
|
|
10251
10352
|
}
|
|
10252
10353
|
async function showCommand2(file) {
|
|
10253
10354
|
const knowledgeDir = findKnowledgeDir();
|
|
10254
10355
|
if (!knowledgeDir) {
|
|
10255
|
-
console.log(
|
|
10356
|
+
console.log(chalk28.red("No .reygent/knowledge/ directory found."));
|
|
10256
10357
|
process.exit(1);
|
|
10257
10358
|
}
|
|
10258
10359
|
const normalizedFile = file.endsWith(".md") ? file : `${file}.md`;
|
|
@@ -10260,24 +10361,24 @@ async function showCommand2(file) {
|
|
|
10260
10361
|
try {
|
|
10261
10362
|
const content = readMarkdown(filePath);
|
|
10262
10363
|
if (content === null) {
|
|
10263
|
-
console.log(
|
|
10264
|
-
console.log(
|
|
10364
|
+
console.log(chalk28.red(`Knowledge file validation failed: ${normalizedFile}`));
|
|
10365
|
+
console.log(chalk28.gray("File may contain suspicious content or be malformed."));
|
|
10265
10366
|
process.exit(1);
|
|
10266
10367
|
}
|
|
10267
10368
|
if (content === "") {
|
|
10268
|
-
console.log(
|
|
10269
|
-
console.log(
|
|
10369
|
+
console.log(chalk28.yellow(`Knowledge file is empty or not found: ${normalizedFile}`));
|
|
10370
|
+
console.log(chalk28.gray("Available files:"));
|
|
10270
10371
|
const files = listKnowledgeFiles();
|
|
10271
|
-
files.forEach((f) => console.log(
|
|
10372
|
+
files.forEach((f) => console.log(chalk28.gray(` - ${f}`)));
|
|
10272
10373
|
process.exit(1);
|
|
10273
10374
|
}
|
|
10274
|
-
console.log(
|
|
10375
|
+
console.log(chalk28.bold(`
|
|
10275
10376
|
${normalizedFile}
|
|
10276
10377
|
`));
|
|
10277
10378
|
console.log(content);
|
|
10278
10379
|
console.log();
|
|
10279
10380
|
} catch (err) {
|
|
10280
|
-
console.log(
|
|
10381
|
+
console.log(chalk28.red(`Failed to read ${normalizedFile}: ${err.message}`));
|
|
10281
10382
|
process.exit(1);
|
|
10282
10383
|
}
|
|
10283
10384
|
}
|
|
@@ -10286,45 +10387,45 @@ async function searchCommand(query) {
|
|
|
10286
10387
|
try {
|
|
10287
10388
|
const results = searchKnowledge(query);
|
|
10288
10389
|
if (results.length === 0) {
|
|
10289
|
-
spinner.fail(
|
|
10390
|
+
spinner.fail(chalk28.yellow("No matches found."));
|
|
10290
10391
|
return;
|
|
10291
10392
|
}
|
|
10292
|
-
spinner.succeed(
|
|
10393
|
+
spinner.succeed(chalk28.green(`Found ${results.length} match(es)`));
|
|
10293
10394
|
console.log();
|
|
10294
10395
|
for (const result of results) {
|
|
10295
|
-
console.log(
|
|
10296
|
-
console.log(
|
|
10297
|
-
console.log(
|
|
10396
|
+
console.log(chalk28.bold.cyan(`${result.file}`));
|
|
10397
|
+
console.log(chalk28.bold(` ${result.entry.title}`));
|
|
10398
|
+
console.log(chalk28.gray(` ${result.excerpt}`));
|
|
10298
10399
|
console.log();
|
|
10299
10400
|
}
|
|
10300
10401
|
} catch (err) {
|
|
10301
|
-
spinner.fail(
|
|
10402
|
+
spinner.fail(chalk28.red(`Search failed: ${err.message}`));
|
|
10302
10403
|
process.exit(1);
|
|
10303
10404
|
}
|
|
10304
10405
|
}
|
|
10305
10406
|
async function editCommand(file) {
|
|
10306
10407
|
const knowledgeDir = findKnowledgeDir();
|
|
10307
10408
|
if (!knowledgeDir) {
|
|
10308
|
-
console.log(
|
|
10409
|
+
console.log(chalk28.red("No .reygent/knowledge/ directory found."));
|
|
10309
10410
|
process.exit(1);
|
|
10310
10411
|
}
|
|
10311
10412
|
const normalizedFile = file.endsWith(".md") ? file : `${file}.md`;
|
|
10312
10413
|
const filePath = join12(knowledgeDir, normalizedFile);
|
|
10313
10414
|
const editor = process.env.EDITOR || "vi";
|
|
10314
|
-
console.log(
|
|
10415
|
+
console.log(chalk28.cyan(`Opening ${normalizedFile} in ${editor}...`));
|
|
10315
10416
|
try {
|
|
10316
10417
|
execSync(`${editor} "${filePath}"`, { stdio: "inherit" });
|
|
10317
|
-
console.log(
|
|
10418
|
+
console.log(chalk28.green("File saved."));
|
|
10318
10419
|
} catch (err) {
|
|
10319
|
-
console.log(
|
|
10420
|
+
console.log(chalk28.red(`Failed to open editor: ${err.message}`));
|
|
10320
10421
|
process.exit(1);
|
|
10321
10422
|
}
|
|
10322
10423
|
}
|
|
10323
10424
|
async function addFailureCommand(options) {
|
|
10324
10425
|
const knowledgeDir = findKnowledgeDir();
|
|
10325
10426
|
if (!knowledgeDir) {
|
|
10326
|
-
console.log(
|
|
10327
|
-
console.log(
|
|
10427
|
+
console.log(chalk28.red("No .reygent/knowledge/ directory found."));
|
|
10428
|
+
console.log(chalk28.gray("Run 'reygent init' to create knowledge directory."));
|
|
10328
10429
|
process.exit(1);
|
|
10329
10430
|
}
|
|
10330
10431
|
let issue = options.issue;
|
|
@@ -10339,7 +10440,7 @@ async function addFailureCommand(options) {
|
|
|
10339
10440
|
});
|
|
10340
10441
|
} catch (err) {
|
|
10341
10442
|
if (err instanceof InputTimeoutError) {
|
|
10342
|
-
console.log(
|
|
10443
|
+
console.log(chalk28.red("\n\u2717 Input timed out"));
|
|
10343
10444
|
process.exit(1);
|
|
10344
10445
|
}
|
|
10345
10446
|
throw err;
|
|
@@ -10353,7 +10454,7 @@ async function addFailureCommand(options) {
|
|
|
10353
10454
|
});
|
|
10354
10455
|
} catch (err) {
|
|
10355
10456
|
if (err instanceof InputTimeoutError) {
|
|
10356
|
-
console.log(
|
|
10457
|
+
console.log(chalk28.red("\n\u2717 Input timed out"));
|
|
10357
10458
|
process.exit(1);
|
|
10358
10459
|
}
|
|
10359
10460
|
throw err;
|
|
@@ -10378,7 +10479,7 @@ async function addFailureCommand(options) {
|
|
|
10378
10479
|
});
|
|
10379
10480
|
} catch (err) {
|
|
10380
10481
|
if (err instanceof InputTimeoutError) {
|
|
10381
|
-
console.log(
|
|
10482
|
+
console.log(chalk28.red("\n\u2717 Input timed out"));
|
|
10382
10483
|
process.exit(1);
|
|
10383
10484
|
}
|
|
10384
10485
|
throw err;
|
|
@@ -10392,15 +10493,15 @@ async function addFailureCommand(options) {
|
|
|
10392
10493
|
agent,
|
|
10393
10494
|
example
|
|
10394
10495
|
});
|
|
10395
|
-
console.log(
|
|
10396
|
-
console.log(
|
|
10397
|
-
console.log(
|
|
10496
|
+
console.log(chalk28.green("\u2713 Failure documented"));
|
|
10497
|
+
console.log(chalk28.gray(` File: common-failures.md`));
|
|
10498
|
+
console.log(chalk28.gray(` Agent: ${agent}`));
|
|
10398
10499
|
}
|
|
10399
10500
|
async function addPatternCommand(options) {
|
|
10400
10501
|
const knowledgeDir = findKnowledgeDir();
|
|
10401
10502
|
if (!knowledgeDir) {
|
|
10402
|
-
console.log(
|
|
10403
|
-
console.log(
|
|
10503
|
+
console.log(chalk28.red("No .reygent/knowledge/ directory found."));
|
|
10504
|
+
console.log(chalk28.gray("Run 'reygent init' to create knowledge directory."));
|
|
10404
10505
|
process.exit(1);
|
|
10405
10506
|
}
|
|
10406
10507
|
let description = options.description;
|
|
@@ -10414,7 +10515,7 @@ async function addPatternCommand(options) {
|
|
|
10414
10515
|
});
|
|
10415
10516
|
} catch (err) {
|
|
10416
10517
|
if (err instanceof InputTimeoutError) {
|
|
10417
|
-
console.log(
|
|
10518
|
+
console.log(chalk28.red("\n\u2717 Input timed out"));
|
|
10418
10519
|
process.exit(1);
|
|
10419
10520
|
}
|
|
10420
10521
|
throw err;
|
|
@@ -10432,7 +10533,7 @@ async function addPatternCommand(options) {
|
|
|
10432
10533
|
});
|
|
10433
10534
|
} catch (err) {
|
|
10434
10535
|
if (err instanceof InputTimeoutError) {
|
|
10435
|
-
console.log(
|
|
10536
|
+
console.log(chalk28.red("\n\u2717 Input timed out"));
|
|
10436
10537
|
process.exit(1);
|
|
10437
10538
|
}
|
|
10438
10539
|
throw err;
|
|
@@ -10456,7 +10557,7 @@ async function addPatternCommand(options) {
|
|
|
10456
10557
|
successRate = parseFloat(rateStr);
|
|
10457
10558
|
} catch (err) {
|
|
10458
10559
|
if (err instanceof InputTimeoutError) {
|
|
10459
|
-
console.log(
|
|
10560
|
+
console.log(chalk28.red("\n\u2717 Input timed out"));
|
|
10460
10561
|
process.exit(1);
|
|
10461
10562
|
}
|
|
10462
10563
|
throw err;
|
|
@@ -10469,13 +10570,13 @@ async function addPatternCommand(options) {
|
|
|
10469
10570
|
approach,
|
|
10470
10571
|
successRate
|
|
10471
10572
|
});
|
|
10472
|
-
console.log(
|
|
10473
|
-
console.log(
|
|
10573
|
+
console.log(chalk28.green("\u2713 Pattern documented"));
|
|
10574
|
+
console.log(chalk28.gray(` File: success-patterns.md`));
|
|
10474
10575
|
}
|
|
10475
10576
|
async function statsCommand(options) {
|
|
10476
10577
|
const knowledgeDir = findKnowledgeDir();
|
|
10477
10578
|
if (!knowledgeDir) {
|
|
10478
|
-
console.log(
|
|
10579
|
+
console.log(chalk28.red("No .reygent/knowledge/ directory found."));
|
|
10479
10580
|
process.exit(1);
|
|
10480
10581
|
}
|
|
10481
10582
|
const spinner = ora9("Calculating knowledge base stats...").start();
|
|
@@ -10483,7 +10584,7 @@ async function statsCommand(options) {
|
|
|
10483
10584
|
const since = options.since || "30d";
|
|
10484
10585
|
const match = since.match(/^(\d+)d$/);
|
|
10485
10586
|
if (!match) {
|
|
10486
|
-
spinner.fail(
|
|
10587
|
+
spinner.fail(chalk28.red(`Invalid --since format: ${since}. Use format like "30d".`));
|
|
10487
10588
|
process.exit(1);
|
|
10488
10589
|
}
|
|
10489
10590
|
const days = Number.parseInt(match[1], 10);
|
|
@@ -10497,9 +10598,9 @@ async function statsCommand(options) {
|
|
|
10497
10598
|
}, 0);
|
|
10498
10599
|
const chesstrace = getChesstrace();
|
|
10499
10600
|
if (!chesstrace) {
|
|
10500
|
-
spinner.fail(
|
|
10601
|
+
spinner.fail(chalk28.yellow("Telemetry not available. Cannot calculate effectiveness."));
|
|
10501
10602
|
console.log();
|
|
10502
|
-
console.log(
|
|
10603
|
+
console.log(chalk28.bold("Knowledge Base Stats"));
|
|
10503
10604
|
console.log();
|
|
10504
10605
|
console.log(`Files: ${files.length}`);
|
|
10505
10606
|
console.log(`Total entries: ${totalEntries}`);
|
|
@@ -10507,32 +10608,32 @@ async function statsCommand(options) {
|
|
|
10507
10608
|
}
|
|
10508
10609
|
const backend = chesstrace.getBackend();
|
|
10509
10610
|
const effectiveness = measureKnowledgeEffectiveness(backend, sinceMs);
|
|
10510
|
-
spinner.succeed(
|
|
10611
|
+
spinner.succeed(chalk28.green("Stats calculated"));
|
|
10511
10612
|
console.log();
|
|
10512
|
-
console.log(
|
|
10613
|
+
console.log(chalk28.bold("Knowledge Base Stats"));
|
|
10513
10614
|
console.log();
|
|
10514
|
-
console.log(
|
|
10515
|
-
console.log(
|
|
10615
|
+
console.log(chalk28.cyan("Files:"), files.length);
|
|
10616
|
+
console.log(chalk28.cyan("Total entries:"), totalEntries);
|
|
10516
10617
|
console.log();
|
|
10517
|
-
console.log(
|
|
10518
|
-
console.log(
|
|
10519
|
-
console.log(
|
|
10618
|
+
console.log(chalk28.bold(`Usage (last ${days} days):`));
|
|
10619
|
+
console.log(chalk28.cyan(" Consulted runs:"), effectiveness.consultedRuns);
|
|
10620
|
+
console.log(chalk28.cyan(" Baseline runs:"), effectiveness.baselineRuns);
|
|
10520
10621
|
console.log();
|
|
10521
10622
|
if (effectiveness.consultedRuns > 0 || effectiveness.baselineRuns > 0) {
|
|
10522
10623
|
const withKnowledgePct = Math.round(effectiveness.withKnowledge * 100);
|
|
10523
10624
|
const baselinePct = Math.round(effectiveness.baseline * 100);
|
|
10524
10625
|
const improvementPct = Math.round(effectiveness.improvement * 100);
|
|
10525
|
-
console.log(
|
|
10526
|
-
console.log(
|
|
10527
|
-
console.log(
|
|
10528
|
-
const improvementColor = effectiveness.improvement > 0 ?
|
|
10529
|
-
console.log(
|
|
10626
|
+
console.log(chalk28.bold("Effectiveness:"));
|
|
10627
|
+
console.log(chalk28.cyan(" Success rate with knowledge:"), `${withKnowledgePct}%`);
|
|
10628
|
+
console.log(chalk28.cyan(" Baseline success rate:"), `${baselinePct}%`);
|
|
10629
|
+
const improvementColor = effectiveness.improvement > 0 ? chalk28.green : effectiveness.improvement < 0 ? chalk28.red : chalk28.gray;
|
|
10630
|
+
console.log(chalk28.cyan(" Improvement:"), improvementColor(`${improvementPct > 0 ? "+" : ""}${improvementPct}%`));
|
|
10530
10631
|
} else {
|
|
10531
|
-
console.log(
|
|
10632
|
+
console.log(chalk28.gray("No runs found in time window to measure effectiveness."));
|
|
10532
10633
|
}
|
|
10533
10634
|
console.log();
|
|
10534
10635
|
} catch (err) {
|
|
10535
|
-
spinner.fail(
|
|
10636
|
+
spinner.fail(chalk28.red(`Failed to calculate stats: ${err.message}`));
|
|
10536
10637
|
process.exit(1);
|
|
10537
10638
|
}
|
|
10538
10639
|
}
|
|
@@ -10542,7 +10643,7 @@ import { existsSync as existsSync13, readFileSync as readFileSync11, writeFileSy
|
|
|
10542
10643
|
import { join as join13, dirname as dirname6 } from "path";
|
|
10543
10644
|
import { randomBytes as randomBytes2 } from "crypto";
|
|
10544
10645
|
import { confirm as confirm3 } from "@inquirer/prompts";
|
|
10545
|
-
import
|
|
10646
|
+
import chalk29 from "chalk";
|
|
10546
10647
|
function shouldPromptForTelemetry() {
|
|
10547
10648
|
if (!process.stdin.isTTY) {
|
|
10548
10649
|
return false;
|
|
@@ -10573,16 +10674,16 @@ function shouldPromptForTelemetry() {
|
|
|
10573
10674
|
return false;
|
|
10574
10675
|
} catch (err) {
|
|
10575
10676
|
if (isDebug()) {
|
|
10576
|
-
console.error(
|
|
10677
|
+
console.error(chalk29.gray(`Failed to read config at ${configPath}:`), err);
|
|
10577
10678
|
}
|
|
10578
10679
|
return true;
|
|
10579
10680
|
}
|
|
10580
10681
|
}
|
|
10581
10682
|
async function promptForTelemetryOptIn() {
|
|
10582
10683
|
console.log("");
|
|
10583
|
-
console.log(
|
|
10584
|
-
console.log(
|
|
10585
|
-
console.log(
|
|
10684
|
+
console.log(chalk29.bold("First-run telemetry setup"));
|
|
10685
|
+
console.log(chalk29.gray("Reygent can collect local usage data to help diagnose issues."));
|
|
10686
|
+
console.log(chalk29.gray("Data is stored locally in SQLite and never sent to external servers."));
|
|
10586
10687
|
console.log("");
|
|
10587
10688
|
const enabled = await confirm3({
|
|
10588
10689
|
message: "Enable local telemetry?",
|
|
@@ -10591,9 +10692,9 @@ async function promptForTelemetryOptIn() {
|
|
|
10591
10692
|
await saveTelemetryChoice(enabled);
|
|
10592
10693
|
console.log("");
|
|
10593
10694
|
if (enabled) {
|
|
10594
|
-
console.log(
|
|
10695
|
+
console.log(chalk29.green("\u2713"), "Local telemetry enabled");
|
|
10595
10696
|
} else {
|
|
10596
|
-
console.log(
|
|
10697
|
+
console.log(chalk29.gray("\u2713"), "Local telemetry disabled");
|
|
10597
10698
|
}
|
|
10598
10699
|
console.log("");
|
|
10599
10700
|
}
|
|
@@ -10616,7 +10717,7 @@ async function saveTelemetryChoice(enabled) {
|
|
|
10616
10717
|
rawConfig = JSON.parse(content);
|
|
10617
10718
|
} catch (err) {
|
|
10618
10719
|
if (isDebug()) {
|
|
10619
|
-
console.error(
|
|
10720
|
+
console.error(chalk29.gray(`Failed to parse config at ${configPath}:`), err);
|
|
10620
10721
|
}
|
|
10621
10722
|
}
|
|
10622
10723
|
}
|
|
@@ -10645,9 +10746,9 @@ async function saveTelemetryChoice(enabled) {
|
|
|
10645
10746
|
}
|
|
10646
10747
|
} catch (err) {
|
|
10647
10748
|
const message = err instanceof Error ? err.message : String(err);
|
|
10648
|
-
console.log(
|
|
10749
|
+
console.log(chalk29.yellow("Warning:"), `Failed to save telemetry config: ${message}`);
|
|
10649
10750
|
if (isDebug()) console.error(err instanceof Error ? err.stack : err);
|
|
10650
|
-
console.log(
|
|
10751
|
+
console.log(chalk29.gray("Command will continue without saving telemetry preference."));
|
|
10651
10752
|
}
|
|
10652
10753
|
}
|
|
10653
10754
|
|
|
@@ -10658,7 +10759,7 @@ var pkg = JSON.parse(
|
|
|
10658
10759
|
);
|
|
10659
10760
|
var program = new Command();
|
|
10660
10761
|
program.name("reygent").description("Reygent CLI tool").version(pkg.version).option("--debug", "Show full stack traces on errors (or set REYGENT_DEBUG=1)").option("--model <id>", "Model ID (e.g. claude-sonnet-4-5, gemini-2.5-pro, gpt-5.4)").option("--provider <name>", `AI provider (${PROVIDER_NAMES.join(", ")})`).option("--no-telemetry", "Disable telemetry for this run").option("--telemetry-level <level>", "Override telemetry level (minimal, standard, verbose)").option("--telemetry-verbose", "Shorthand for --telemetry-level verbose").addHelpText("after", `
|
|
10661
|
-
${
|
|
10762
|
+
${chalk30.yellow("Disclaimer:")} This software is provided "as is" with no warranty. AI-generated output should be reviewed by a human. See LICENSE for full terms.`);
|
|
10662
10763
|
program.command("init").description("Initialize .reygent folder with default agent and skill config").option("--dry-run", "Preview what files would be created without writing anything", false).action(initCommand);
|
|
10663
10764
|
program.command("generate-spec").description("Generate a full markdown spec from a short description").argument("[description]", "Short description of the feature to spec out").option("--output <file>", "Output file path").option("--skip-clarification", "Skip clarifying questions and generate spec directly", false).action(generateSpecCommand);
|
|
10664
10765
|
program.command("spec").description("Load a spec from a markdown file, Jira issue, or Linear issue").argument("<source>", "Path to a markdown file, issue key (e.g. PROJ-123), or Linear URL").option("--clarify", "Run planner with clarification loop to evaluate spec", false).option("--source <name>", "Issue source provider (jira, linear, local) \u2014 skips interactive prompt").action(specCommand);
|
|
@@ -10666,7 +10767,7 @@ program.command("agent").description("Start an interactive agent session").argum
|
|
|
10666
10767
|
program.command("run").description("Run the reygent workflow from spec to reviewed PR").option("--spec <source>", "Path to a markdown file, issue key, or Linear URL (prompts if omitted in interactive mode)").option("--type <type>", "Branch type (feat, fix, chore, refactor, docs, test, style, perf) \u2014 skips interactive prompt").option("--dry-run", "Preview workflow stages without executing", false).option("--security-threshold <level>", "Minimum severity to fail security review (CRITICAL, HIGH, MEDIUM, LOW)", "HIGH").option("--auto-approve", "Auto-approve all file edits and actions without prompting", false).option("--insecure", "Skip SSL certificate verification for API calls", false).option("--skip-clarification", "Skip planner clarification and make assumptions", false).option("--max-retries <count>", "Max retry attempts when gate tests fail", "2").option("--verbose", "Show detailed per-agent token and cost breakdown", false).hook("preAction", (thisCommand) => {
|
|
10667
10768
|
const opts = thisCommand.opts();
|
|
10668
10769
|
if (opts.type && !isValidType(opts.type)) {
|
|
10669
|
-
console.error(
|
|
10770
|
+
console.error(chalk30.red(`Error: Invalid --type "${opts.type}". Must be one of: ${VALID_BRANCH_TYPES.join(", ")} (or feature/bugfix aliases)`));
|
|
10670
10771
|
process.exit(1);
|
|
10671
10772
|
}
|
|
10672
10773
|
}).action(runCommand);
|
|
@@ -10686,8 +10787,8 @@ registerSkillsCommand(program);
|
|
|
10686
10787
|
registerKnowledgeCommand(program);
|
|
10687
10788
|
var isHelpOrVersion = process.argv.includes("--help") || process.argv.includes("-h") || process.argv.includes("--version") || process.argv.includes("-V") || process.argv.length <= 2;
|
|
10688
10789
|
if (!isHelpOrVersion) {
|
|
10689
|
-
console.log(
|
|
10690
|
-
reygent`) +
|
|
10790
|
+
console.log(chalk30.bold.cyan(`
|
|
10791
|
+
reygent`) + chalk30.gray(` v${pkg.version}`) + "\n");
|
|
10691
10792
|
}
|
|
10692
10793
|
program.hook("preAction", async () => {
|
|
10693
10794
|
if (program.opts().debug) {
|
|
@@ -10731,7 +10832,7 @@ program.hook("preAction", async () => {
|
|
|
10731
10832
|
}
|
|
10732
10833
|
} catch (err) {
|
|
10733
10834
|
if (program.opts().debug) {
|
|
10734
|
-
console.error(
|
|
10835
|
+
console.error(chalk30.gray("Validation error:"), err);
|
|
10735
10836
|
}
|
|
10736
10837
|
}
|
|
10737
10838
|
const noTelemetry = program.opts().telemetry === false;
|
|
@@ -10740,11 +10841,11 @@ program.hook("preAction", async () => {
|
|
|
10740
10841
|
await promptForTelemetryOptIn();
|
|
10741
10842
|
} catch (err) {
|
|
10742
10843
|
if (err && typeof err === "object" && "name" in err && err.name === "ExitPromptError") {
|
|
10743
|
-
console.log(
|
|
10844
|
+
console.log(chalk30.yellow("\nTelemetry setup cancelled."));
|
|
10744
10845
|
process.exit(0);
|
|
10745
10846
|
}
|
|
10746
10847
|
if (program.opts().debug) {
|
|
10747
|
-
console.error(
|
|
10848
|
+
console.error(chalk30.gray("Telemetry prompt failed:"), err);
|
|
10748
10849
|
}
|
|
10749
10850
|
}
|
|
10750
10851
|
}
|