@rely-ai/caliber 1.20.0-dev.1773685589 → 1.20.0-dev.1773685636
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.js +606 -382
- package/package.json +1 -1
package/dist/bin.js
CHANGED
|
@@ -225,7 +225,7 @@ import { fileURLToPath } from "url";
|
|
|
225
225
|
|
|
226
226
|
// src/commands/init.ts
|
|
227
227
|
import path19 from "path";
|
|
228
|
-
import
|
|
228
|
+
import chalk10 from "chalk";
|
|
229
229
|
import ora2 from "ora";
|
|
230
230
|
import select5 from "@inquirer/select";
|
|
231
231
|
import checkbox from "@inquirer/checkbox";
|
|
@@ -2686,6 +2686,37 @@ async function generateMonolithic(fingerprint, targetAgent, prompt, callbacks, f
|
|
|
2686
2686
|
};
|
|
2687
2687
|
return attemptGeneration();
|
|
2688
2688
|
}
|
|
2689
|
+
async function generateSkillsForSetup(setup, fingerprint, targetAgent, onStatus) {
|
|
2690
|
+
const skillTopics = collectSkillTopics(setup, targetAgent, fingerprint);
|
|
2691
|
+
if (skillTopics.length === 0) return 0;
|
|
2692
|
+
onStatus?.(`Generating ${skillTopics.length} skills...`);
|
|
2693
|
+
const allDeps = extractAllDeps(process.cwd());
|
|
2694
|
+
const skillContext = buildSkillContext(fingerprint, setup, allDeps);
|
|
2695
|
+
const fastModel = getFastModel();
|
|
2696
|
+
const skillResults = await Promise.allSettled(
|
|
2697
|
+
skillTopics.map(
|
|
2698
|
+
({ platform, topic }) => generateSkill(skillContext, topic, fastModel).then((skill) => ({ platform, skill }))
|
|
2699
|
+
)
|
|
2700
|
+
);
|
|
2701
|
+
for (const result of skillResults) {
|
|
2702
|
+
if (result.status === "fulfilled") {
|
|
2703
|
+
const { platform, skill } = result.value;
|
|
2704
|
+
const platformObj = setup[platform] ?? {};
|
|
2705
|
+
const skills = platformObj.skills ?? [];
|
|
2706
|
+
skills.push(skill);
|
|
2707
|
+
platformObj.skills = skills;
|
|
2708
|
+
setup[platform] = platformObj;
|
|
2709
|
+
const skillPath = platform === "codex" ? `.agents/skills/${skill.name}/SKILL.md` : `.${platform}/skills/${skill.name}/SKILL.md`;
|
|
2710
|
+
const descriptions = setup.fileDescriptions ?? {};
|
|
2711
|
+
descriptions[skillPath] = skill.description.slice(0, 80);
|
|
2712
|
+
setup.fileDescriptions = descriptions;
|
|
2713
|
+
}
|
|
2714
|
+
}
|
|
2715
|
+
const succeeded = skillResults.filter((r) => r.status === "fulfilled").length;
|
|
2716
|
+
const failed = skillResults.filter((r) => r.status === "rejected").length;
|
|
2717
|
+
if (failed > 0) onStatus?.(`${succeeded} generated, ${failed} failed`);
|
|
2718
|
+
return succeeded;
|
|
2719
|
+
}
|
|
2689
2720
|
var LIMITS = {
|
|
2690
2721
|
FILE_TREE_ENTRIES: 500,
|
|
2691
2722
|
EXISTING_CONFIG_CHARS: 8e3,
|
|
@@ -3679,8 +3710,8 @@ function removePreCommitHook() {
|
|
|
3679
3710
|
if (!content.includes(PRECOMMIT_START)) {
|
|
3680
3711
|
return { removed: false, notFound: true };
|
|
3681
3712
|
}
|
|
3682
|
-
const
|
|
3683
|
-
content = content.replace(
|
|
3713
|
+
const regex2 = new RegExp(`\\n?${PRECOMMIT_START}[\\s\\S]*?${PRECOMMIT_END}\\n?`);
|
|
3714
|
+
content = content.replace(regex2, "\n");
|
|
3684
3715
|
if (content.trim() === "#!/bin/sh" || content.trim() === "") {
|
|
3685
3716
|
fs17.unlinkSync(hookPath);
|
|
3686
3717
|
} else {
|
|
@@ -6007,6 +6038,51 @@ function extractTopDeps() {
|
|
|
6007
6038
|
return [];
|
|
6008
6039
|
}
|
|
6009
6040
|
}
|
|
6041
|
+
async function searchSkills(fingerprint, targetPlatforms, onStatus) {
|
|
6042
|
+
const installedSkills = getInstalledSkills(targetPlatforms);
|
|
6043
|
+
const technologies = [...new Set([
|
|
6044
|
+
...fingerprint.languages,
|
|
6045
|
+
...fingerprint.frameworks,
|
|
6046
|
+
...extractTopDeps()
|
|
6047
|
+
].filter(Boolean))];
|
|
6048
|
+
if (technologies.length === 0) {
|
|
6049
|
+
return { results: [], contentMap: /* @__PURE__ */ new Map() };
|
|
6050
|
+
}
|
|
6051
|
+
const primaryPlatform = targetPlatforms.includes("claude") ? "claude" : targetPlatforms[0];
|
|
6052
|
+
onStatus?.("Searching skill registries...");
|
|
6053
|
+
const allCandidates = await searchAllProviders(technologies, primaryPlatform);
|
|
6054
|
+
if (!allCandidates.length) {
|
|
6055
|
+
return { results: [], contentMap: /* @__PURE__ */ new Map() };
|
|
6056
|
+
}
|
|
6057
|
+
const newCandidates = allCandidates.filter((c) => !installedSkills.has(c.slug.toLowerCase()));
|
|
6058
|
+
if (!newCandidates.length) {
|
|
6059
|
+
return { results: [], contentMap: /* @__PURE__ */ new Map() };
|
|
6060
|
+
}
|
|
6061
|
+
onStatus?.(`Scoring ${newCandidates.length} candidates...`);
|
|
6062
|
+
let results;
|
|
6063
|
+
const config = loadConfig();
|
|
6064
|
+
if (config) {
|
|
6065
|
+
try {
|
|
6066
|
+
const projectContext = buildProjectContext(fingerprint, targetPlatforms);
|
|
6067
|
+
results = await scoreWithLLM(newCandidates, projectContext, technologies);
|
|
6068
|
+
} catch {
|
|
6069
|
+
results = newCandidates.slice(0, 20);
|
|
6070
|
+
}
|
|
6071
|
+
} else {
|
|
6072
|
+
results = newCandidates.slice(0, 20);
|
|
6073
|
+
}
|
|
6074
|
+
if (results.length === 0) {
|
|
6075
|
+
return { results: [], contentMap: /* @__PURE__ */ new Map() };
|
|
6076
|
+
}
|
|
6077
|
+
onStatus?.("Fetching skill content...");
|
|
6078
|
+
const contentMap = /* @__PURE__ */ new Map();
|
|
6079
|
+
await Promise.all(results.map(async (rec) => {
|
|
6080
|
+
const content = await fetchSkillContent(rec);
|
|
6081
|
+
if (content) contentMap.set(rec.slug, content);
|
|
6082
|
+
}));
|
|
6083
|
+
const available = results.filter((r) => contentMap.has(r.slug));
|
|
6084
|
+
return { results: available, contentMap };
|
|
6085
|
+
}
|
|
6010
6086
|
async function recommendCommand() {
|
|
6011
6087
|
const proceed = await select4({
|
|
6012
6088
|
message: "Search public repos for relevant skills to add to this project?",
|
|
@@ -6371,13 +6447,144 @@ function formatMs(ms) {
|
|
|
6371
6447
|
return `${secs}s`;
|
|
6372
6448
|
}
|
|
6373
6449
|
|
|
6450
|
+
// src/utils/parallel-tasks.ts
|
|
6451
|
+
import chalk9 from "chalk";
|
|
6452
|
+
|
|
6453
|
+
// node_modules/ansi-regex/index.js
|
|
6454
|
+
function ansiRegex({ onlyFirst = false } = {}) {
|
|
6455
|
+
const ST = "(?:\\u0007|\\u001B\\u005C|\\u009C)";
|
|
6456
|
+
const osc = `(?:\\u001B\\][\\s\\S]*?${ST})`;
|
|
6457
|
+
const csi = "[\\u001B\\u009B][[\\]()#;?]*(?:\\d{1,4}(?:[;:]\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]";
|
|
6458
|
+
const pattern = `${osc}|${csi}`;
|
|
6459
|
+
return new RegExp(pattern, onlyFirst ? void 0 : "g");
|
|
6460
|
+
}
|
|
6461
|
+
|
|
6462
|
+
// node_modules/strip-ansi/index.js
|
|
6463
|
+
var regex = ansiRegex();
|
|
6464
|
+
function stripAnsi(string) {
|
|
6465
|
+
if (typeof string !== "string") {
|
|
6466
|
+
throw new TypeError(`Expected a \`string\`, got \`${typeof string}\``);
|
|
6467
|
+
}
|
|
6468
|
+
if (!string.includes("\x1B") && !string.includes("\x9B")) {
|
|
6469
|
+
return string;
|
|
6470
|
+
}
|
|
6471
|
+
return string.replace(regex, "");
|
|
6472
|
+
}
|
|
6473
|
+
|
|
6474
|
+
// src/utils/parallel-tasks.ts
|
|
6475
|
+
var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
6476
|
+
var SPINNER_INTERVAL_MS = 80;
|
|
6477
|
+
var ParallelTaskDisplay = class {
|
|
6478
|
+
tasks = [];
|
|
6479
|
+
lineCount = 0;
|
|
6480
|
+
spinnerFrame = 0;
|
|
6481
|
+
timer = null;
|
|
6482
|
+
startTime = 0;
|
|
6483
|
+
rendered = false;
|
|
6484
|
+
add(name) {
|
|
6485
|
+
const index = this.tasks.length;
|
|
6486
|
+
this.tasks.push({ name, status: "pending", message: "" });
|
|
6487
|
+
return index;
|
|
6488
|
+
}
|
|
6489
|
+
start() {
|
|
6490
|
+
this.startTime = Date.now();
|
|
6491
|
+
this.draw(true);
|
|
6492
|
+
this.timer = setInterval(() => {
|
|
6493
|
+
this.spinnerFrame = (this.spinnerFrame + 1) % SPINNER_FRAMES.length;
|
|
6494
|
+
this.draw(false);
|
|
6495
|
+
}, SPINNER_INTERVAL_MS);
|
|
6496
|
+
}
|
|
6497
|
+
update(index, status, message) {
|
|
6498
|
+
const task = this.tasks[index];
|
|
6499
|
+
if (!task) return;
|
|
6500
|
+
if (status === "running" && task.status === "pending") {
|
|
6501
|
+
task.startTime = Date.now();
|
|
6502
|
+
}
|
|
6503
|
+
if ((status === "done" || status === "failed") && !task.endTime) {
|
|
6504
|
+
task.endTime = Date.now();
|
|
6505
|
+
}
|
|
6506
|
+
task.status = status;
|
|
6507
|
+
if (message !== void 0) task.message = message;
|
|
6508
|
+
}
|
|
6509
|
+
stop() {
|
|
6510
|
+
if (this.timer) {
|
|
6511
|
+
clearInterval(this.timer);
|
|
6512
|
+
this.timer = null;
|
|
6513
|
+
}
|
|
6514
|
+
this.draw(false);
|
|
6515
|
+
}
|
|
6516
|
+
formatTime(ms) {
|
|
6517
|
+
const secs = Math.floor(ms / 1e3);
|
|
6518
|
+
if (secs < 60) return `${secs}s`;
|
|
6519
|
+
return `${Math.floor(secs / 60)}m ${secs % 60}s`;
|
|
6520
|
+
}
|
|
6521
|
+
truncate(text, maxVisible) {
|
|
6522
|
+
const plain = stripAnsi(text);
|
|
6523
|
+
if (plain.length <= maxVisible) return text;
|
|
6524
|
+
let visible = 0;
|
|
6525
|
+
let i = 0;
|
|
6526
|
+
while (i < text.length && visible < maxVisible - 3) {
|
|
6527
|
+
if (text[i] === "\x1B") {
|
|
6528
|
+
const end = text.indexOf("m", i);
|
|
6529
|
+
if (end !== -1) {
|
|
6530
|
+
i = end + 1;
|
|
6531
|
+
continue;
|
|
6532
|
+
}
|
|
6533
|
+
}
|
|
6534
|
+
visible++;
|
|
6535
|
+
i++;
|
|
6536
|
+
}
|
|
6537
|
+
return text.slice(0, i) + "...";
|
|
6538
|
+
}
|
|
6539
|
+
renderLine(task) {
|
|
6540
|
+
const maxWidth = process.stdout.columns || 80;
|
|
6541
|
+
const elapsed = task.startTime ? this.formatTime((task.endTime ?? Date.now()) - task.startTime) : "";
|
|
6542
|
+
let line;
|
|
6543
|
+
switch (task.status) {
|
|
6544
|
+
case "pending":
|
|
6545
|
+
line = ` ${chalk9.dim("\u25CB")} ${chalk9.dim(task.name)}${task.message ? chalk9.dim(` \u2014 ${task.message}`) : ""}`;
|
|
6546
|
+
break;
|
|
6547
|
+
case "running": {
|
|
6548
|
+
const spinner = chalk9.cyan(SPINNER_FRAMES[this.spinnerFrame]);
|
|
6549
|
+
const time = elapsed ? chalk9.dim(` (${elapsed})`) : "";
|
|
6550
|
+
line = ` ${spinner} ${task.name}${task.message ? chalk9.dim(` \u2014 ${task.message}`) : ""}${time}`;
|
|
6551
|
+
break;
|
|
6552
|
+
}
|
|
6553
|
+
case "done": {
|
|
6554
|
+
const time = elapsed ? chalk9.dim(` (${elapsed})`) : "";
|
|
6555
|
+
line = ` ${chalk9.green("\u2713")} ${task.name}${task.message ? chalk9.dim(` \u2014 ${task.message}`) : ""}${time}`;
|
|
6556
|
+
break;
|
|
6557
|
+
}
|
|
6558
|
+
case "failed":
|
|
6559
|
+
line = ` ${chalk9.red("\u2717")} ${task.name}${task.message ? chalk9.red(` \u2014 ${task.message}`) : ""}`;
|
|
6560
|
+
break;
|
|
6561
|
+
}
|
|
6562
|
+
return this.truncate(line, maxWidth - 1);
|
|
6563
|
+
}
|
|
6564
|
+
draw(initial) {
|
|
6565
|
+
const { stdout } = process;
|
|
6566
|
+
if (!initial && this.rendered && this.lineCount > 0) {
|
|
6567
|
+
stdout.write(`\x1B[${this.lineCount}A`);
|
|
6568
|
+
}
|
|
6569
|
+
stdout.write("\x1B[0J");
|
|
6570
|
+
const lines = this.tasks.map((t) => this.renderLine(t));
|
|
6571
|
+
const totalElapsed = this.formatTime(Date.now() - this.startTime);
|
|
6572
|
+
lines.push(chalk9.dim(`
|
|
6573
|
+
Total: ${totalElapsed}`));
|
|
6574
|
+
const output = lines.join("\n");
|
|
6575
|
+
stdout.write(output + "\n");
|
|
6576
|
+
this.lineCount = output.split("\n").length;
|
|
6577
|
+
this.rendered = true;
|
|
6578
|
+
}
|
|
6579
|
+
};
|
|
6580
|
+
|
|
6374
6581
|
// src/commands/init.ts
|
|
6375
6582
|
function log(verbose, ...args) {
|
|
6376
|
-
if (verbose) console.log(
|
|
6583
|
+
if (verbose) console.log(chalk10.dim(` [verbose] ${args.map(String).join(" ")}`));
|
|
6377
6584
|
}
|
|
6378
6585
|
async function initCommand(options) {
|
|
6379
|
-
const brand =
|
|
6380
|
-
const title =
|
|
6586
|
+
const brand = chalk10.hex("#EB9D83");
|
|
6587
|
+
const title = chalk10.hex("#83D1EB");
|
|
6381
6588
|
console.log(brand.bold(`
|
|
6382
6589
|
\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2557
|
|
6383
6590
|
\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557
|
|
@@ -6386,34 +6593,33 @@ async function initCommand(options) {
|
|
|
6386
6593
|
\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551
|
|
6387
6594
|
\u255A\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D
|
|
6388
6595
|
`));
|
|
6389
|
-
console.log(
|
|
6390
|
-
console.log(
|
|
6596
|
+
console.log(chalk10.dim(" Scan your project and generate tailored config files for"));
|
|
6597
|
+
console.log(chalk10.dim(" Claude Code, Cursor, and Codex.\n"));
|
|
6391
6598
|
const report = options.debugReport ? new DebugReport() : null;
|
|
6392
6599
|
console.log(title.bold(" How it works:\n"));
|
|
6393
|
-
console.log(
|
|
6394
|
-
console.log(
|
|
6395
|
-
console.log(
|
|
6396
|
-
console.log(
|
|
6397
|
-
console.log(
|
|
6398
|
-
console.log(title.bold(" Step 1/5 \u2014 Connect\n"));
|
|
6600
|
+
console.log(chalk10.dim(" 1. Setup Connect your LLM provider and select your agents"));
|
|
6601
|
+
console.log(chalk10.dim(" 2. Engine Detect stack, generate configs & skills in parallel"));
|
|
6602
|
+
console.log(chalk10.dim(" 3. Review See all changes \u2014 accept, refine, or decline"));
|
|
6603
|
+
console.log(chalk10.dim(" 4. Finalize Score check and auto-sync hooks\n"));
|
|
6604
|
+
console.log(title.bold(" Step 1/4 \u2014 Setup\n"));
|
|
6399
6605
|
let config = loadConfig();
|
|
6400
6606
|
if (!config) {
|
|
6401
|
-
console.log(
|
|
6607
|
+
console.log(chalk10.dim(" No LLM provider configured yet.\n"));
|
|
6402
6608
|
await runInteractiveProviderSetup({
|
|
6403
6609
|
selectMessage: "How do you want to use Caliber? (choose LLM provider)"
|
|
6404
6610
|
});
|
|
6405
6611
|
config = loadConfig();
|
|
6406
6612
|
if (!config) {
|
|
6407
|
-
console.log(
|
|
6613
|
+
console.log(chalk10.red(" Setup was cancelled or failed.\n"));
|
|
6408
6614
|
throw new Error("__exit__");
|
|
6409
6615
|
}
|
|
6410
|
-
console.log(
|
|
6616
|
+
console.log(chalk10.green(" \u2713 Provider saved\n"));
|
|
6411
6617
|
}
|
|
6412
6618
|
trackInitProviderSelected(config.provider, config.model);
|
|
6413
6619
|
const displayModel = getDisplayModel(config);
|
|
6414
6620
|
const fastModel = getFastModel();
|
|
6415
6621
|
const modelLine = fastModel ? ` Provider: ${config.provider} | Model: ${displayModel} | Scan: ${fastModel}` : ` Provider: ${config.provider} | Model: ${displayModel}`;
|
|
6416
|
-
console.log(
|
|
6622
|
+
console.log(chalk10.dim(modelLine + "\n"));
|
|
6417
6623
|
if (report) {
|
|
6418
6624
|
report.markStep("Provider setup");
|
|
6419
6625
|
report.addSection("LLM Provider", `- **Provider**: ${config.provider}
|
|
@@ -6421,30 +6627,6 @@ async function initCommand(options) {
|
|
|
6421
6627
|
- **Fast model**: ${fastModel || "none"}`);
|
|
6422
6628
|
}
|
|
6423
6629
|
await validateModel({ fast: true });
|
|
6424
|
-
console.log(title.bold(" Step 2/5 \u2014 Discover\n"));
|
|
6425
|
-
const spinner = ora2("Scanning code, dependencies, and existing configs...").start();
|
|
6426
|
-
const fingerprint = await collectFingerprint(process.cwd());
|
|
6427
|
-
spinner.succeed("Project scanned");
|
|
6428
|
-
log(options.verbose, `Fingerprint: ${fingerprint.languages.length} languages, ${fingerprint.frameworks.length} frameworks, ${fingerprint.fileTree.length} files`);
|
|
6429
|
-
if (options.verbose && fingerprint.codeAnalysis) {
|
|
6430
|
-
log(options.verbose, `Code analysis: ${fingerprint.codeAnalysis.filesIncluded}/${fingerprint.codeAnalysis.filesAnalyzed} files, ~${fingerprint.codeAnalysis.includedTokens.toLocaleString()} tokens, ${fingerprint.codeAnalysis.duplicateGroups} dedup groups`);
|
|
6431
|
-
}
|
|
6432
|
-
trackInitProjectDiscovered(fingerprint.languages.length, fingerprint.frameworks.length, fingerprint.fileTree.length);
|
|
6433
|
-
const langDisplay = fingerprint.languages.join(", ") || "none detected";
|
|
6434
|
-
const frameworkDisplay = fingerprint.frameworks.length > 0 ? ` (${fingerprint.frameworks.join(", ")})` : "";
|
|
6435
|
-
console.log(chalk9.dim(` Languages: ${langDisplay}${frameworkDisplay}`));
|
|
6436
|
-
console.log(chalk9.dim(` Files: ${fingerprint.fileTree.length} found
|
|
6437
|
-
`));
|
|
6438
|
-
if (report) {
|
|
6439
|
-
report.markStep("Fingerprint");
|
|
6440
|
-
report.addJson("Fingerprint: Git", { remote: fingerprint.gitRemoteUrl, packageName: fingerprint.packageName });
|
|
6441
|
-
report.addCodeBlock("Fingerprint: File Tree", fingerprint.fileTree.join("\n"));
|
|
6442
|
-
report.addJson("Fingerprint: Detected Stack", { languages: fingerprint.languages, frameworks: fingerprint.frameworks, tools: fingerprint.tools });
|
|
6443
|
-
report.addJson("Fingerprint: Existing Configs", fingerprint.existingConfigs);
|
|
6444
|
-
if (fingerprint.codeAnalysis) {
|
|
6445
|
-
report.addJson("Fingerprint: Code Analysis", fingerprint.codeAnalysis);
|
|
6446
|
-
}
|
|
6447
|
-
}
|
|
6448
6630
|
let targetAgent;
|
|
6449
6631
|
if (options.agent) {
|
|
6450
6632
|
targetAgent = options.agent;
|
|
@@ -6454,30 +6636,27 @@ async function initCommand(options) {
|
|
|
6454
6636
|
} else {
|
|
6455
6637
|
targetAgent = await promptAgent();
|
|
6456
6638
|
}
|
|
6457
|
-
console.log(
|
|
6639
|
+
console.log(chalk10.dim(` Target: ${targetAgent.join(", ")}
|
|
6458
6640
|
`));
|
|
6459
6641
|
trackInitAgentSelected(targetAgent);
|
|
6460
|
-
|
|
6461
|
-
|
|
6462
|
-
|
|
6463
|
-
|
|
6464
|
-
|
|
6465
|
-
|
|
6466
|
-
|
|
6467
|
-
|
|
6468
|
-
|
|
6469
|
-
}
|
|
6642
|
+
let wantsSkills = false;
|
|
6643
|
+
if (!options.autoApprove) {
|
|
6644
|
+
wantsSkills = await select5({
|
|
6645
|
+
message: "Discover community-maintained skills that match your stack?",
|
|
6646
|
+
choices: [
|
|
6647
|
+
{ name: "Yes, find skills for my project", value: true },
|
|
6648
|
+
{ name: "Skip for now", value: false }
|
|
6649
|
+
]
|
|
6650
|
+
});
|
|
6470
6651
|
}
|
|
6471
|
-
|
|
6472
|
-
console.log(
|
|
6652
|
+
let baselineScore = computeLocalScore(process.cwd(), targetAgent);
|
|
6653
|
+
console.log(chalk10.dim("\n Current setup score:"));
|
|
6473
6654
|
displayScoreSummary(baselineScore);
|
|
6474
6655
|
if (options.verbose) {
|
|
6475
6656
|
for (const c of baselineScore.checks) {
|
|
6476
6657
|
log(options.verbose, ` ${c.passed ? "\u2713" : "\u2717"} ${c.name}: ${c.earnedPoints}/${c.maxPoints}${c.suggestion ? ` \u2014 ${c.suggestion}` : ""}`);
|
|
6477
6658
|
}
|
|
6478
6659
|
}
|
|
6479
|
-
const passingCount = baselineScore.checks.filter((c) => c.passed).length;
|
|
6480
|
-
const failingCount = baselineScore.checks.filter((c) => !c.passed).length;
|
|
6481
6660
|
if (report) {
|
|
6482
6661
|
report.markStep("Baseline scoring");
|
|
6483
6662
|
report.addSection("Scoring: Baseline", `**Score**: ${baselineScore.score}/100
|
|
@@ -6487,7 +6666,7 @@ async function initCommand(options) {
|
|
|
6487
6666
|
` + baselineScore.checks.map((c) => `| ${c.name} | ${c.passed ? "Yes" : "No"} | ${c.earnedPoints} | ${c.maxPoints} |`).join("\n"));
|
|
6488
6667
|
report.addSection("Generation: Target Agents", targetAgent.join(", "));
|
|
6489
6668
|
}
|
|
6490
|
-
const hasExistingConfig = !!(
|
|
6669
|
+
const hasExistingConfig = !!(baselineScore.checks.some((c) => c.id === "claude_md_exists" && c.passed) || baselineScore.checks.some((c) => c.id === "cursorrules_exists" && c.passed));
|
|
6491
6670
|
const NON_LLM_CHECKS = /* @__PURE__ */ new Set([
|
|
6492
6671
|
"hooks_configured",
|
|
6493
6672
|
"agents_md_exists",
|
|
@@ -6496,111 +6675,175 @@ async function initCommand(options) {
|
|
|
6496
6675
|
"service_coverage",
|
|
6497
6676
|
"mcp_completeness"
|
|
6498
6677
|
]);
|
|
6678
|
+
const passingCount = baselineScore.checks.filter((c) => c.passed).length;
|
|
6679
|
+
const failingCount = baselineScore.checks.filter((c) => !c.passed).length;
|
|
6499
6680
|
if (hasExistingConfig && baselineScore.score === 100) {
|
|
6500
6681
|
trackInitScoreComputed(baselineScore.score, passingCount, failingCount, true);
|
|
6501
|
-
console.log(
|
|
6502
|
-
console.log(
|
|
6682
|
+
console.log(chalk10.bold.green(" Your setup is already optimal \u2014 nothing to change.\n"));
|
|
6683
|
+
console.log(chalk10.dim(" Run ") + chalk10.hex("#83D1EB")("caliber init --force") + chalk10.dim(" to regenerate anyway.\n"));
|
|
6503
6684
|
if (!options.force) return;
|
|
6504
6685
|
}
|
|
6505
6686
|
const allFailingChecks = baselineScore.checks.filter((c) => !c.passed && c.maxPoints > 0);
|
|
6506
6687
|
const llmFixableChecks = allFailingChecks.filter((c) => !NON_LLM_CHECKS.has(c.id));
|
|
6507
6688
|
trackInitScoreComputed(baselineScore.score, passingCount, failingCount, false);
|
|
6508
6689
|
if (hasExistingConfig && llmFixableChecks.length === 0 && allFailingChecks.length > 0 && !options.force) {
|
|
6509
|
-
console.log(
|
|
6510
|
-
console.log(
|
|
6690
|
+
console.log(chalk10.bold.green("\n Your config is fully optimized for LLM generation.\n"));
|
|
6691
|
+
console.log(chalk10.dim(" Remaining items need CLI actions:\n"));
|
|
6511
6692
|
for (const check of allFailingChecks) {
|
|
6512
|
-
console.log(
|
|
6693
|
+
console.log(chalk10.dim(` \u2022 ${check.name}`));
|
|
6513
6694
|
if (check.suggestion) {
|
|
6514
|
-
console.log(` ${
|
|
6695
|
+
console.log(` ${chalk10.hex("#83D1EB")(check.suggestion)}`);
|
|
6515
6696
|
}
|
|
6516
6697
|
}
|
|
6517
6698
|
console.log("");
|
|
6518
|
-
console.log(
|
|
6699
|
+
console.log(chalk10.dim(" Run ") + chalk10.hex("#83D1EB")("caliber init --force") + chalk10.dim(" to regenerate anyway.\n"));
|
|
6519
6700
|
return;
|
|
6520
6701
|
}
|
|
6702
|
+
console.log(title.bold(" Step 2/4 \u2014 Engine\n"));
|
|
6703
|
+
const genModelInfo = fastModel ? ` Using ${displayModel} for docs, ${fastModel} for skills` : ` Using ${displayModel}`;
|
|
6704
|
+
console.log(chalk10.dim(genModelInfo + "\n"));
|
|
6705
|
+
if (report) report.markStep("Generation");
|
|
6706
|
+
trackInitGenerationStarted(false);
|
|
6707
|
+
const genStartTime = Date.now();
|
|
6708
|
+
let generatedSetup = null;
|
|
6709
|
+
let rawOutput;
|
|
6710
|
+
let genStopReason;
|
|
6711
|
+
let skillSearchResult = { results: [], contentMap: /* @__PURE__ */ new Map() };
|
|
6712
|
+
let fingerprint;
|
|
6713
|
+
const fpSpinner = ora2("Scanning project...").start();
|
|
6714
|
+
try {
|
|
6715
|
+
fingerprint = await collectFingerprint(process.cwd());
|
|
6716
|
+
fpSpinner.succeed(`Stack detected \u2014 ${fingerprint.languages.join(", ") || "no languages"}${fingerprint.frameworks.length > 0 ? `, ${fingerprint.frameworks.join(", ")}` : ""}`);
|
|
6717
|
+
} catch (err) {
|
|
6718
|
+
fpSpinner.fail("Failed to scan project");
|
|
6719
|
+
throw new Error("__exit__");
|
|
6720
|
+
}
|
|
6721
|
+
trackInitProjectDiscovered(fingerprint.languages.length, fingerprint.frameworks.length, fingerprint.fileTree.length);
|
|
6722
|
+
log(options.verbose, `Fingerprint: ${fingerprint.languages.length} languages, ${fingerprint.frameworks.length} frameworks, ${fingerprint.fileTree.length} files`);
|
|
6723
|
+
if (report) {
|
|
6724
|
+
report.addJson("Fingerprint: Git", { remote: fingerprint.gitRemoteUrl, packageName: fingerprint.packageName });
|
|
6725
|
+
report.addCodeBlock("Fingerprint: File Tree", fingerprint.fileTree.join("\n"));
|
|
6726
|
+
report.addJson("Fingerprint: Detected Stack", { languages: fingerprint.languages, frameworks: fingerprint.frameworks, tools: fingerprint.tools });
|
|
6727
|
+
report.addJson("Fingerprint: Existing Configs", fingerprint.existingConfigs);
|
|
6728
|
+
if (fingerprint.codeAnalysis) report.addJson("Fingerprint: Code Analysis", fingerprint.codeAnalysis);
|
|
6729
|
+
}
|
|
6521
6730
|
const isEmpty = fingerprint.fileTree.length < 3;
|
|
6522
6731
|
if (isEmpty) {
|
|
6523
6732
|
fingerprint.description = await promptInput("What will you build in this project?");
|
|
6524
6733
|
}
|
|
6734
|
+
const failingForDismissal = baselineScore.checks.filter((c) => !c.passed && c.maxPoints > 0);
|
|
6735
|
+
if (failingForDismissal.length > 0) {
|
|
6736
|
+
const newDismissals = await evaluateDismissals(failingForDismissal, fingerprint);
|
|
6737
|
+
if (newDismissals.length > 0) {
|
|
6738
|
+
const existing = readDismissedChecks();
|
|
6739
|
+
const existingIds = new Set(existing.map((d) => d.id));
|
|
6740
|
+
const merged = [...existing, ...newDismissals.filter((d) => !existingIds.has(d.id))];
|
|
6741
|
+
writeDismissedChecks(merged);
|
|
6742
|
+
baselineScore = computeLocalScore(process.cwd(), targetAgent);
|
|
6743
|
+
}
|
|
6744
|
+
}
|
|
6525
6745
|
let failingChecks;
|
|
6526
6746
|
let passingChecks;
|
|
6527
6747
|
let currentScore;
|
|
6528
6748
|
if (hasExistingConfig && baselineScore.score >= 95 && !options.force) {
|
|
6529
|
-
|
|
6749
|
+
const currentLlmFixable = baselineScore.checks.filter((c) => !c.passed && c.maxPoints > 0 && !NON_LLM_CHECKS.has(c.id));
|
|
6750
|
+
failingChecks = currentLlmFixable.map((c) => ({ name: c.name, suggestion: c.suggestion, fix: c.fix }));
|
|
6530
6751
|
passingChecks = baselineScore.checks.filter((c) => c.passed).map((c) => ({ name: c.name }));
|
|
6531
6752
|
currentScore = baselineScore.score;
|
|
6532
|
-
if (failingChecks.length > 0) {
|
|
6533
|
-
console.log(title.bold(" Step 3/5 \u2014 Generate\n"));
|
|
6534
|
-
console.log(chalk9.dim(` Score is ${baselineScore.score}/100 \u2014 fine-tuning ${failingChecks.length} remaining issue${failingChecks.length === 1 ? "" : "s"}:
|
|
6535
|
-
`));
|
|
6536
|
-
for (const check of failingChecks) {
|
|
6537
|
-
console.log(chalk9.dim(` \u2022 ${check.name}`));
|
|
6538
|
-
}
|
|
6539
|
-
console.log("");
|
|
6540
|
-
}
|
|
6541
|
-
} else if (hasExistingConfig) {
|
|
6542
|
-
console.log(title.bold(" Step 3/5 \u2014 Generate\n"));
|
|
6543
|
-
console.log(chalk9.dim(" Auditing your existing configs against your codebase and improving them.\n"));
|
|
6544
|
-
} else {
|
|
6545
|
-
console.log(title.bold(" Step 3/5 \u2014 Generate\n"));
|
|
6546
|
-
console.log(chalk9.dim(" Building CLAUDE.md, rules, and skills tailored to your project.\n"));
|
|
6547
6753
|
}
|
|
6548
|
-
const genModelInfo = fastModel ? ` Using ${displayModel} for docs, ${fastModel} for skills` : ` Using ${displayModel}`;
|
|
6549
|
-
console.log(chalk9.dim(genModelInfo));
|
|
6550
|
-
console.log(chalk9.dim(" This can take a couple of minutes depending on your model and provider.\n"));
|
|
6551
6754
|
if (report) {
|
|
6552
|
-
report.markStep("Generation");
|
|
6553
6755
|
const fullPrompt = buildGeneratePrompt(fingerprint, targetAgent, fingerprint.description, failingChecks, currentScore, passingChecks);
|
|
6554
6756
|
report.addCodeBlock("Generation: Full LLM Prompt", fullPrompt);
|
|
6555
6757
|
}
|
|
6556
|
-
|
|
6557
|
-
const
|
|
6558
|
-
const
|
|
6559
|
-
const
|
|
6560
|
-
|
|
6561
|
-
let generatedSetup = null;
|
|
6562
|
-
let rawOutput;
|
|
6563
|
-
let genStopReason;
|
|
6758
|
+
const display = new ParallelTaskDisplay();
|
|
6759
|
+
const TASK_CONFIG = display.add("Generating configs");
|
|
6760
|
+
const TASK_SKILLS_GEN = display.add("Generating skills");
|
|
6761
|
+
const TASK_SKILLS_SEARCH = wantsSkills ? display.add("Searching community skills") : -1;
|
|
6762
|
+
display.start();
|
|
6564
6763
|
try {
|
|
6565
|
-
|
|
6566
|
-
|
|
6567
|
-
|
|
6568
|
-
|
|
6569
|
-
|
|
6570
|
-
|
|
6571
|
-
|
|
6572
|
-
|
|
6573
|
-
|
|
6574
|
-
|
|
6764
|
+
display.update(TASK_CONFIG, "running");
|
|
6765
|
+
const generatePromise = (async () => {
|
|
6766
|
+
const result = await generateSetup(
|
|
6767
|
+
fingerprint,
|
|
6768
|
+
targetAgent,
|
|
6769
|
+
fingerprint.description,
|
|
6770
|
+
{
|
|
6771
|
+
onStatus: (status) => display.update(TASK_CONFIG, "running", status),
|
|
6772
|
+
onComplete: (setup) => {
|
|
6773
|
+
generatedSetup = setup;
|
|
6774
|
+
},
|
|
6775
|
+
onError: (error) => display.update(TASK_CONFIG, "failed", error)
|
|
6575
6776
|
},
|
|
6576
|
-
|
|
6577
|
-
|
|
6578
|
-
|
|
6579
|
-
}
|
|
6580
|
-
|
|
6581
|
-
|
|
6582
|
-
currentScore,
|
|
6583
|
-
passingChecks
|
|
6584
|
-
);
|
|
6585
|
-
if (!generatedSetup) {
|
|
6586
|
-
generatedSetup = result.setup;
|
|
6777
|
+
failingChecks,
|
|
6778
|
+
currentScore,
|
|
6779
|
+
passingChecks,
|
|
6780
|
+
{ skipSkills: true }
|
|
6781
|
+
);
|
|
6782
|
+
if (!generatedSetup) generatedSetup = result.setup;
|
|
6587
6783
|
rawOutput = result.raw;
|
|
6588
|
-
|
|
6589
|
-
|
|
6784
|
+
genStopReason = result.stopReason;
|
|
6785
|
+
if (!generatedSetup) {
|
|
6786
|
+
display.update(TASK_CONFIG, "failed", "Could not parse LLM response");
|
|
6787
|
+
display.update(TASK_SKILLS_GEN, "failed", "Skipped");
|
|
6788
|
+
return;
|
|
6789
|
+
}
|
|
6790
|
+
display.update(TASK_CONFIG, "done");
|
|
6791
|
+
display.update(TASK_SKILLS_GEN, "running");
|
|
6792
|
+
const skillCount = await generateSkillsForSetup(
|
|
6793
|
+
generatedSetup,
|
|
6794
|
+
fingerprint,
|
|
6795
|
+
targetAgent,
|
|
6796
|
+
(status) => display.update(TASK_SKILLS_GEN, "running", status)
|
|
6797
|
+
);
|
|
6798
|
+
display.update(TASK_SKILLS_GEN, "done", `${skillCount} skills`);
|
|
6799
|
+
})();
|
|
6800
|
+
const SEARCH_TIMEOUT_MS = 6e4;
|
|
6801
|
+
const searchPromise = wantsSkills ? (async () => {
|
|
6802
|
+
display.update(TASK_SKILLS_SEARCH, "running");
|
|
6803
|
+
try {
|
|
6804
|
+
const searchWithTimeout = Promise.race([
|
|
6805
|
+
searchSkills(
|
|
6806
|
+
fingerprint,
|
|
6807
|
+
targetAgent,
|
|
6808
|
+
(status) => display.update(TASK_SKILLS_SEARCH, "running", status)
|
|
6809
|
+
),
|
|
6810
|
+
new Promise(
|
|
6811
|
+
(_, reject) => setTimeout(() => reject(new Error("timeout")), SEARCH_TIMEOUT_MS)
|
|
6812
|
+
)
|
|
6813
|
+
]);
|
|
6814
|
+
skillSearchResult = await searchWithTimeout;
|
|
6815
|
+
const count = skillSearchResult.results.length;
|
|
6816
|
+
display.update(TASK_SKILLS_SEARCH, "done", count > 0 ? `${count} skills found` : "No matches");
|
|
6817
|
+
} catch (err) {
|
|
6818
|
+
const reason = err instanceof Error && err.message === "timeout" ? "Timed out" : "Search failed";
|
|
6819
|
+
display.update(TASK_SKILLS_SEARCH, "failed", reason);
|
|
6820
|
+
}
|
|
6821
|
+
})() : Promise.resolve();
|
|
6822
|
+
await Promise.all([generatePromise, searchPromise]);
|
|
6590
6823
|
} catch (err) {
|
|
6591
|
-
|
|
6824
|
+
display.stop();
|
|
6592
6825
|
const msg = err instanceof Error ? err.message : "Unknown error";
|
|
6593
|
-
|
|
6826
|
+
console.log(chalk10.red(`
|
|
6827
|
+
Engine failed: ${msg}
|
|
6828
|
+
`));
|
|
6594
6829
|
writeErrorLog(config, void 0, msg, "exception");
|
|
6595
6830
|
throw new Error("__exit__");
|
|
6596
6831
|
}
|
|
6597
|
-
|
|
6832
|
+
display.stop();
|
|
6833
|
+
const elapsedMs = Date.now() - genStartTime;
|
|
6834
|
+
trackInitGenerationCompleted(elapsedMs, 0);
|
|
6835
|
+
const mins = Math.floor(elapsedMs / 6e4);
|
|
6836
|
+
const secs = Math.floor(elapsedMs % 6e4 / 1e3);
|
|
6837
|
+
const timeStr = mins > 0 ? `${mins}m ${secs}s` : `${secs}s`;
|
|
6838
|
+
console.log(chalk10.dim(`
|
|
6839
|
+
Completed in ${timeStr}
|
|
6840
|
+
`));
|
|
6598
6841
|
if (!generatedSetup) {
|
|
6599
|
-
|
|
6842
|
+
console.log(chalk10.red(" Failed to generate setup."));
|
|
6600
6843
|
writeErrorLog(config, rawOutput, void 0, genStopReason);
|
|
6601
6844
|
if (rawOutput) {
|
|
6602
|
-
console.log(
|
|
6603
|
-
console.log(
|
|
6845
|
+
console.log(chalk10.dim("\nRaw LLM output (JSON parse failed):"));
|
|
6846
|
+
console.log(chalk10.dim(rawOutput.slice(0, 500)));
|
|
6604
6847
|
}
|
|
6605
6848
|
throw new Error("__exit__");
|
|
6606
6849
|
}
|
|
@@ -6608,12 +6851,6 @@ async function initCommand(options) {
|
|
|
6608
6851
|
if (rawOutput) report.addCodeBlock("Generation: Raw LLM Response", rawOutput);
|
|
6609
6852
|
report.addJson("Generation: Parsed Setup", generatedSetup);
|
|
6610
6853
|
}
|
|
6611
|
-
const elapsedMs = Date.now() - genStartTime;
|
|
6612
|
-
trackInitGenerationCompleted(elapsedMs, 0);
|
|
6613
|
-
const mins = Math.floor(elapsedMs / 6e4);
|
|
6614
|
-
const secs = Math.floor(elapsedMs % 6e4 / 1e3);
|
|
6615
|
-
const timeStr = mins > 0 ? `${mins}m ${secs}s` : `${secs}s`;
|
|
6616
|
-
genSpinner.succeed(`Setup generated ${chalk9.dim(`in ${timeStr}`)}`);
|
|
6617
6854
|
log(options.verbose, `Generation completed: ${elapsedMs}ms, stopReason: ${genStopReason || "end_turn"}`);
|
|
6618
6855
|
printSetupSummary(generatedSetup);
|
|
6619
6856
|
const sessionHistory = [];
|
|
@@ -6621,15 +6858,20 @@ async function initCommand(options) {
|
|
|
6621
6858
|
role: "assistant",
|
|
6622
6859
|
content: summarizeSetup("Initial generation", generatedSetup)
|
|
6623
6860
|
});
|
|
6624
|
-
console.log(title.bold(" Step 4
|
|
6861
|
+
console.log(title.bold(" Step 3/4 \u2014 Review\n"));
|
|
6625
6862
|
const setupFiles = collectSetupFiles(generatedSetup, targetAgent);
|
|
6626
6863
|
const staged = stageFiles(setupFiles, process.cwd());
|
|
6627
6864
|
const totalChanges = staged.newFiles + staged.modifiedFiles;
|
|
6628
|
-
console.log(
|
|
6865
|
+
console.log(chalk10.dim(` ${chalk10.green(`${staged.newFiles} new`)} / ${chalk10.yellow(`${staged.modifiedFiles} modified`)} file${totalChanges !== 1 ? "s" : ""}`));
|
|
6866
|
+
if (skillSearchResult.results.length > 0) {
|
|
6867
|
+
console.log(chalk10.dim(` ${chalk10.cyan(`${skillSearchResult.results.length}`)} community skills available to install
|
|
6629
6868
|
`));
|
|
6869
|
+
} else {
|
|
6870
|
+
console.log("");
|
|
6871
|
+
}
|
|
6630
6872
|
let action;
|
|
6631
|
-
if (totalChanges === 0) {
|
|
6632
|
-
console.log(
|
|
6873
|
+
if (totalChanges === 0 && skillSearchResult.results.length === 0) {
|
|
6874
|
+
console.log(chalk10.dim(" No changes needed \u2014 your configs are already up to date.\n"));
|
|
6633
6875
|
cleanupStaging();
|
|
6634
6876
|
action = "accept";
|
|
6635
6877
|
} else if (options.autoApprove) {
|
|
@@ -6637,13 +6879,15 @@ async function initCommand(options) {
|
|
|
6637
6879
|
action = "accept";
|
|
6638
6880
|
trackInitReviewAction(action, "auto-approved");
|
|
6639
6881
|
} else {
|
|
6640
|
-
|
|
6641
|
-
|
|
6642
|
-
|
|
6643
|
-
|
|
6882
|
+
if (totalChanges > 0) {
|
|
6883
|
+
const wantsReview = await promptWantsReview();
|
|
6884
|
+
if (wantsReview) {
|
|
6885
|
+
const reviewMethod = await promptReviewMethod();
|
|
6886
|
+
await openReview(reviewMethod, staged.stagedFiles);
|
|
6887
|
+
}
|
|
6644
6888
|
}
|
|
6645
6889
|
action = await promptReviewAction();
|
|
6646
|
-
trackInitReviewAction(action,
|
|
6890
|
+
trackInitReviewAction(action, totalChanges > 0 ? "reviewed" : "skipped");
|
|
6647
6891
|
}
|
|
6648
6892
|
let refinementRound = 0;
|
|
6649
6893
|
while (action === "refine") {
|
|
@@ -6652,12 +6896,12 @@ async function initCommand(options) {
|
|
|
6652
6896
|
trackInitRefinementRound(refinementRound, !!generatedSetup);
|
|
6653
6897
|
if (!generatedSetup) {
|
|
6654
6898
|
cleanupStaging();
|
|
6655
|
-
console.log(
|
|
6899
|
+
console.log(chalk10.dim("Refinement cancelled. No files were modified."));
|
|
6656
6900
|
return;
|
|
6657
6901
|
}
|
|
6658
6902
|
const updatedFiles = collectSetupFiles(generatedSetup, targetAgent);
|
|
6659
6903
|
const restaged = stageFiles(updatedFiles, process.cwd());
|
|
6660
|
-
console.log(
|
|
6904
|
+
console.log(chalk10.dim(` ${chalk10.green(`${restaged.newFiles} new`)} / ${chalk10.yellow(`${restaged.modifiedFiles} modified`)} file${restaged.newFiles + restaged.modifiedFiles !== 1 ? "s" : ""}
|
|
6661
6905
|
`));
|
|
6662
6906
|
printSetupSummary(generatedSetup);
|
|
6663
6907
|
await openReview("terminal", restaged.stagedFiles);
|
|
@@ -6666,11 +6910,12 @@ async function initCommand(options) {
|
|
|
6666
6910
|
}
|
|
6667
6911
|
cleanupStaging();
|
|
6668
6912
|
if (action === "decline") {
|
|
6669
|
-
console.log(
|
|
6913
|
+
console.log(chalk10.dim("Setup declined. No files were modified."));
|
|
6670
6914
|
return;
|
|
6671
6915
|
}
|
|
6916
|
+
console.log(title.bold("\n Step 4/4 \u2014 Finalize\n"));
|
|
6672
6917
|
if (options.dryRun) {
|
|
6673
|
-
console.log(
|
|
6918
|
+
console.log(chalk10.yellow("\n[Dry run] Would write the following files:"));
|
|
6674
6919
|
console.log(JSON.stringify(generatedSetup, null, 2));
|
|
6675
6920
|
return;
|
|
6676
6921
|
}
|
|
@@ -6699,85 +6944,45 @@ ${agentRefs.join(" ")}
|
|
|
6699
6944
|
0,
|
|
6700
6945
|
result.deleted.length
|
|
6701
6946
|
);
|
|
6702
|
-
console.log(
|
|
6947
|
+
console.log(chalk10.bold("\nFiles created/updated:"));
|
|
6703
6948
|
for (const file of result.written) {
|
|
6704
|
-
console.log(` ${
|
|
6949
|
+
console.log(` ${chalk10.green("\u2713")} ${file}`);
|
|
6705
6950
|
}
|
|
6706
6951
|
if (result.deleted.length > 0) {
|
|
6707
|
-
console.log(
|
|
6952
|
+
console.log(chalk10.bold("\nFiles removed:"));
|
|
6708
6953
|
for (const file of result.deleted) {
|
|
6709
|
-
console.log(` ${
|
|
6954
|
+
console.log(` ${chalk10.red("\u2717")} ${file}`);
|
|
6710
6955
|
}
|
|
6711
6956
|
}
|
|
6712
6957
|
if (result.backupDir) {
|
|
6713
|
-
console.log(
|
|
6958
|
+
console.log(chalk10.dim(`
|
|
6714
6959
|
Backups saved to ${result.backupDir}`));
|
|
6715
6960
|
}
|
|
6716
6961
|
} catch (err) {
|
|
6717
6962
|
writeSpinner.fail("Failed to write files");
|
|
6718
|
-
console.error(
|
|
6963
|
+
console.error(chalk10.red(err instanceof Error ? err.message : "Unknown error"));
|
|
6719
6964
|
throw new Error("__exit__");
|
|
6720
6965
|
}
|
|
6721
|
-
ensurePermissions(fingerprint);
|
|
6966
|
+
if (fingerprint) ensurePermissions(fingerprint);
|
|
6722
6967
|
const sha = getCurrentHeadSha();
|
|
6723
6968
|
writeState({
|
|
6724
6969
|
lastRefreshSha: sha ?? "",
|
|
6725
6970
|
lastRefreshTimestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
6726
6971
|
targetAgent
|
|
6727
6972
|
});
|
|
6728
|
-
console.log("");
|
|
6729
|
-
console.log(chalk9.dim(" Auto-refresh: keep your configs in sync as your code changes.\n"));
|
|
6730
|
-
let hookChoice;
|
|
6731
|
-
if (options.autoApprove) {
|
|
6732
|
-
hookChoice = "skip";
|
|
6733
|
-
log(options.verbose, "Auto-approve: skipping hook installation");
|
|
6734
|
-
} else {
|
|
6735
|
-
hookChoice = await promptHookType(targetAgent);
|
|
6736
|
-
}
|
|
6737
|
-
trackInitHookSelected(hookChoice);
|
|
6738
|
-
if (hookChoice === "claude" || hookChoice === "both") {
|
|
6739
|
-
const hookResult = installHook();
|
|
6740
|
-
if (hookResult.installed) {
|
|
6741
|
-
console.log(` ${chalk9.green("\u2713")} Claude Code hook installed \u2014 docs update on session end`);
|
|
6742
|
-
console.log(chalk9.dim(" Run ") + chalk9.hex("#83D1EB")("caliber hooks --remove") + chalk9.dim(" to disable"));
|
|
6743
|
-
} else if (hookResult.alreadyInstalled) {
|
|
6744
|
-
console.log(chalk9.dim(" Claude Code hook already installed"));
|
|
6745
|
-
}
|
|
6746
|
-
const learnResult = installLearningHooks();
|
|
6747
|
-
if (learnResult.installed) {
|
|
6748
|
-
console.log(` ${chalk9.green("\u2713")} Learning hooks installed \u2014 session insights captured automatically`);
|
|
6749
|
-
console.log(chalk9.dim(" Run ") + chalk9.hex("#83D1EB")("caliber learn remove") + chalk9.dim(" to disable"));
|
|
6750
|
-
} else if (learnResult.alreadyInstalled) {
|
|
6751
|
-
console.log(chalk9.dim(" Learning hooks already installed"));
|
|
6752
|
-
}
|
|
6753
|
-
}
|
|
6754
|
-
if (hookChoice === "precommit" || hookChoice === "both") {
|
|
6755
|
-
const precommitResult = installPreCommitHook();
|
|
6756
|
-
if (precommitResult.installed) {
|
|
6757
|
-
console.log(` ${chalk9.green("\u2713")} Pre-commit hook installed \u2014 docs refresh before each commit`);
|
|
6758
|
-
console.log(chalk9.dim(" Run ") + chalk9.hex("#83D1EB")("caliber hooks --remove") + chalk9.dim(" to disable"));
|
|
6759
|
-
} else if (precommitResult.alreadyInstalled) {
|
|
6760
|
-
console.log(chalk9.dim(" Pre-commit hook already installed"));
|
|
6761
|
-
} else {
|
|
6762
|
-
console.log(chalk9.yellow(" Could not install pre-commit hook (not a git repository?)"));
|
|
6763
|
-
}
|
|
6764
|
-
}
|
|
6765
|
-
if (hookChoice === "skip") {
|
|
6766
|
-
console.log(chalk9.dim(" Skipped auto-refresh hooks. Run ") + chalk9.hex("#83D1EB")("caliber hooks --install") + chalk9.dim(" later to enable."));
|
|
6767
|
-
}
|
|
6768
6973
|
const afterScore = computeLocalScore(process.cwd(), targetAgent);
|
|
6769
6974
|
if (afterScore.score < baselineScore.score) {
|
|
6770
6975
|
trackInitScoreRegression(baselineScore.score, afterScore.score);
|
|
6771
6976
|
console.log("");
|
|
6772
|
-
console.log(
|
|
6977
|
+
console.log(chalk10.yellow(` Score would drop from ${baselineScore.score} to ${afterScore.score} \u2014 reverting changes.`));
|
|
6773
6978
|
try {
|
|
6774
6979
|
const { restored, removed } = undoSetup();
|
|
6775
6980
|
if (restored.length > 0 || removed.length > 0) {
|
|
6776
|
-
console.log(
|
|
6981
|
+
console.log(chalk10.dim(` Reverted ${restored.length + removed.length} file${restored.length + removed.length === 1 ? "" : "s"} from backup.`));
|
|
6777
6982
|
}
|
|
6778
6983
|
} catch {
|
|
6779
6984
|
}
|
|
6780
|
-
console.log(
|
|
6985
|
+
console.log(chalk10.dim(" Run ") + chalk10.hex("#83D1EB")("caliber init --force") + chalk10.dim(" to override.\n"));
|
|
6781
6986
|
return;
|
|
6782
6987
|
}
|
|
6783
6988
|
if (report) {
|
|
@@ -6795,39 +7000,57 @@ ${agentRefs.join(" ")}
|
|
|
6795
7000
|
log(options.verbose, ` Still failing: ${c.name} (${c.earnedPoints}/${c.maxPoints})${c.suggestion ? ` \u2014 ${c.suggestion}` : ""}`);
|
|
6796
7001
|
}
|
|
6797
7002
|
}
|
|
6798
|
-
|
|
6799
|
-
|
|
6800
|
-
|
|
7003
|
+
if (skillSearchResult.results.length > 0 && !options.autoApprove) {
|
|
7004
|
+
console.log(chalk10.dim(" Community skills matched to your project:\n"));
|
|
7005
|
+
const selected = await interactiveSelect(skillSearchResult.results);
|
|
7006
|
+
if (selected?.length) {
|
|
7007
|
+
await installSkills(selected, targetAgent, skillSearchResult.contentMap);
|
|
7008
|
+
trackInitSkillsSearch(true, selected.length);
|
|
7009
|
+
}
|
|
7010
|
+
}
|
|
7011
|
+
console.log("");
|
|
7012
|
+
let hookChoice;
|
|
6801
7013
|
if (options.autoApprove) {
|
|
6802
|
-
|
|
6803
|
-
log(options.verbose, "Auto-approve: skipping
|
|
7014
|
+
hookChoice = "skip";
|
|
7015
|
+
log(options.verbose, "Auto-approve: skipping hook installation");
|
|
6804
7016
|
} else {
|
|
6805
|
-
|
|
6806
|
-
message: "Search public repos for relevant skills to add to this project?",
|
|
6807
|
-
choices: [
|
|
6808
|
-
{ name: "Yes, find skills for my project", value: true },
|
|
6809
|
-
{ name: "Skip for now", value: false }
|
|
6810
|
-
]
|
|
6811
|
-
});
|
|
7017
|
+
hookChoice = await promptHookType(targetAgent);
|
|
6812
7018
|
}
|
|
6813
|
-
|
|
6814
|
-
|
|
6815
|
-
|
|
6816
|
-
|
|
6817
|
-
|
|
6818
|
-
|
|
6819
|
-
|
|
6820
|
-
|
|
6821
|
-
console.log(chalk9.dim(" Run ") + chalk9.hex("#83D1EB")("caliber skills") + chalk9.dim(" later to try again.\n"));
|
|
7019
|
+
trackInitHookSelected(hookChoice);
|
|
7020
|
+
if (hookChoice === "claude" || hookChoice === "both") {
|
|
7021
|
+
const hookResult = installHook();
|
|
7022
|
+
if (hookResult.installed) {
|
|
7023
|
+
console.log(` ${chalk10.green("\u2713")} Claude Code hook installed \u2014 docs update on session end`);
|
|
7024
|
+
console.log(chalk10.dim(" Run ") + chalk10.hex("#83D1EB")("caliber hooks --remove") + chalk10.dim(" to disable"));
|
|
7025
|
+
} else if (hookResult.alreadyInstalled) {
|
|
7026
|
+
console.log(chalk10.dim(" Claude Code hook already installed"));
|
|
6822
7027
|
}
|
|
6823
|
-
|
|
6824
|
-
|
|
6825
|
-
|
|
7028
|
+
const learnResult = installLearningHooks();
|
|
7029
|
+
if (learnResult.installed) {
|
|
7030
|
+
console.log(` ${chalk10.green("\u2713")} Learning hooks installed \u2014 session insights captured automatically`);
|
|
7031
|
+
console.log(chalk10.dim(" Run ") + chalk10.hex("#83D1EB")("caliber learn remove") + chalk10.dim(" to disable"));
|
|
7032
|
+
} else if (learnResult.alreadyInstalled) {
|
|
7033
|
+
console.log(chalk10.dim(" Learning hooks already installed"));
|
|
7034
|
+
}
|
|
7035
|
+
}
|
|
7036
|
+
if (hookChoice === "precommit" || hookChoice === "both") {
|
|
7037
|
+
const precommitResult = installPreCommitHook();
|
|
7038
|
+
if (precommitResult.installed) {
|
|
7039
|
+
console.log(` ${chalk10.green("\u2713")} Pre-commit hook installed \u2014 docs refresh before each commit`);
|
|
7040
|
+
console.log(chalk10.dim(" Run ") + chalk10.hex("#83D1EB")("caliber hooks --remove") + chalk10.dim(" to disable"));
|
|
7041
|
+
} else if (precommitResult.alreadyInstalled) {
|
|
7042
|
+
console.log(chalk10.dim(" Pre-commit hook already installed"));
|
|
7043
|
+
} else {
|
|
7044
|
+
console.log(chalk10.yellow(" Could not install pre-commit hook (not a git repository?)"));
|
|
7045
|
+
}
|
|
7046
|
+
}
|
|
7047
|
+
if (hookChoice === "skip") {
|
|
7048
|
+
console.log(chalk10.dim(" Skipped auto-sync hooks. Run ") + chalk10.hex("#83D1EB")("caliber hooks --install") + chalk10.dim(" later to enable."));
|
|
6826
7049
|
}
|
|
6827
|
-
console.log(
|
|
6828
|
-
console.log(
|
|
6829
|
-
console.log(
|
|
6830
|
-
console.log(
|
|
7050
|
+
console.log(chalk10.bold.green("\n Setup complete!"));
|
|
7051
|
+
console.log(chalk10.dim(" Your AI agents now understand your project's architecture, build commands,"));
|
|
7052
|
+
console.log(chalk10.dim(" testing patterns, and conventions. All changes are backed up automatically.\n"));
|
|
7053
|
+
console.log(chalk10.bold(" Next steps:\n"));
|
|
6831
7054
|
console.log(` ${title("caliber score")} See your full config breakdown`);
|
|
6832
7055
|
console.log(` ${title("caliber refresh")} Update docs after code changes`);
|
|
6833
7056
|
console.log(` ${title("caliber hooks")} Toggle auto-refresh hooks`);
|
|
@@ -6841,7 +7064,7 @@ ${agentRefs.join(" ")}
|
|
|
6841
7064
|
report.markStep("Finished");
|
|
6842
7065
|
const reportPath = path19.join(process.cwd(), ".caliber", "debug-report.md");
|
|
6843
7066
|
report.write(reportPath);
|
|
6844
|
-
console.log(
|
|
7067
|
+
console.log(chalk10.dim(` Debug report written to ${path19.relative(process.cwd(), reportPath)}
|
|
6845
7068
|
`));
|
|
6846
7069
|
}
|
|
6847
7070
|
}
|
|
@@ -6856,9 +7079,9 @@ async function refineLoop(currentSetup, _targetAgent, sessionHistory) {
|
|
|
6856
7079
|
}
|
|
6857
7080
|
const isValid = await classifyRefineIntent(message);
|
|
6858
7081
|
if (!isValid) {
|
|
6859
|
-
console.log(
|
|
6860
|
-
console.log(
|
|
6861
|
-
console.log(
|
|
7082
|
+
console.log(chalk10.dim(" This doesn't look like a config change request."));
|
|
7083
|
+
console.log(chalk10.dim(" Describe what to add, remove, or modify in your configs."));
|
|
7084
|
+
console.log(chalk10.dim(' Type "done" to accept the current setup.\n'));
|
|
6862
7085
|
continue;
|
|
6863
7086
|
}
|
|
6864
7087
|
const refineSpinner = ora2("Refining setup...").start();
|
|
@@ -6879,10 +7102,10 @@ async function refineLoop(currentSetup, _targetAgent, sessionHistory) {
|
|
|
6879
7102
|
});
|
|
6880
7103
|
refineSpinner.succeed("Setup updated");
|
|
6881
7104
|
printSetupSummary(refined);
|
|
6882
|
-
console.log(
|
|
7105
|
+
console.log(chalk10.dim('Type "done" to accept, or describe more changes.'));
|
|
6883
7106
|
} else {
|
|
6884
7107
|
refineSpinner.fail("Refinement failed \u2014 could not parse AI response.");
|
|
6885
|
-
console.log(
|
|
7108
|
+
console.log(chalk10.dim('Try rephrasing your request, or type "done" to keep the current setup.'));
|
|
6886
7109
|
}
|
|
6887
7110
|
}
|
|
6888
7111
|
}
|
|
@@ -6910,6 +7133,7 @@ Return {"valid": true} or {"valid": false}. Nothing else.`,
|
|
|
6910
7133
|
}
|
|
6911
7134
|
}
|
|
6912
7135
|
async function evaluateDismissals(failingChecks, fingerprint) {
|
|
7136
|
+
if (failingChecks.length === 0) return [];
|
|
6913
7137
|
const fastModel = getFastModel();
|
|
6914
7138
|
const checkList = failingChecks.map((c) => ({
|
|
6915
7139
|
id: c.id,
|
|
@@ -6977,7 +7201,7 @@ async function promptHookType(targetAgent) {
|
|
|
6977
7201
|
}
|
|
6978
7202
|
choices.push({ name: "Skip for now", value: "skip" });
|
|
6979
7203
|
return select5({
|
|
6980
|
-
message: "
|
|
7204
|
+
message: "Keep your AI docs & skills in sync as your code evolves?",
|
|
6981
7205
|
choices
|
|
6982
7206
|
});
|
|
6983
7207
|
}
|
|
@@ -6997,26 +7221,26 @@ function printSetupSummary(setup) {
|
|
|
6997
7221
|
const fileDescriptions = setup.fileDescriptions;
|
|
6998
7222
|
const deletions = setup.deletions;
|
|
6999
7223
|
console.log("");
|
|
7000
|
-
console.log(
|
|
7224
|
+
console.log(chalk10.bold(" Proposed changes:\n"));
|
|
7001
7225
|
const getDescription = (filePath) => {
|
|
7002
7226
|
return fileDescriptions?.[filePath];
|
|
7003
7227
|
};
|
|
7004
7228
|
if (claude) {
|
|
7005
7229
|
if (claude.claudeMd) {
|
|
7006
|
-
const icon = fs24.existsSync("CLAUDE.md") ?
|
|
7230
|
+
const icon = fs24.existsSync("CLAUDE.md") ? chalk10.yellow("~") : chalk10.green("+");
|
|
7007
7231
|
const desc = getDescription("CLAUDE.md");
|
|
7008
|
-
console.log(` ${icon} ${
|
|
7009
|
-
if (desc) console.log(
|
|
7232
|
+
console.log(` ${icon} ${chalk10.bold("CLAUDE.md")}`);
|
|
7233
|
+
if (desc) console.log(chalk10.dim(` ${desc}`));
|
|
7010
7234
|
console.log("");
|
|
7011
7235
|
}
|
|
7012
7236
|
const skills = claude.skills;
|
|
7013
7237
|
if (Array.isArray(skills) && skills.length > 0) {
|
|
7014
7238
|
for (const skill of skills) {
|
|
7015
7239
|
const skillPath = `.claude/skills/${skill.name}/SKILL.md`;
|
|
7016
|
-
const icon = fs24.existsSync(skillPath) ?
|
|
7240
|
+
const icon = fs24.existsSync(skillPath) ? chalk10.yellow("~") : chalk10.green("+");
|
|
7017
7241
|
const desc = getDescription(skillPath);
|
|
7018
|
-
console.log(` ${icon} ${
|
|
7019
|
-
console.log(
|
|
7242
|
+
console.log(` ${icon} ${chalk10.bold(skillPath)}`);
|
|
7243
|
+
console.log(chalk10.dim(` ${desc || skill.description || skill.name}`));
|
|
7020
7244
|
console.log("");
|
|
7021
7245
|
}
|
|
7022
7246
|
}
|
|
@@ -7024,40 +7248,40 @@ function printSetupSummary(setup) {
|
|
|
7024
7248
|
const codex = setup.codex;
|
|
7025
7249
|
if (codex) {
|
|
7026
7250
|
if (codex.agentsMd) {
|
|
7027
|
-
const icon = fs24.existsSync("AGENTS.md") ?
|
|
7251
|
+
const icon = fs24.existsSync("AGENTS.md") ? chalk10.yellow("~") : chalk10.green("+");
|
|
7028
7252
|
const desc = getDescription("AGENTS.md");
|
|
7029
|
-
console.log(` ${icon} ${
|
|
7030
|
-
if (desc) console.log(
|
|
7253
|
+
console.log(` ${icon} ${chalk10.bold("AGENTS.md")}`);
|
|
7254
|
+
if (desc) console.log(chalk10.dim(` ${desc}`));
|
|
7031
7255
|
console.log("");
|
|
7032
7256
|
}
|
|
7033
7257
|
const codexSkills = codex.skills;
|
|
7034
7258
|
if (Array.isArray(codexSkills) && codexSkills.length > 0) {
|
|
7035
7259
|
for (const skill of codexSkills) {
|
|
7036
7260
|
const skillPath = `.agents/skills/${skill.name}/SKILL.md`;
|
|
7037
|
-
const icon = fs24.existsSync(skillPath) ?
|
|
7261
|
+
const icon = fs24.existsSync(skillPath) ? chalk10.yellow("~") : chalk10.green("+");
|
|
7038
7262
|
const desc = getDescription(skillPath);
|
|
7039
|
-
console.log(` ${icon} ${
|
|
7040
|
-
console.log(
|
|
7263
|
+
console.log(` ${icon} ${chalk10.bold(skillPath)}`);
|
|
7264
|
+
console.log(chalk10.dim(` ${desc || skill.description || skill.name}`));
|
|
7041
7265
|
console.log("");
|
|
7042
7266
|
}
|
|
7043
7267
|
}
|
|
7044
7268
|
}
|
|
7045
7269
|
if (cursor) {
|
|
7046
7270
|
if (cursor.cursorrules) {
|
|
7047
|
-
const icon = fs24.existsSync(".cursorrules") ?
|
|
7271
|
+
const icon = fs24.existsSync(".cursorrules") ? chalk10.yellow("~") : chalk10.green("+");
|
|
7048
7272
|
const desc = getDescription(".cursorrules");
|
|
7049
|
-
console.log(` ${icon} ${
|
|
7050
|
-
if (desc) console.log(
|
|
7273
|
+
console.log(` ${icon} ${chalk10.bold(".cursorrules")}`);
|
|
7274
|
+
if (desc) console.log(chalk10.dim(` ${desc}`));
|
|
7051
7275
|
console.log("");
|
|
7052
7276
|
}
|
|
7053
7277
|
const cursorSkills = cursor.skills;
|
|
7054
7278
|
if (Array.isArray(cursorSkills) && cursorSkills.length > 0) {
|
|
7055
7279
|
for (const skill of cursorSkills) {
|
|
7056
7280
|
const skillPath = `.cursor/skills/${skill.name}/SKILL.md`;
|
|
7057
|
-
const icon = fs24.existsSync(skillPath) ?
|
|
7281
|
+
const icon = fs24.existsSync(skillPath) ? chalk10.yellow("~") : chalk10.green("+");
|
|
7058
7282
|
const desc = getDescription(skillPath);
|
|
7059
|
-
console.log(` ${icon} ${
|
|
7060
|
-
console.log(
|
|
7283
|
+
console.log(` ${icon} ${chalk10.bold(skillPath)}`);
|
|
7284
|
+
console.log(chalk10.dim(` ${desc || skill.description || skill.name}`));
|
|
7061
7285
|
console.log("");
|
|
7062
7286
|
}
|
|
7063
7287
|
}
|
|
@@ -7065,14 +7289,14 @@ function printSetupSummary(setup) {
|
|
|
7065
7289
|
if (Array.isArray(rules) && rules.length > 0) {
|
|
7066
7290
|
for (const rule of rules) {
|
|
7067
7291
|
const rulePath = `.cursor/rules/${rule.filename}`;
|
|
7068
|
-
const icon = fs24.existsSync(rulePath) ?
|
|
7292
|
+
const icon = fs24.existsSync(rulePath) ? chalk10.yellow("~") : chalk10.green("+");
|
|
7069
7293
|
const desc = getDescription(rulePath);
|
|
7070
|
-
console.log(` ${icon} ${
|
|
7294
|
+
console.log(` ${icon} ${chalk10.bold(rulePath)}`);
|
|
7071
7295
|
if (desc) {
|
|
7072
|
-
console.log(
|
|
7296
|
+
console.log(chalk10.dim(` ${desc}`));
|
|
7073
7297
|
} else {
|
|
7074
7298
|
const firstLine = rule.content.split("\n").filter((l) => l.trim() && !l.trim().startsWith("#"))[0];
|
|
7075
|
-
if (firstLine) console.log(
|
|
7299
|
+
if (firstLine) console.log(chalk10.dim(` ${firstLine.trim().slice(0, 80)}`));
|
|
7076
7300
|
}
|
|
7077
7301
|
console.log("");
|
|
7078
7302
|
}
|
|
@@ -7080,12 +7304,12 @@ function printSetupSummary(setup) {
|
|
|
7080
7304
|
}
|
|
7081
7305
|
if (Array.isArray(deletions) && deletions.length > 0) {
|
|
7082
7306
|
for (const del of deletions) {
|
|
7083
|
-
console.log(` ${
|
|
7084
|
-
console.log(
|
|
7307
|
+
console.log(` ${chalk10.red("-")} ${chalk10.bold(del.filePath)}`);
|
|
7308
|
+
console.log(chalk10.dim(` ${del.reason}`));
|
|
7085
7309
|
console.log("");
|
|
7086
7310
|
}
|
|
7087
7311
|
}
|
|
7088
|
-
console.log(` ${
|
|
7312
|
+
console.log(` ${chalk10.green("+")} ${chalk10.dim("new")} ${chalk10.yellow("~")} ${chalk10.dim("modified")} ${chalk10.red("-")} ${chalk10.dim("removed")}`);
|
|
7089
7313
|
console.log("");
|
|
7090
7314
|
}
|
|
7091
7315
|
function derivePermissions(fingerprint) {
|
|
@@ -7145,20 +7369,20 @@ function ensurePermissions(fingerprint) {
|
|
|
7145
7369
|
function displayTokenUsage() {
|
|
7146
7370
|
const summary = getUsageSummary();
|
|
7147
7371
|
if (summary.length === 0) {
|
|
7148
|
-
console.log(
|
|
7372
|
+
console.log(chalk10.dim(" Token tracking not available for this provider.\n"));
|
|
7149
7373
|
return;
|
|
7150
7374
|
}
|
|
7151
|
-
console.log(
|
|
7375
|
+
console.log(chalk10.bold(" Token usage:\n"));
|
|
7152
7376
|
let totalIn = 0;
|
|
7153
7377
|
let totalOut = 0;
|
|
7154
7378
|
for (const m of summary) {
|
|
7155
7379
|
totalIn += m.inputTokens;
|
|
7156
7380
|
totalOut += m.outputTokens;
|
|
7157
|
-
const cacheInfo = m.cacheReadTokens > 0 || m.cacheWriteTokens > 0 ?
|
|
7158
|
-
console.log(` ${
|
|
7381
|
+
const cacheInfo = m.cacheReadTokens > 0 || m.cacheWriteTokens > 0 ? chalk10.dim(` (cache: ${m.cacheReadTokens.toLocaleString()} read, ${m.cacheWriteTokens.toLocaleString()} write)`) : "";
|
|
7382
|
+
console.log(` ${chalk10.dim(m.model)}: ${m.inputTokens.toLocaleString()} in / ${m.outputTokens.toLocaleString()} out (${m.calls} call${m.calls === 1 ? "" : "s"})${cacheInfo}`);
|
|
7159
7383
|
}
|
|
7160
7384
|
if (summary.length > 1) {
|
|
7161
|
-
console.log(` ${
|
|
7385
|
+
console.log(` ${chalk10.dim("Total")}: ${totalIn.toLocaleString()} in / ${totalOut.toLocaleString()} out`);
|
|
7162
7386
|
}
|
|
7163
7387
|
console.log("");
|
|
7164
7388
|
}
|
|
@@ -7179,14 +7403,14 @@ function writeErrorLog(config, rawOutput, error, stopReason) {
|
|
|
7179
7403
|
lines.push("## Raw LLM Output", "```", rawOutput || "(empty)", "```");
|
|
7180
7404
|
fs24.mkdirSync(path19.join(process.cwd(), ".caliber"), { recursive: true });
|
|
7181
7405
|
fs24.writeFileSync(logPath, lines.join("\n"));
|
|
7182
|
-
console.log(
|
|
7406
|
+
console.log(chalk10.dim(`
|
|
7183
7407
|
Error log written to .caliber/error-log.md`));
|
|
7184
7408
|
} catch {
|
|
7185
7409
|
}
|
|
7186
7410
|
}
|
|
7187
7411
|
|
|
7188
7412
|
// src/commands/undo.ts
|
|
7189
|
-
import
|
|
7413
|
+
import chalk11 from "chalk";
|
|
7190
7414
|
import ora3 from "ora";
|
|
7191
7415
|
function undoCommand() {
|
|
7192
7416
|
const spinner = ora3("Reverting setup...").start();
|
|
@@ -7199,26 +7423,26 @@ function undoCommand() {
|
|
|
7199
7423
|
trackUndoExecuted();
|
|
7200
7424
|
spinner.succeed("Setup reverted successfully.\n");
|
|
7201
7425
|
if (restored.length > 0) {
|
|
7202
|
-
console.log(
|
|
7426
|
+
console.log(chalk11.cyan(" Restored from backup:"));
|
|
7203
7427
|
for (const file of restored) {
|
|
7204
|
-
console.log(` ${
|
|
7428
|
+
console.log(` ${chalk11.green("\u21A9")} ${file}`);
|
|
7205
7429
|
}
|
|
7206
7430
|
}
|
|
7207
7431
|
if (removed.length > 0) {
|
|
7208
|
-
console.log(
|
|
7432
|
+
console.log(chalk11.cyan(" Removed:"));
|
|
7209
7433
|
for (const file of removed) {
|
|
7210
|
-
console.log(` ${
|
|
7434
|
+
console.log(` ${chalk11.red("\u2717")} ${file}`);
|
|
7211
7435
|
}
|
|
7212
7436
|
}
|
|
7213
7437
|
console.log("");
|
|
7214
7438
|
} catch (err) {
|
|
7215
|
-
spinner.fail(
|
|
7439
|
+
spinner.fail(chalk11.red(err instanceof Error ? err.message : "Undo failed"));
|
|
7216
7440
|
throw new Error("__exit__");
|
|
7217
7441
|
}
|
|
7218
7442
|
}
|
|
7219
7443
|
|
|
7220
7444
|
// src/commands/status.ts
|
|
7221
|
-
import
|
|
7445
|
+
import chalk12 from "chalk";
|
|
7222
7446
|
import fs25 from "fs";
|
|
7223
7447
|
init_config();
|
|
7224
7448
|
async function statusCommand(options) {
|
|
@@ -7233,40 +7457,40 @@ async function statusCommand(options) {
|
|
|
7233
7457
|
}, null, 2));
|
|
7234
7458
|
return;
|
|
7235
7459
|
}
|
|
7236
|
-
console.log(
|
|
7460
|
+
console.log(chalk12.bold("\nCaliber Status\n"));
|
|
7237
7461
|
if (config) {
|
|
7238
|
-
console.log(` LLM: ${
|
|
7462
|
+
console.log(` LLM: ${chalk12.green(config.provider)} (${config.model})`);
|
|
7239
7463
|
} else {
|
|
7240
|
-
console.log(` LLM: ${
|
|
7464
|
+
console.log(` LLM: ${chalk12.yellow("Not configured")} \u2014 run ${chalk12.hex("#83D1EB")("caliber config")}`);
|
|
7241
7465
|
}
|
|
7242
7466
|
if (!manifest) {
|
|
7243
|
-
console.log(` Setup: ${
|
|
7244
|
-
console.log(
|
|
7467
|
+
console.log(` Setup: ${chalk12.dim("No setup applied")}`);
|
|
7468
|
+
console.log(chalk12.dim("\n Run ") + chalk12.hex("#83D1EB")("caliber init") + chalk12.dim(" to get started.\n"));
|
|
7245
7469
|
return;
|
|
7246
7470
|
}
|
|
7247
|
-
console.log(` Files managed: ${
|
|
7471
|
+
console.log(` Files managed: ${chalk12.cyan(manifest.entries.length.toString())}`);
|
|
7248
7472
|
for (const entry of manifest.entries) {
|
|
7249
7473
|
const exists = fs25.existsSync(entry.path);
|
|
7250
|
-
const icon = exists ?
|
|
7474
|
+
const icon = exists ? chalk12.green("\u2713") : chalk12.red("\u2717");
|
|
7251
7475
|
console.log(` ${icon} ${entry.path} (${entry.action})`);
|
|
7252
7476
|
}
|
|
7253
7477
|
console.log("");
|
|
7254
7478
|
}
|
|
7255
7479
|
|
|
7256
7480
|
// src/commands/regenerate.ts
|
|
7257
|
-
import
|
|
7481
|
+
import chalk13 from "chalk";
|
|
7258
7482
|
import ora4 from "ora";
|
|
7259
7483
|
import select6 from "@inquirer/select";
|
|
7260
7484
|
init_config();
|
|
7261
7485
|
async function regenerateCommand(options) {
|
|
7262
7486
|
const config = loadConfig();
|
|
7263
7487
|
if (!config) {
|
|
7264
|
-
console.log(
|
|
7488
|
+
console.log(chalk13.red("No LLM provider configured. Run ") + chalk13.hex("#83D1EB")("caliber config") + chalk13.red(" first."));
|
|
7265
7489
|
throw new Error("__exit__");
|
|
7266
7490
|
}
|
|
7267
7491
|
const manifest = readManifest();
|
|
7268
7492
|
if (!manifest) {
|
|
7269
|
-
console.log(
|
|
7493
|
+
console.log(chalk13.yellow("No existing setup found. Run ") + chalk13.hex("#83D1EB")("caliber init") + chalk13.yellow(" first."));
|
|
7270
7494
|
throw new Error("__exit__");
|
|
7271
7495
|
}
|
|
7272
7496
|
const targetAgent = readState()?.targetAgent ?? ["claude", "cursor"];
|
|
@@ -7277,7 +7501,7 @@ async function regenerateCommand(options) {
|
|
|
7277
7501
|
const baselineScore = computeLocalScore(process.cwd(), targetAgent);
|
|
7278
7502
|
displayScoreSummary(baselineScore);
|
|
7279
7503
|
if (baselineScore.score === 100) {
|
|
7280
|
-
console.log(
|
|
7504
|
+
console.log(chalk13.green(" Your setup is already at 100/100 \u2014 nothing to regenerate.\n"));
|
|
7281
7505
|
return;
|
|
7282
7506
|
}
|
|
7283
7507
|
const genSpinner = ora4("Regenerating setup...").start();
|
|
@@ -7318,18 +7542,18 @@ async function regenerateCommand(options) {
|
|
|
7318
7542
|
const setupFiles = collectSetupFiles(generatedSetup, targetAgent);
|
|
7319
7543
|
const staged = stageFiles(setupFiles, process.cwd());
|
|
7320
7544
|
const totalChanges = staged.newFiles + staged.modifiedFiles;
|
|
7321
|
-
console.log(
|
|
7322
|
-
${
|
|
7545
|
+
console.log(chalk13.dim(`
|
|
7546
|
+
${chalk13.green(`${staged.newFiles} new`)} / ${chalk13.yellow(`${staged.modifiedFiles} modified`)} file${totalChanges !== 1 ? "s" : ""}
|
|
7323
7547
|
`));
|
|
7324
7548
|
if (totalChanges === 0) {
|
|
7325
|
-
console.log(
|
|
7549
|
+
console.log(chalk13.dim(" No changes needed \u2014 your configs are already up to date.\n"));
|
|
7326
7550
|
cleanupStaging();
|
|
7327
7551
|
return;
|
|
7328
7552
|
}
|
|
7329
7553
|
if (options.dryRun) {
|
|
7330
|
-
console.log(
|
|
7554
|
+
console.log(chalk13.yellow("[Dry run] Would write:"));
|
|
7331
7555
|
for (const f of staged.stagedFiles) {
|
|
7332
|
-
console.log(` ${f.isNew ?
|
|
7556
|
+
console.log(` ${f.isNew ? chalk13.green("+") : chalk13.yellow("~")} ${f.relativePath}`);
|
|
7333
7557
|
}
|
|
7334
7558
|
cleanupStaging();
|
|
7335
7559
|
return;
|
|
@@ -7348,7 +7572,7 @@ async function regenerateCommand(options) {
|
|
|
7348
7572
|
});
|
|
7349
7573
|
cleanupStaging();
|
|
7350
7574
|
if (action === "decline") {
|
|
7351
|
-
console.log(
|
|
7575
|
+
console.log(chalk13.dim("Regeneration cancelled. No files were modified."));
|
|
7352
7576
|
return;
|
|
7353
7577
|
}
|
|
7354
7578
|
const writeSpinner = ora4("Writing config files...").start();
|
|
@@ -7356,20 +7580,20 @@ async function regenerateCommand(options) {
|
|
|
7356
7580
|
const result = writeSetup(generatedSetup);
|
|
7357
7581
|
writeSpinner.succeed("Config files written");
|
|
7358
7582
|
for (const file of result.written) {
|
|
7359
|
-
console.log(` ${
|
|
7583
|
+
console.log(` ${chalk13.green("\u2713")} ${file}`);
|
|
7360
7584
|
}
|
|
7361
7585
|
if (result.deleted.length > 0) {
|
|
7362
7586
|
for (const file of result.deleted) {
|
|
7363
|
-
console.log(` ${
|
|
7587
|
+
console.log(` ${chalk13.red("\u2717")} ${file}`);
|
|
7364
7588
|
}
|
|
7365
7589
|
}
|
|
7366
7590
|
if (result.backupDir) {
|
|
7367
|
-
console.log(
|
|
7591
|
+
console.log(chalk13.dim(`
|
|
7368
7592
|
Backups saved to ${result.backupDir}`));
|
|
7369
7593
|
}
|
|
7370
7594
|
} catch (err) {
|
|
7371
7595
|
writeSpinner.fail("Failed to write files");
|
|
7372
|
-
console.error(
|
|
7596
|
+
console.error(chalk13.red(err instanceof Error ? err.message : "Unknown error"));
|
|
7373
7597
|
throw new Error("__exit__");
|
|
7374
7598
|
}
|
|
7375
7599
|
const sha = getCurrentHeadSha();
|
|
@@ -7381,25 +7605,25 @@ async function regenerateCommand(options) {
|
|
|
7381
7605
|
const afterScore = computeLocalScore(process.cwd(), targetAgent);
|
|
7382
7606
|
if (afterScore.score < baselineScore.score) {
|
|
7383
7607
|
console.log("");
|
|
7384
|
-
console.log(
|
|
7608
|
+
console.log(chalk13.yellow(` Score would drop from ${baselineScore.score} to ${afterScore.score} \u2014 reverting changes.`));
|
|
7385
7609
|
try {
|
|
7386
7610
|
const { restored, removed } = undoSetup();
|
|
7387
7611
|
if (restored.length > 0 || removed.length > 0) {
|
|
7388
|
-
console.log(
|
|
7612
|
+
console.log(chalk13.dim(` Reverted ${restored.length + removed.length} file${restored.length + removed.length === 1 ? "" : "s"} from backup.`));
|
|
7389
7613
|
}
|
|
7390
7614
|
} catch {
|
|
7391
7615
|
}
|
|
7392
|
-
console.log(
|
|
7616
|
+
console.log(chalk13.dim(" Run ") + chalk13.hex("#83D1EB")("caliber init --force") + chalk13.dim(" to override.\n"));
|
|
7393
7617
|
return;
|
|
7394
7618
|
}
|
|
7395
7619
|
displayScoreDelta(baselineScore, afterScore);
|
|
7396
7620
|
trackRegenerateCompleted(action, Date.now());
|
|
7397
|
-
console.log(
|
|
7398
|
-
console.log(
|
|
7621
|
+
console.log(chalk13.bold.green(" Regeneration complete!"));
|
|
7622
|
+
console.log(chalk13.dim(" Run ") + chalk13.hex("#83D1EB")("caliber undo") + chalk13.dim(" to revert changes.\n"));
|
|
7399
7623
|
}
|
|
7400
7624
|
|
|
7401
7625
|
// src/commands/score.ts
|
|
7402
|
-
import
|
|
7626
|
+
import chalk14 from "chalk";
|
|
7403
7627
|
async function scoreCommand(options) {
|
|
7404
7628
|
const dir = process.cwd();
|
|
7405
7629
|
const target = options.agent ?? readState()?.targetAgent;
|
|
@@ -7414,14 +7638,14 @@ async function scoreCommand(options) {
|
|
|
7414
7638
|
return;
|
|
7415
7639
|
}
|
|
7416
7640
|
displayScore(result);
|
|
7417
|
-
const separator =
|
|
7641
|
+
const separator = chalk14.gray(" " + "\u2500".repeat(53));
|
|
7418
7642
|
console.log(separator);
|
|
7419
7643
|
if (result.score < 40) {
|
|
7420
|
-
console.log(
|
|
7644
|
+
console.log(chalk14.gray(" Run ") + chalk14.hex("#83D1EB")("caliber init") + chalk14.gray(" to generate a complete, optimized setup."));
|
|
7421
7645
|
} else if (result.score < 70) {
|
|
7422
|
-
console.log(
|
|
7646
|
+
console.log(chalk14.gray(" Run ") + chalk14.hex("#83D1EB")("caliber init") + chalk14.gray(" to improve your setup."));
|
|
7423
7647
|
} else {
|
|
7424
|
-
console.log(
|
|
7648
|
+
console.log(chalk14.green(" Looking good!") + chalk14.gray(" Run ") + chalk14.hex("#83D1EB")("caliber regenerate") + chalk14.gray(" to rebuild from scratch."));
|
|
7425
7649
|
}
|
|
7426
7650
|
console.log("");
|
|
7427
7651
|
}
|
|
@@ -7429,7 +7653,7 @@ async function scoreCommand(options) {
|
|
|
7429
7653
|
// src/commands/refresh.ts
|
|
7430
7654
|
import fs29 from "fs";
|
|
7431
7655
|
import path23 from "path";
|
|
7432
|
-
import
|
|
7656
|
+
import chalk15 from "chalk";
|
|
7433
7657
|
import ora5 from "ora";
|
|
7434
7658
|
|
|
7435
7659
|
// src/lib/git-diff.ts
|
|
@@ -7772,7 +7996,7 @@ function discoverGitRepos(parentDir) {
|
|
|
7772
7996
|
}
|
|
7773
7997
|
async function refreshSingleRepo(repoDir, options) {
|
|
7774
7998
|
const quiet = !!options.quiet;
|
|
7775
|
-
const prefix = options.label ? `${
|
|
7999
|
+
const prefix = options.label ? `${chalk15.bold(options.label)} ` : "";
|
|
7776
8000
|
const state = readState();
|
|
7777
8001
|
const lastSha = state?.lastRefreshSha ?? null;
|
|
7778
8002
|
const diff = collectDiff(lastSha);
|
|
@@ -7781,7 +8005,7 @@ async function refreshSingleRepo(repoDir, options) {
|
|
|
7781
8005
|
if (currentSha) {
|
|
7782
8006
|
writeState({ lastRefreshSha: currentSha, lastRefreshTimestamp: (/* @__PURE__ */ new Date()).toISOString() });
|
|
7783
8007
|
}
|
|
7784
|
-
log2(quiet,
|
|
8008
|
+
log2(quiet, chalk15.dim(`${prefix}No changes since last refresh.`));
|
|
7785
8009
|
return;
|
|
7786
8010
|
}
|
|
7787
8011
|
const spinner = quiet ? null : ora5(`${prefix}Analyzing changes...`).start();
|
|
@@ -7815,10 +8039,10 @@ async function refreshSingleRepo(repoDir, options) {
|
|
|
7815
8039
|
if (options.dryRun) {
|
|
7816
8040
|
spinner?.info(`${prefix}Dry run \u2014 would update:`);
|
|
7817
8041
|
for (const doc of response.docsUpdated) {
|
|
7818
|
-
console.log(` ${
|
|
8042
|
+
console.log(` ${chalk15.yellow("~")} ${doc}`);
|
|
7819
8043
|
}
|
|
7820
8044
|
if (response.changesSummary) {
|
|
7821
|
-
console.log(
|
|
8045
|
+
console.log(chalk15.dim(`
|
|
7822
8046
|
${response.changesSummary}`));
|
|
7823
8047
|
}
|
|
7824
8048
|
return;
|
|
@@ -7827,10 +8051,10 @@ async function refreshSingleRepo(repoDir, options) {
|
|
|
7827
8051
|
trackRefreshCompleted(written.length, Date.now());
|
|
7828
8052
|
spinner?.succeed(`${prefix}Updated ${written.length} doc${written.length === 1 ? "" : "s"}`);
|
|
7829
8053
|
for (const file of written) {
|
|
7830
|
-
log2(quiet, ` ${
|
|
8054
|
+
log2(quiet, ` ${chalk15.green("\u2713")} ${file}`);
|
|
7831
8055
|
}
|
|
7832
8056
|
if (response.changesSummary) {
|
|
7833
|
-
log2(quiet,
|
|
8057
|
+
log2(quiet, chalk15.dim(`
|
|
7834
8058
|
${response.changesSummary}`));
|
|
7835
8059
|
}
|
|
7836
8060
|
if (currentSha) {
|
|
@@ -7847,7 +8071,7 @@ async function refreshCommand(options) {
|
|
|
7847
8071
|
const config = loadConfig();
|
|
7848
8072
|
if (!config) {
|
|
7849
8073
|
if (quiet) return;
|
|
7850
|
-
console.log(
|
|
8074
|
+
console.log(chalk15.red("No LLM provider configured. Run ") + chalk15.hex("#83D1EB")("caliber config") + chalk15.red(" (e.g. choose Cursor) or set an API key."));
|
|
7851
8075
|
throw new Error("__exit__");
|
|
7852
8076
|
}
|
|
7853
8077
|
await validateModel({ fast: true });
|
|
@@ -7858,10 +8082,10 @@ async function refreshCommand(options) {
|
|
|
7858
8082
|
const repos = discoverGitRepos(process.cwd());
|
|
7859
8083
|
if (repos.length === 0) {
|
|
7860
8084
|
if (quiet) return;
|
|
7861
|
-
console.log(
|
|
8085
|
+
console.log(chalk15.red("Not inside a git repository and no git repos found in child directories."));
|
|
7862
8086
|
throw new Error("__exit__");
|
|
7863
8087
|
}
|
|
7864
|
-
log2(quiet,
|
|
8088
|
+
log2(quiet, chalk15.dim(`Found ${repos.length} git repo${repos.length === 1 ? "" : "s"}
|
|
7865
8089
|
`));
|
|
7866
8090
|
const originalDir = process.cwd();
|
|
7867
8091
|
for (const repo of repos) {
|
|
@@ -7871,7 +8095,7 @@ async function refreshCommand(options) {
|
|
|
7871
8095
|
await refreshSingleRepo(repo, { ...options, label: repoName });
|
|
7872
8096
|
} catch (err) {
|
|
7873
8097
|
if (err instanceof Error && err.message === "__exit__") continue;
|
|
7874
|
-
log2(quiet,
|
|
8098
|
+
log2(quiet, chalk15.yellow(`${repoName}: refresh failed \u2014 ${err instanceof Error ? err.message : "unknown error"}`));
|
|
7875
8099
|
}
|
|
7876
8100
|
}
|
|
7877
8101
|
process.chdir(originalDir);
|
|
@@ -7879,13 +8103,13 @@ async function refreshCommand(options) {
|
|
|
7879
8103
|
if (err instanceof Error && err.message === "__exit__") throw err;
|
|
7880
8104
|
if (quiet) return;
|
|
7881
8105
|
const msg = err instanceof Error ? err.message : "Unknown error";
|
|
7882
|
-
console.log(
|
|
8106
|
+
console.log(chalk15.red(`Refresh failed: ${msg}`));
|
|
7883
8107
|
throw new Error("__exit__");
|
|
7884
8108
|
}
|
|
7885
8109
|
}
|
|
7886
8110
|
|
|
7887
8111
|
// src/commands/hooks.ts
|
|
7888
|
-
import
|
|
8112
|
+
import chalk16 from "chalk";
|
|
7889
8113
|
var HOOKS = [
|
|
7890
8114
|
{
|
|
7891
8115
|
id: "session-end",
|
|
@@ -7905,13 +8129,13 @@ var HOOKS = [
|
|
|
7905
8129
|
}
|
|
7906
8130
|
];
|
|
7907
8131
|
function printStatus() {
|
|
7908
|
-
console.log(
|
|
8132
|
+
console.log(chalk16.bold("\n Hooks\n"));
|
|
7909
8133
|
for (const hook of HOOKS) {
|
|
7910
8134
|
const installed = hook.isInstalled();
|
|
7911
|
-
const icon = installed ?
|
|
7912
|
-
const state = installed ?
|
|
8135
|
+
const icon = installed ? chalk16.green("\u2713") : chalk16.dim("\u2717");
|
|
8136
|
+
const state = installed ? chalk16.green("enabled") : chalk16.dim("disabled");
|
|
7913
8137
|
console.log(` ${icon} ${hook.label.padEnd(26)} ${state}`);
|
|
7914
|
-
console.log(
|
|
8138
|
+
console.log(chalk16.dim(` ${hook.description}`));
|
|
7915
8139
|
}
|
|
7916
8140
|
console.log("");
|
|
7917
8141
|
}
|
|
@@ -7920,9 +8144,9 @@ async function hooksCommand(options) {
|
|
|
7920
8144
|
for (const hook of HOOKS) {
|
|
7921
8145
|
const result = hook.install();
|
|
7922
8146
|
if (result.alreadyInstalled) {
|
|
7923
|
-
console.log(
|
|
8147
|
+
console.log(chalk16.dim(` ${hook.label} already enabled.`));
|
|
7924
8148
|
} else {
|
|
7925
|
-
console.log(
|
|
8149
|
+
console.log(chalk16.green(" \u2713") + ` ${hook.label} enabled`);
|
|
7926
8150
|
}
|
|
7927
8151
|
}
|
|
7928
8152
|
return;
|
|
@@ -7931,9 +8155,9 @@ async function hooksCommand(options) {
|
|
|
7931
8155
|
for (const hook of HOOKS) {
|
|
7932
8156
|
const result = hook.remove();
|
|
7933
8157
|
if (result.notFound) {
|
|
7934
|
-
console.log(
|
|
8158
|
+
console.log(chalk16.dim(` ${hook.label} already disabled.`));
|
|
7935
8159
|
} else {
|
|
7936
|
-
console.log(
|
|
8160
|
+
console.log(chalk16.green(" \u2713") + ` ${hook.label} removed`);
|
|
7937
8161
|
}
|
|
7938
8162
|
}
|
|
7939
8163
|
return;
|
|
@@ -7948,18 +8172,18 @@ async function hooksCommand(options) {
|
|
|
7948
8172
|
const states = HOOKS.map((h) => h.isInstalled());
|
|
7949
8173
|
function render() {
|
|
7950
8174
|
const lines = [];
|
|
7951
|
-
lines.push(
|
|
8175
|
+
lines.push(chalk16.bold(" Hooks"));
|
|
7952
8176
|
lines.push("");
|
|
7953
8177
|
for (let i = 0; i < HOOKS.length; i++) {
|
|
7954
8178
|
const hook = HOOKS[i];
|
|
7955
8179
|
const enabled = states[i];
|
|
7956
|
-
const toggle = enabled ?
|
|
7957
|
-
const ptr = i === cursor ?
|
|
8180
|
+
const toggle = enabled ? chalk16.green("[on] ") : chalk16.dim("[off]");
|
|
8181
|
+
const ptr = i === cursor ? chalk16.cyan(">") : " ";
|
|
7958
8182
|
lines.push(` ${ptr} ${toggle} ${hook.label}`);
|
|
7959
|
-
lines.push(
|
|
8183
|
+
lines.push(chalk16.dim(` ${hook.description}`));
|
|
7960
8184
|
}
|
|
7961
8185
|
lines.push("");
|
|
7962
|
-
lines.push(
|
|
8186
|
+
lines.push(chalk16.dim(" \u2191\u2193 navigate \u23B5 toggle a all on n all off \u23CE apply q cancel"));
|
|
7963
8187
|
return lines.join("\n");
|
|
7964
8188
|
}
|
|
7965
8189
|
function draw(initial) {
|
|
@@ -7990,16 +8214,16 @@ async function hooksCommand(options) {
|
|
|
7990
8214
|
const wantEnabled = states[i];
|
|
7991
8215
|
if (wantEnabled && !wasInstalled) {
|
|
7992
8216
|
hook.install();
|
|
7993
|
-
console.log(
|
|
8217
|
+
console.log(chalk16.green(" \u2713") + ` ${hook.label} enabled`);
|
|
7994
8218
|
changed++;
|
|
7995
8219
|
} else if (!wantEnabled && wasInstalled) {
|
|
7996
8220
|
hook.remove();
|
|
7997
|
-
console.log(
|
|
8221
|
+
console.log(chalk16.green(" \u2713") + ` ${hook.label} disabled`);
|
|
7998
8222
|
changed++;
|
|
7999
8223
|
}
|
|
8000
8224
|
}
|
|
8001
8225
|
if (changed === 0) {
|
|
8002
|
-
console.log(
|
|
8226
|
+
console.log(chalk16.dim(" No changes."));
|
|
8003
8227
|
}
|
|
8004
8228
|
console.log("");
|
|
8005
8229
|
}
|
|
@@ -8035,7 +8259,7 @@ async function hooksCommand(options) {
|
|
|
8035
8259
|
case "\x1B":
|
|
8036
8260
|
case "":
|
|
8037
8261
|
cleanup();
|
|
8038
|
-
console.log(
|
|
8262
|
+
console.log(chalk16.dim("\n Cancelled.\n"));
|
|
8039
8263
|
resolve2();
|
|
8040
8264
|
break;
|
|
8041
8265
|
}
|
|
@@ -8046,51 +8270,51 @@ async function hooksCommand(options) {
|
|
|
8046
8270
|
|
|
8047
8271
|
// src/commands/config.ts
|
|
8048
8272
|
init_config();
|
|
8049
|
-
import
|
|
8273
|
+
import chalk17 from "chalk";
|
|
8050
8274
|
async function configCommand() {
|
|
8051
8275
|
const existing = loadConfig();
|
|
8052
8276
|
if (existing) {
|
|
8053
8277
|
const displayModel = getDisplayModel(existing);
|
|
8054
8278
|
const fastModel = getFastModel();
|
|
8055
|
-
console.log(
|
|
8056
|
-
console.log(` Provider: ${
|
|
8057
|
-
console.log(` Model: ${
|
|
8279
|
+
console.log(chalk17.bold("\nCurrent Configuration\n"));
|
|
8280
|
+
console.log(` Provider: ${chalk17.cyan(existing.provider)}`);
|
|
8281
|
+
console.log(` Model: ${chalk17.cyan(displayModel)}`);
|
|
8058
8282
|
if (fastModel) {
|
|
8059
|
-
console.log(` Scan: ${
|
|
8283
|
+
console.log(` Scan: ${chalk17.cyan(fastModel)}`);
|
|
8060
8284
|
}
|
|
8061
8285
|
if (existing.apiKey) {
|
|
8062
8286
|
const masked = existing.apiKey.slice(0, 8) + "..." + existing.apiKey.slice(-4);
|
|
8063
|
-
console.log(` API Key: ${
|
|
8287
|
+
console.log(` API Key: ${chalk17.dim(masked)}`);
|
|
8064
8288
|
}
|
|
8065
8289
|
if (existing.provider === "cursor") {
|
|
8066
|
-
console.log(` Seat: ${
|
|
8290
|
+
console.log(` Seat: ${chalk17.dim("Cursor (agent acp)")}`);
|
|
8067
8291
|
}
|
|
8068
8292
|
if (existing.provider === "claude-cli") {
|
|
8069
|
-
console.log(` Seat: ${
|
|
8293
|
+
console.log(` Seat: ${chalk17.dim("Claude Code (claude -p)")}`);
|
|
8070
8294
|
}
|
|
8071
8295
|
if (existing.baseUrl) {
|
|
8072
|
-
console.log(` Base URL: ${
|
|
8296
|
+
console.log(` Base URL: ${chalk17.dim(existing.baseUrl)}`);
|
|
8073
8297
|
}
|
|
8074
8298
|
if (existing.vertexProjectId) {
|
|
8075
|
-
console.log(` Vertex Project: ${
|
|
8076
|
-
console.log(` Vertex Region: ${
|
|
8299
|
+
console.log(` Vertex Project: ${chalk17.dim(existing.vertexProjectId)}`);
|
|
8300
|
+
console.log(` Vertex Region: ${chalk17.dim(existing.vertexRegion || "us-east5")}`);
|
|
8077
8301
|
}
|
|
8078
|
-
console.log(` Source: ${
|
|
8302
|
+
console.log(` Source: ${chalk17.dim(process.env.ANTHROPIC_API_KEY || process.env.OPENAI_API_KEY || process.env.VERTEX_PROJECT_ID || process.env.CALIBER_USE_CURSOR_SEAT || process.env.CALIBER_USE_CLAUDE_CLI ? "environment variables" : getConfigFilePath())}`);
|
|
8079
8303
|
console.log("");
|
|
8080
8304
|
}
|
|
8081
8305
|
await runInteractiveProviderSetup();
|
|
8082
8306
|
const updated = loadConfig();
|
|
8083
8307
|
if (updated) trackConfigProviderSet(updated.provider);
|
|
8084
|
-
console.log(
|
|
8085
|
-
console.log(
|
|
8308
|
+
console.log(chalk17.green("\n\u2713 Configuration saved"));
|
|
8309
|
+
console.log(chalk17.dim(` ${getConfigFilePath()}
|
|
8086
8310
|
`));
|
|
8087
|
-
console.log(
|
|
8088
|
-
console.log(
|
|
8311
|
+
console.log(chalk17.dim(" You can also set environment variables instead:"));
|
|
8312
|
+
console.log(chalk17.dim(" ANTHROPIC_API_KEY, OPENAI_API_KEY, VERTEX_PROJECT_ID, CALIBER_USE_CURSOR_SEAT=1, or CALIBER_USE_CLAUDE_CLI=1\n"));
|
|
8089
8313
|
}
|
|
8090
8314
|
|
|
8091
8315
|
// src/commands/learn.ts
|
|
8092
8316
|
import fs31 from "fs";
|
|
8093
|
-
import
|
|
8317
|
+
import chalk18 from "chalk";
|
|
8094
8318
|
|
|
8095
8319
|
// src/learner/stdin.ts
|
|
8096
8320
|
var STDIN_TIMEOUT_MS = 5e3;
|
|
@@ -8406,26 +8630,26 @@ async function learnFinalizeCommand(options) {
|
|
|
8406
8630
|
if (!options?.force) {
|
|
8407
8631
|
const { isCaliberRunning: isCaliberRunning2 } = await Promise.resolve().then(() => (init_lock(), lock_exports));
|
|
8408
8632
|
if (isCaliberRunning2()) {
|
|
8409
|
-
console.log(
|
|
8633
|
+
console.log(chalk18.dim("caliber: skipping finalize \u2014 another caliber process is running"));
|
|
8410
8634
|
return;
|
|
8411
8635
|
}
|
|
8412
8636
|
}
|
|
8413
8637
|
if (!acquireFinalizeLock()) {
|
|
8414
|
-
console.log(
|
|
8638
|
+
console.log(chalk18.dim("caliber: skipping finalize \u2014 another finalize is in progress"));
|
|
8415
8639
|
return;
|
|
8416
8640
|
}
|
|
8417
8641
|
let analyzed = false;
|
|
8418
8642
|
try {
|
|
8419
8643
|
const config = loadConfig();
|
|
8420
8644
|
if (!config) {
|
|
8421
|
-
console.log(
|
|
8645
|
+
console.log(chalk18.yellow("caliber: no LLM provider configured \u2014 run `caliber config` first"));
|
|
8422
8646
|
clearSession();
|
|
8423
8647
|
resetState();
|
|
8424
8648
|
return;
|
|
8425
8649
|
}
|
|
8426
8650
|
const events = readAllEvents();
|
|
8427
8651
|
if (events.length < MIN_EVENTS_FOR_ANALYSIS) {
|
|
8428
|
-
console.log(
|
|
8652
|
+
console.log(chalk18.dim(`caliber: ${events.length}/${MIN_EVENTS_FOR_ANALYSIS} events recorded \u2014 need more before analysis`));
|
|
8429
8653
|
return;
|
|
8430
8654
|
}
|
|
8431
8655
|
await validateModel({ fast: true });
|
|
@@ -8446,15 +8670,15 @@ async function learnFinalizeCommand(options) {
|
|
|
8446
8670
|
skills: response.skills
|
|
8447
8671
|
});
|
|
8448
8672
|
if (result.newItemCount > 0) {
|
|
8449
|
-
console.log(
|
|
8673
|
+
console.log(chalk18.dim(`caliber: learned ${result.newItemCount} new pattern${result.newItemCount === 1 ? "" : "s"}`));
|
|
8450
8674
|
for (const item of result.newItems) {
|
|
8451
|
-
console.log(
|
|
8675
|
+
console.log(chalk18.dim(` + ${item.replace(/^- /, "").slice(0, 80)}`));
|
|
8452
8676
|
}
|
|
8453
8677
|
}
|
|
8454
8678
|
}
|
|
8455
8679
|
} catch (err) {
|
|
8456
8680
|
if (options?.force) {
|
|
8457
|
-
console.error(
|
|
8681
|
+
console.error(chalk18.red("caliber: finalize failed \u2014"), err instanceof Error ? err.message : err);
|
|
8458
8682
|
}
|
|
8459
8683
|
} finally {
|
|
8460
8684
|
if (analyzed) {
|
|
@@ -8469,45 +8693,45 @@ async function learnInstallCommand() {
|
|
|
8469
8693
|
if (fs31.existsSync(".claude")) {
|
|
8470
8694
|
const r = installLearningHooks();
|
|
8471
8695
|
if (r.installed) {
|
|
8472
|
-
console.log(
|
|
8696
|
+
console.log(chalk18.green("\u2713") + " Claude Code learning hooks installed");
|
|
8473
8697
|
anyInstalled = true;
|
|
8474
8698
|
} else if (r.alreadyInstalled) {
|
|
8475
|
-
console.log(
|
|
8699
|
+
console.log(chalk18.dim(" Claude Code hooks already installed"));
|
|
8476
8700
|
}
|
|
8477
8701
|
}
|
|
8478
8702
|
if (fs31.existsSync(".cursor")) {
|
|
8479
8703
|
const r = installCursorLearningHooks();
|
|
8480
8704
|
if (r.installed) {
|
|
8481
|
-
console.log(
|
|
8705
|
+
console.log(chalk18.green("\u2713") + " Cursor learning hooks installed");
|
|
8482
8706
|
anyInstalled = true;
|
|
8483
8707
|
} else if (r.alreadyInstalled) {
|
|
8484
|
-
console.log(
|
|
8708
|
+
console.log(chalk18.dim(" Cursor hooks already installed"));
|
|
8485
8709
|
}
|
|
8486
8710
|
}
|
|
8487
8711
|
if (!fs31.existsSync(".claude") && !fs31.existsSync(".cursor")) {
|
|
8488
|
-
console.log(
|
|
8489
|
-
console.log(
|
|
8712
|
+
console.log(chalk18.yellow("No .claude/ or .cursor/ directory found."));
|
|
8713
|
+
console.log(chalk18.dim(" Run `caliber init` first, or create the directory manually."));
|
|
8490
8714
|
return;
|
|
8491
8715
|
}
|
|
8492
8716
|
if (anyInstalled) {
|
|
8493
|
-
console.log(
|
|
8494
|
-
console.log(
|
|
8717
|
+
console.log(chalk18.dim(` Tool usage will be recorded and learnings extracted after \u2265${MIN_EVENTS_FOR_ANALYSIS} events.`));
|
|
8718
|
+
console.log(chalk18.dim(" Learnings written to CALIBER_LEARNINGS.md."));
|
|
8495
8719
|
}
|
|
8496
8720
|
}
|
|
8497
8721
|
async function learnRemoveCommand() {
|
|
8498
8722
|
let anyRemoved = false;
|
|
8499
8723
|
const r1 = removeLearningHooks();
|
|
8500
8724
|
if (r1.removed) {
|
|
8501
|
-
console.log(
|
|
8725
|
+
console.log(chalk18.green("\u2713") + " Claude Code learning hooks removed");
|
|
8502
8726
|
anyRemoved = true;
|
|
8503
8727
|
}
|
|
8504
8728
|
const r2 = removeCursorLearningHooks();
|
|
8505
8729
|
if (r2.removed) {
|
|
8506
|
-
console.log(
|
|
8730
|
+
console.log(chalk18.green("\u2713") + " Cursor learning hooks removed");
|
|
8507
8731
|
anyRemoved = true;
|
|
8508
8732
|
}
|
|
8509
8733
|
if (!anyRemoved) {
|
|
8510
|
-
console.log(
|
|
8734
|
+
console.log(chalk18.dim("No learning hooks found."));
|
|
8511
8735
|
}
|
|
8512
8736
|
}
|
|
8513
8737
|
async function learnStatusCommand() {
|
|
@@ -8515,34 +8739,34 @@ async function learnStatusCommand() {
|
|
|
8515
8739
|
const cursorInstalled = areCursorLearningHooksInstalled();
|
|
8516
8740
|
const state = readState2();
|
|
8517
8741
|
const eventCount = getEventCount();
|
|
8518
|
-
console.log(
|
|
8742
|
+
console.log(chalk18.bold("Session Learning Status"));
|
|
8519
8743
|
console.log();
|
|
8520
8744
|
if (claudeInstalled) {
|
|
8521
|
-
console.log(
|
|
8745
|
+
console.log(chalk18.green("\u2713") + " Claude Code hooks " + chalk18.green("installed"));
|
|
8522
8746
|
} else {
|
|
8523
|
-
console.log(
|
|
8747
|
+
console.log(chalk18.dim("\u2717") + " Claude Code hooks " + chalk18.dim("not installed"));
|
|
8524
8748
|
}
|
|
8525
8749
|
if (cursorInstalled) {
|
|
8526
|
-
console.log(
|
|
8750
|
+
console.log(chalk18.green("\u2713") + " Cursor hooks " + chalk18.green("installed"));
|
|
8527
8751
|
} else {
|
|
8528
|
-
console.log(
|
|
8752
|
+
console.log(chalk18.dim("\u2717") + " Cursor hooks " + chalk18.dim("not installed"));
|
|
8529
8753
|
}
|
|
8530
8754
|
if (!claudeInstalled && !cursorInstalled) {
|
|
8531
|
-
console.log(
|
|
8755
|
+
console.log(chalk18.dim(" Run `caliber learn install` to enable session learning."));
|
|
8532
8756
|
}
|
|
8533
8757
|
console.log();
|
|
8534
|
-
console.log(`Events recorded: ${
|
|
8535
|
-
console.log(`Threshold for analysis: ${
|
|
8758
|
+
console.log(`Events recorded: ${chalk18.cyan(String(eventCount))}`);
|
|
8759
|
+
console.log(`Threshold for analysis: ${chalk18.cyan(String(MIN_EVENTS_FOR_ANALYSIS))}`);
|
|
8536
8760
|
if (state.lastAnalysisTimestamp) {
|
|
8537
|
-
console.log(`Last analysis: ${
|
|
8761
|
+
console.log(`Last analysis: ${chalk18.cyan(state.lastAnalysisTimestamp)}`);
|
|
8538
8762
|
} else {
|
|
8539
|
-
console.log(`Last analysis: ${
|
|
8763
|
+
console.log(`Last analysis: ${chalk18.dim("none")}`);
|
|
8540
8764
|
}
|
|
8541
8765
|
const learnedSection = readLearnedSection();
|
|
8542
8766
|
if (learnedSection) {
|
|
8543
8767
|
const lineCount = learnedSection.split("\n").filter(Boolean).length;
|
|
8544
8768
|
console.log(`
|
|
8545
|
-
Learned items in CALIBER_LEARNINGS.md: ${
|
|
8769
|
+
Learned items in CALIBER_LEARNINGS.md: ${chalk18.cyan(String(lineCount))}`);
|
|
8546
8770
|
}
|
|
8547
8771
|
}
|
|
8548
8772
|
|
|
@@ -8627,7 +8851,7 @@ import fs33 from "fs";
|
|
|
8627
8851
|
import path26 from "path";
|
|
8628
8852
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
8629
8853
|
import { execSync as execSync14 } from "child_process";
|
|
8630
|
-
import
|
|
8854
|
+
import chalk19 from "chalk";
|
|
8631
8855
|
import ora6 from "ora";
|
|
8632
8856
|
import confirm2 from "@inquirer/confirm";
|
|
8633
8857
|
var __dirname_vc = path26.dirname(fileURLToPath2(import.meta.url));
|
|
@@ -8661,17 +8885,17 @@ async function checkForUpdates() {
|
|
|
8661
8885
|
const isInteractive = process.stdin.isTTY === true;
|
|
8662
8886
|
if (!isInteractive) {
|
|
8663
8887
|
console.log(
|
|
8664
|
-
|
|
8888
|
+
chalk19.yellow(
|
|
8665
8889
|
`
|
|
8666
8890
|
Update available: ${current} -> ${latest}
|
|
8667
|
-
Run ${
|
|
8891
|
+
Run ${chalk19.bold("npm install -g @rely-ai/caliber")} to upgrade.
|
|
8668
8892
|
`
|
|
8669
8893
|
)
|
|
8670
8894
|
);
|
|
8671
8895
|
return;
|
|
8672
8896
|
}
|
|
8673
8897
|
console.log(
|
|
8674
|
-
|
|
8898
|
+
chalk19.yellow(`
|
|
8675
8899
|
Update available: ${current} -> ${latest}`)
|
|
8676
8900
|
);
|
|
8677
8901
|
const shouldUpdate = await confirm2({ message: "Would you like to update now? (Y/n)", default: true });
|
|
@@ -8689,13 +8913,13 @@ Update available: ${current} -> ${latest}`)
|
|
|
8689
8913
|
const installed = getInstalledVersion();
|
|
8690
8914
|
if (installed !== latest) {
|
|
8691
8915
|
spinner.fail(`Update incomplete \u2014 got ${installed ?? "unknown"}, expected ${latest}`);
|
|
8692
|
-
console.log(
|
|
8916
|
+
console.log(chalk19.yellow(`Run ${chalk19.bold(`npm install -g @rely-ai/caliber@${latest}`)} manually.
|
|
8693
8917
|
`));
|
|
8694
8918
|
return;
|
|
8695
8919
|
}
|
|
8696
|
-
spinner.succeed(
|
|
8920
|
+
spinner.succeed(chalk19.green(`Updated to ${latest}`));
|
|
8697
8921
|
const args = process.argv.slice(2);
|
|
8698
|
-
console.log(
|
|
8922
|
+
console.log(chalk19.dim(`
|
|
8699
8923
|
Restarting: caliber ${args.join(" ")}
|
|
8700
8924
|
`));
|
|
8701
8925
|
execSync14(`caliber ${args.map((a) => JSON.stringify(a)).join(" ")}`, {
|
|
@@ -8708,11 +8932,11 @@ Restarting: caliber ${args.join(" ")}
|
|
|
8708
8932
|
if (err instanceof Error) {
|
|
8709
8933
|
const stderr = err.stderr;
|
|
8710
8934
|
const errMsg = stderr ? String(stderr).trim().split("\n").pop() : err.message.split("\n")[0];
|
|
8711
|
-
if (errMsg && !errMsg.includes("SIGTERM")) console.log(
|
|
8935
|
+
if (errMsg && !errMsg.includes("SIGTERM")) console.log(chalk19.dim(` ${errMsg}`));
|
|
8712
8936
|
}
|
|
8713
8937
|
console.log(
|
|
8714
|
-
|
|
8715
|
-
`Run ${
|
|
8938
|
+
chalk19.yellow(
|
|
8939
|
+
`Run ${chalk19.bold(`npm install -g @rely-ai/caliber@${latest}`)} manually to upgrade.
|
|
8716
8940
|
`
|
|
8717
8941
|
)
|
|
8718
8942
|
);
|