@rely-ai/caliber 1.20.0-dev.1773690658 → 1.20.0-dev.1773694290
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 +668 -305
- package/package.json +1 -1
package/dist/bin.js
CHANGED
|
@@ -227,8 +227,8 @@ import { fileURLToPath } from "url";
|
|
|
227
227
|
|
|
228
228
|
// src/commands/init.ts
|
|
229
229
|
import path20 from "path";
|
|
230
|
-
import
|
|
231
|
-
import
|
|
230
|
+
import chalk11 from "chalk";
|
|
231
|
+
import ora3 from "ora";
|
|
232
232
|
import select5 from "@inquirer/select";
|
|
233
233
|
import checkbox from "@inquirer/checkbox";
|
|
234
234
|
import fs25 from "fs";
|
|
@@ -4362,7 +4362,7 @@ function checkExistence(dir) {
|
|
|
4362
4362
|
import { join as join4 } from "path";
|
|
4363
4363
|
|
|
4364
4364
|
// src/scoring/utils.ts
|
|
4365
|
-
import { readFileSync as readFileSync3, readdirSync as readdirSync2 } from "fs";
|
|
4365
|
+
import { existsSync as existsSync3, readFileSync as readFileSync3, readdirSync as readdirSync2 } from "fs";
|
|
4366
4366
|
import { join as join3, relative } from "path";
|
|
4367
4367
|
function readFileOrNull2(filePath) {
|
|
4368
4368
|
try {
|
|
@@ -4545,6 +4545,58 @@ function extractReferences(content) {
|
|
|
4545
4545
|
}
|
|
4546
4546
|
return Array.from(refs);
|
|
4547
4547
|
}
|
|
4548
|
+
function validateFileReferences(content, dir, checkExists = existsSync3) {
|
|
4549
|
+
const refs = extractReferences(content);
|
|
4550
|
+
const valid = [];
|
|
4551
|
+
const invalid = [];
|
|
4552
|
+
for (const ref of refs) {
|
|
4553
|
+
if (/^https?:\/\//.test(ref)) continue;
|
|
4554
|
+
if (/^\d+\.\d+/.test(ref)) continue;
|
|
4555
|
+
if (ref.startsWith("#") || ref.startsWith("@")) continue;
|
|
4556
|
+
if (ref.includes("*") || ref.includes("..")) continue;
|
|
4557
|
+
if (!ref.includes("/") && !ref.includes(".")) continue;
|
|
4558
|
+
const fullPath = join3(dir, ref);
|
|
4559
|
+
if (checkExists(fullPath)) {
|
|
4560
|
+
valid.push(ref);
|
|
4561
|
+
} else {
|
|
4562
|
+
const withoutTrailing = ref.replace(/\/+$/, "");
|
|
4563
|
+
if (withoutTrailing !== ref && checkExists(join3(dir, withoutTrailing))) {
|
|
4564
|
+
valid.push(ref);
|
|
4565
|
+
} else {
|
|
4566
|
+
invalid.push(ref);
|
|
4567
|
+
}
|
|
4568
|
+
}
|
|
4569
|
+
}
|
|
4570
|
+
return { valid, invalid, total: valid.length + invalid.length };
|
|
4571
|
+
}
|
|
4572
|
+
function countConcreteness(content) {
|
|
4573
|
+
let concrete = 0;
|
|
4574
|
+
let abstract = 0;
|
|
4575
|
+
let inCodeBlock = false;
|
|
4576
|
+
for (const line of content.split("\n")) {
|
|
4577
|
+
if (line.trim().startsWith("```")) {
|
|
4578
|
+
inCodeBlock = !inCodeBlock;
|
|
4579
|
+
continue;
|
|
4580
|
+
}
|
|
4581
|
+
const classification = classifyLine(line, inCodeBlock);
|
|
4582
|
+
if (classification === "concrete") concrete++;
|
|
4583
|
+
else if (classification === "abstract") abstract++;
|
|
4584
|
+
}
|
|
4585
|
+
return { concrete, abstract };
|
|
4586
|
+
}
|
|
4587
|
+
function countTreeLines(content) {
|
|
4588
|
+
const treeLinePattern = /[├└│─┬]/;
|
|
4589
|
+
let count = 0;
|
|
4590
|
+
let inCodeBlock = false;
|
|
4591
|
+
for (const line of content.split("\n")) {
|
|
4592
|
+
if (line.trim().startsWith("```")) {
|
|
4593
|
+
inCodeBlock = !inCodeBlock;
|
|
4594
|
+
continue;
|
|
4595
|
+
}
|
|
4596
|
+
if (inCodeBlock && treeLinePattern.test(line)) count++;
|
|
4597
|
+
}
|
|
4598
|
+
return count;
|
|
4599
|
+
}
|
|
4548
4600
|
function classifyLine(line, inCodeBlock) {
|
|
4549
4601
|
if (inCodeBlock) return "concrete";
|
|
4550
4602
|
const trimmed = line.trim();
|
|
@@ -4604,25 +4656,17 @@ function checkQuality(dir) {
|
|
|
4604
4656
|
instruction: `Reduce total config from ~${totalTokens} tokens to under 5000.`
|
|
4605
4657
|
} : void 0
|
|
4606
4658
|
});
|
|
4607
|
-
|
|
4608
|
-
let abstractCount = 0;
|
|
4659
|
+
const { concrete: concreteCount, abstract: abstractCount } = primaryInstructions ? countConcreteness(primaryInstructions) : { concrete: 0, abstract: 0 };
|
|
4609
4660
|
const abstractExamples = [];
|
|
4610
|
-
if (primaryInstructions) {
|
|
4611
|
-
let
|
|
4661
|
+
if (primaryInstructions && abstractCount > 0) {
|
|
4662
|
+
let inCb = false;
|
|
4612
4663
|
for (const line of primaryInstructions.split("\n")) {
|
|
4613
4664
|
if (line.trim().startsWith("```")) {
|
|
4614
|
-
|
|
4665
|
+
inCb = !inCb;
|
|
4615
4666
|
continue;
|
|
4616
4667
|
}
|
|
4617
|
-
|
|
4618
|
-
|
|
4619
|
-
if (classification === "concrete") {
|
|
4620
|
-
concreteCount++;
|
|
4621
|
-
} else {
|
|
4622
|
-
abstractCount++;
|
|
4623
|
-
if (abstractExamples.length < 3) {
|
|
4624
|
-
abstractExamples.push(line.trim().slice(0, 80));
|
|
4625
|
-
}
|
|
4668
|
+
if (!inCb && classifyLine(line, false) === "abstract" && abstractExamples.length < 3) {
|
|
4669
|
+
abstractExamples.push(line.trim().slice(0, 80));
|
|
4626
4670
|
}
|
|
4627
4671
|
}
|
|
4628
4672
|
}
|
|
@@ -4645,20 +4689,7 @@ function checkQuality(dir) {
|
|
|
4645
4689
|
instruction: `Replace generic prose with specific references. Examples of vague lines: ${abstractExamples.join("; ")}`
|
|
4646
4690
|
} : void 0
|
|
4647
4691
|
});
|
|
4648
|
-
const
|
|
4649
|
-
let treeLineCount = 0;
|
|
4650
|
-
let inCodeBlock = false;
|
|
4651
|
-
if (combinedContent) {
|
|
4652
|
-
for (const line of combinedContent.split("\n")) {
|
|
4653
|
-
if (line.trim().startsWith("```")) {
|
|
4654
|
-
inCodeBlock = !inCodeBlock;
|
|
4655
|
-
continue;
|
|
4656
|
-
}
|
|
4657
|
-
if (inCodeBlock && treeLinePattern.test(line)) {
|
|
4658
|
-
treeLineCount++;
|
|
4659
|
-
}
|
|
4660
|
-
}
|
|
4661
|
-
}
|
|
4692
|
+
const treeLineCount = combinedContent ? countTreeLines(combinedContent) : 0;
|
|
4662
4693
|
const hasLargeTree = treeLineCount > 10;
|
|
4663
4694
|
checks.push({
|
|
4664
4695
|
id: "no_directory_tree",
|
|
@@ -4823,30 +4854,7 @@ import { join as join5 } from "path";
|
|
|
4823
4854
|
function validateReferences(dir) {
|
|
4824
4855
|
const configContent = collectPrimaryConfigContent(dir);
|
|
4825
4856
|
if (!configContent) return { valid: [], invalid: [], total: 0 };
|
|
4826
|
-
|
|
4827
|
-
const valid = [];
|
|
4828
|
-
const invalid = [];
|
|
4829
|
-
for (const ref of refs) {
|
|
4830
|
-
if (/^https?:\/\//.test(ref)) continue;
|
|
4831
|
-
if (/^\d+\.\d+/.test(ref)) continue;
|
|
4832
|
-
if (ref.startsWith("#")) continue;
|
|
4833
|
-
if (ref.startsWith("@")) continue;
|
|
4834
|
-
if (ref.includes("*")) continue;
|
|
4835
|
-
if (ref.includes("..")) continue;
|
|
4836
|
-
if (!ref.includes("/") && !ref.includes(".")) continue;
|
|
4837
|
-
const fullPath = join5(dir, ref);
|
|
4838
|
-
if (existsSync4(fullPath)) {
|
|
4839
|
-
valid.push(ref);
|
|
4840
|
-
} else {
|
|
4841
|
-
const withoutTrailing = ref.replace(/\/+$/, "");
|
|
4842
|
-
if (withoutTrailing !== ref && existsSync4(join5(dir, withoutTrailing))) {
|
|
4843
|
-
valid.push(ref);
|
|
4844
|
-
} else {
|
|
4845
|
-
invalid.push(ref);
|
|
4846
|
-
}
|
|
4847
|
-
}
|
|
4848
|
-
}
|
|
4849
|
-
return { valid, invalid, total: valid.length + invalid.length };
|
|
4857
|
+
return validateFileReferences(configContent, dir);
|
|
4850
4858
|
}
|
|
4851
4859
|
function detectGitDrift(dir) {
|
|
4852
4860
|
try {
|
|
@@ -6428,6 +6436,184 @@ function printSkills(recs) {
|
|
|
6428
6436
|
console.log("");
|
|
6429
6437
|
}
|
|
6430
6438
|
|
|
6439
|
+
// src/ai/score-refine.ts
|
|
6440
|
+
import { existsSync as existsSync9 } from "fs";
|
|
6441
|
+
import ora2 from "ora";
|
|
6442
|
+
var MAX_REFINE_ITERATIONS = 2;
|
|
6443
|
+
function extractConfigContent(setup) {
|
|
6444
|
+
const claude = setup.claude;
|
|
6445
|
+
const codex = setup.codex;
|
|
6446
|
+
return {
|
|
6447
|
+
claudeMd: claude?.claudeMd ?? null,
|
|
6448
|
+
agentsMd: codex?.agentsMd ?? null
|
|
6449
|
+
};
|
|
6450
|
+
}
|
|
6451
|
+
function validateSetup(setup, dir, checkExists = existsSync9) {
|
|
6452
|
+
const issues = [];
|
|
6453
|
+
const { claudeMd, agentsMd } = extractConfigContent(setup);
|
|
6454
|
+
const primaryContent = [claudeMd, agentsMd].filter(Boolean).join("\n");
|
|
6455
|
+
if (!primaryContent) return issues;
|
|
6456
|
+
const refs = validateFileReferences(primaryContent, dir, checkExists);
|
|
6457
|
+
if (refs.invalid.length > 0 && refs.total > 0) {
|
|
6458
|
+
const ratio = refs.valid.length / refs.total;
|
|
6459
|
+
const earnedPoints = Math.round(ratio * POINTS_REFERENCES_VALID);
|
|
6460
|
+
const lost = POINTS_REFERENCES_VALID - earnedPoints;
|
|
6461
|
+
if (lost > 0) {
|
|
6462
|
+
issues.push({
|
|
6463
|
+
check: "References valid",
|
|
6464
|
+
detail: `${refs.valid.length}/${refs.total} references verified, ${refs.invalid.length} invalid`,
|
|
6465
|
+
fixInstruction: `Remove these non-existent paths from the config: ${refs.invalid.map((r) => `\`${r}\``).join(", ")}. Do NOT guess replacements \u2014 just delete them.`,
|
|
6466
|
+
pointsLost: lost
|
|
6467
|
+
});
|
|
6468
|
+
}
|
|
6469
|
+
}
|
|
6470
|
+
const totalTokens = estimateTokens2(primaryContent);
|
|
6471
|
+
const tokenThreshold = TOKEN_BUDGET_THRESHOLDS.find((t) => totalTokens <= t.maxTokens);
|
|
6472
|
+
const tokenPoints = tokenThreshold?.points ?? 0;
|
|
6473
|
+
const maxTokenPoints = TOKEN_BUDGET_THRESHOLDS[0].points;
|
|
6474
|
+
if (tokenPoints < maxTokenPoints) {
|
|
6475
|
+
issues.push({
|
|
6476
|
+
check: "Token budget",
|
|
6477
|
+
detail: `~${totalTokens} tokens (target: \u2264${TOKEN_BUDGET_THRESHOLDS[0].maxTokens} for full points)`,
|
|
6478
|
+
fixInstruction: `Config is ~${totalTokens} tokens. Remove the least important lines to get under ${TOKEN_BUDGET_THRESHOLDS[0].maxTokens} tokens. Prioritize removing verbose prose over code blocks or path references.`,
|
|
6479
|
+
pointsLost: maxTokenPoints - tokenPoints
|
|
6480
|
+
});
|
|
6481
|
+
}
|
|
6482
|
+
const content = claudeMd ?? agentsMd ?? "";
|
|
6483
|
+
if (content) {
|
|
6484
|
+
const structure = analyzeMarkdownStructure(content);
|
|
6485
|
+
const blockThreshold = CODE_BLOCK_THRESHOLDS.find((t) => structure.codeBlockCount >= t.minBlocks);
|
|
6486
|
+
const blockPoints = blockThreshold?.points ?? 0;
|
|
6487
|
+
const maxBlockPoints = CODE_BLOCK_THRESHOLDS[0].points;
|
|
6488
|
+
if (blockPoints < maxBlockPoints && structure.codeBlockCount < CODE_BLOCK_THRESHOLDS[0].minBlocks) {
|
|
6489
|
+
issues.push({
|
|
6490
|
+
check: "Executable content",
|
|
6491
|
+
detail: `${structure.codeBlockCount} code block${structure.codeBlockCount === 1 ? "" : "s"} (need \u2265${CODE_BLOCK_THRESHOLDS[0].minBlocks} for full points)`,
|
|
6492
|
+
fixInstruction: `Add ${CODE_BLOCK_THRESHOLDS[0].minBlocks - structure.codeBlockCount} more code blocks with actual project commands (build, test, lint, deploy).`,
|
|
6493
|
+
pointsLost: maxBlockPoints - blockPoints
|
|
6494
|
+
});
|
|
6495
|
+
}
|
|
6496
|
+
const { concrete: concreteCount, abstract: abstractCount } = countConcreteness(content);
|
|
6497
|
+
const totalMeaningful = concreteCount + abstractCount;
|
|
6498
|
+
const concreteRatio = totalMeaningful > 0 ? concreteCount / totalMeaningful : 1;
|
|
6499
|
+
const concThreshold = CONCRETENESS_THRESHOLDS.find((t) => concreteRatio >= t.minRatio);
|
|
6500
|
+
const concPoints = totalMeaningful === 0 ? 0 : concThreshold?.points ?? 0;
|
|
6501
|
+
const maxConcPoints = CONCRETENESS_THRESHOLDS[0].points;
|
|
6502
|
+
if (concPoints < maxConcPoints && totalMeaningful > 0 && concreteRatio < CONCRETENESS_THRESHOLDS[0].minRatio) {
|
|
6503
|
+
issues.push({
|
|
6504
|
+
check: "Concrete instructions",
|
|
6505
|
+
detail: `${Math.round(concreteRatio * 100)}% concrete (need \u2265${Math.round(CONCRETENESS_THRESHOLDS[0].minRatio * 100)}%)`,
|
|
6506
|
+
fixInstruction: `${abstractCount} lines are generic prose. Replace vague instructions with specific ones that reference project files, paths, or commands in backticks.`,
|
|
6507
|
+
pointsLost: maxConcPoints - concPoints
|
|
6508
|
+
});
|
|
6509
|
+
}
|
|
6510
|
+
const treeLineCount = countTreeLines(content);
|
|
6511
|
+
if (treeLineCount > 10) {
|
|
6512
|
+
issues.push({
|
|
6513
|
+
check: "No directory tree listings",
|
|
6514
|
+
detail: `${treeLineCount}-line directory tree found in code blocks`,
|
|
6515
|
+
fixInstruction: "Remove directory tree listings from code blocks. Reference key directories inline with backticks instead.",
|
|
6516
|
+
pointsLost: POINTS_NO_DIR_TREE
|
|
6517
|
+
});
|
|
6518
|
+
}
|
|
6519
|
+
if (structure.h2Count < 3 || structure.listItemCount < 3) {
|
|
6520
|
+
const parts = [];
|
|
6521
|
+
if (structure.h2Count < 3) parts.push(`add ${3 - structure.h2Count} more ## sections`);
|
|
6522
|
+
if (structure.listItemCount < 3) parts.push("use bullet lists for multi-item instructions");
|
|
6523
|
+
issues.push({
|
|
6524
|
+
check: "Structured with headings",
|
|
6525
|
+
detail: `${structure.h2Count} sections, ${structure.listItemCount} list items`,
|
|
6526
|
+
fixInstruction: `Improve structure: ${parts.join(" and ")}.`,
|
|
6527
|
+
pointsLost: POINTS_HAS_STRUCTURE - ((structure.h2Count >= 3 ? 1 : 0) + (structure.listItemCount >= 3 ? 1 : 0))
|
|
6528
|
+
});
|
|
6529
|
+
}
|
|
6530
|
+
}
|
|
6531
|
+
return issues.sort((a, b) => b.pointsLost - a.pointsLost);
|
|
6532
|
+
}
|
|
6533
|
+
function buildFeedbackMessage(issues) {
|
|
6534
|
+
const lines = [
|
|
6535
|
+
"Your generated config has these scoring issues. Fix ONLY these \u2014 do not rewrite, restructure, or make cosmetic changes to anything else:\n"
|
|
6536
|
+
];
|
|
6537
|
+
for (let i = 0; i < issues.length; i++) {
|
|
6538
|
+
const issue = issues[i];
|
|
6539
|
+
lines.push(`${i + 1}. ${issue.check.toUpperCase()} (-${issue.pointsLost} pts): ${issue.detail}`);
|
|
6540
|
+
lines.push(` Action: ${issue.fixInstruction}
|
|
6541
|
+
`);
|
|
6542
|
+
}
|
|
6543
|
+
lines.push("Return the complete updated AgentSetup JSON with only these fixes applied.");
|
|
6544
|
+
return lines.join("\n");
|
|
6545
|
+
}
|
|
6546
|
+
function countIssuePoints(issues) {
|
|
6547
|
+
return issues.reduce((sum, i) => sum + i.pointsLost, 0);
|
|
6548
|
+
}
|
|
6549
|
+
async function scoreAndRefine(setup, dir, sessionHistory, callbacks) {
|
|
6550
|
+
const existsCache = /* @__PURE__ */ new Map();
|
|
6551
|
+
const cachedExists = (path29) => {
|
|
6552
|
+
const cached = existsCache.get(path29);
|
|
6553
|
+
if (cached !== void 0) return cached;
|
|
6554
|
+
const result = existsSync9(path29);
|
|
6555
|
+
existsCache.set(path29, result);
|
|
6556
|
+
return result;
|
|
6557
|
+
};
|
|
6558
|
+
let currentSetup = setup;
|
|
6559
|
+
let bestSetup = setup;
|
|
6560
|
+
let bestLostPoints = Infinity;
|
|
6561
|
+
for (let iteration = 0; iteration < MAX_REFINE_ITERATIONS; iteration++) {
|
|
6562
|
+
const issues = validateSetup(currentSetup, dir, cachedExists);
|
|
6563
|
+
const lostPoints = countIssuePoints(issues);
|
|
6564
|
+
if (lostPoints < bestLostPoints) {
|
|
6565
|
+
bestSetup = currentSetup;
|
|
6566
|
+
bestLostPoints = lostPoints;
|
|
6567
|
+
}
|
|
6568
|
+
if (issues.length === 0) {
|
|
6569
|
+
if (callbacks?.onStatus) callbacks.onStatus("Setup passes all scoring checks");
|
|
6570
|
+
return bestSetup;
|
|
6571
|
+
}
|
|
6572
|
+
if (callbacks?.onStatus) {
|
|
6573
|
+
const issueNames = issues.map((i) => i.check).join(", ");
|
|
6574
|
+
callbacks.onStatus(`Fixing ${issues.length} scoring issue${issues.length === 1 ? "" : "s"}: ${issueNames}...`);
|
|
6575
|
+
}
|
|
6576
|
+
const feedbackMessage = buildFeedbackMessage(issues);
|
|
6577
|
+
const refined = await refineSetup(currentSetup, feedbackMessage, sessionHistory);
|
|
6578
|
+
if (!refined) {
|
|
6579
|
+
if (callbacks?.onStatus) callbacks.onStatus("Refinement failed, keeping current setup");
|
|
6580
|
+
return bestSetup;
|
|
6581
|
+
}
|
|
6582
|
+
sessionHistory.push({ role: "user", content: feedbackMessage });
|
|
6583
|
+
sessionHistory.push({
|
|
6584
|
+
role: "assistant",
|
|
6585
|
+
content: `Applied scoring fixes for: ${issues.map((i) => i.check).join(", ")}`
|
|
6586
|
+
});
|
|
6587
|
+
currentSetup = refined;
|
|
6588
|
+
}
|
|
6589
|
+
const finalIssues = validateSetup(currentSetup, dir, cachedExists);
|
|
6590
|
+
const finalLostPoints = countIssuePoints(finalIssues);
|
|
6591
|
+
if (finalLostPoints < bestLostPoints) {
|
|
6592
|
+
bestSetup = currentSetup;
|
|
6593
|
+
}
|
|
6594
|
+
return bestSetup;
|
|
6595
|
+
}
|
|
6596
|
+
async function runScoreRefineWithSpinner(setup, dir, sessionHistory) {
|
|
6597
|
+
const spinner = ora2("Validating setup against scoring criteria...").start();
|
|
6598
|
+
try {
|
|
6599
|
+
const refined = await scoreAndRefine(setup, dir, sessionHistory, {
|
|
6600
|
+
onStatus: (msg) => {
|
|
6601
|
+
spinner.text = msg;
|
|
6602
|
+
}
|
|
6603
|
+
});
|
|
6604
|
+
if (refined !== setup) {
|
|
6605
|
+
spinner.succeed("Setup refined based on scoring feedback");
|
|
6606
|
+
} else {
|
|
6607
|
+
spinner.succeed("Setup passes scoring validation");
|
|
6608
|
+
}
|
|
6609
|
+
return refined;
|
|
6610
|
+
} catch (err) {
|
|
6611
|
+
const msg = err instanceof Error ? err.message : "unknown error";
|
|
6612
|
+
spinner.warn(`Scoring validation skipped: ${msg}`);
|
|
6613
|
+
return setup;
|
|
6614
|
+
}
|
|
6615
|
+
}
|
|
6616
|
+
|
|
6431
6617
|
// src/lib/debug-report.ts
|
|
6432
6618
|
import fs24 from "fs";
|
|
6433
6619
|
import path19 from "path";
|
|
@@ -6516,9 +6702,101 @@ function formatMs(ms) {
|
|
|
6516
6702
|
}
|
|
6517
6703
|
|
|
6518
6704
|
// src/utils/parallel-tasks.ts
|
|
6705
|
+
import chalk10 from "chalk";
|
|
6706
|
+
|
|
6707
|
+
// src/utils/waiting-content.ts
|
|
6519
6708
|
import chalk9 from "chalk";
|
|
6709
|
+
|
|
6710
|
+
// src/utils/waiting-cards.json
|
|
6711
|
+
var waiting_cards_default = [
|
|
6712
|
+
{
|
|
6713
|
+
title: "What is Caliber?",
|
|
6714
|
+
icon: "?",
|
|
6715
|
+
lines: [
|
|
6716
|
+
"Caliber scans your project and generates tailored configs",
|
|
6717
|
+
"for Claude Code, Cursor, and Codex \u2014 so your AI agent",
|
|
6718
|
+
"understands your codebase from the start."
|
|
6719
|
+
]
|
|
6720
|
+
},
|
|
6721
|
+
{
|
|
6722
|
+
title: "Generated Configs",
|
|
6723
|
+
icon: "\u2699",
|
|
6724
|
+
lines: [
|
|
6725
|
+
"CLAUDE.md and .cursor/rules/ tell your AI agent about",
|
|
6726
|
+
"your build commands, conventions, architecture, and tools.",
|
|
6727
|
+
"Think of them as onboarding docs \u2014 but for your copilot."
|
|
6728
|
+
]
|
|
6729
|
+
},
|
|
6730
|
+
{
|
|
6731
|
+
title: "Skills",
|
|
6732
|
+
icon: "\u26A1",
|
|
6733
|
+
lines: [
|
|
6734
|
+
"Skills are reusable task-specific instructions your agent",
|
|
6735
|
+
"loads on demand \u2014 deploy scripts, migration patterns, etc.",
|
|
6736
|
+
"Run `caliber skills` to search the community registry."
|
|
6737
|
+
]
|
|
6738
|
+
},
|
|
6739
|
+
{
|
|
6740
|
+
title: "Keep Configs Fresh",
|
|
6741
|
+
icon: "\u21BB",
|
|
6742
|
+
lines: [
|
|
6743
|
+
"As your code evolves, configs drift. `caliber refresh`",
|
|
6744
|
+
"reads your recent git diffs and updates configs to match.",
|
|
6745
|
+
"Add it as a post-commit hook for hands-free updates."
|
|
6746
|
+
]
|
|
6747
|
+
},
|
|
6748
|
+
{
|
|
6749
|
+
title: "Score Your Setup",
|
|
6750
|
+
icon: "\u2605",
|
|
6751
|
+
lines: [
|
|
6752
|
+
"`caliber score` runs 20+ checks against your config \u2014",
|
|
6753
|
+
"grounding, accuracy, freshness \u2014 and gives a letter grade.",
|
|
6754
|
+
"Aim for an A to get the most out of your AI agent."
|
|
6755
|
+
]
|
|
6756
|
+
},
|
|
6757
|
+
{
|
|
6758
|
+
title: "Quick Health Check",
|
|
6759
|
+
icon: "\u2764",
|
|
6760
|
+
lines: [
|
|
6761
|
+
"`caliber status` shows what you have configured,",
|
|
6762
|
+
"which hooks are active, and if anything needs attention.",
|
|
6763
|
+
"It runs in under a second \u2014 great for CI checks too."
|
|
6764
|
+
]
|
|
6765
|
+
}
|
|
6766
|
+
];
|
|
6767
|
+
|
|
6768
|
+
// src/utils/waiting-content.ts
|
|
6769
|
+
var ACCENT = chalk9.hex("#83D1EB");
|
|
6770
|
+
var BRAND = chalk9.hex("#EB9D83");
|
|
6771
|
+
var WAITING_CARDS = waiting_cards_default;
|
|
6772
|
+
function highlightCommands(text) {
|
|
6773
|
+
return text.replace(/`([^`]+)`/g, (_, cmd) => ACCENT(cmd));
|
|
6774
|
+
}
|
|
6775
|
+
function renderCard(card, index, total, cols) {
|
|
6776
|
+
const prefix = " ";
|
|
6777
|
+
const maxWidth = Math.min(cols - 8, 65);
|
|
6778
|
+
const lines = [];
|
|
6779
|
+
lines.push(chalk9.dim(`${prefix}${"\u2500".repeat(maxWidth)}`));
|
|
6780
|
+
lines.push("");
|
|
6781
|
+
const dots = Array.from(
|
|
6782
|
+
{ length: total },
|
|
6783
|
+
(_, i) => i === index ? ACCENT("\u25CF") : chalk9.dim("\u25CB")
|
|
6784
|
+
).join(" ");
|
|
6785
|
+
lines.push(`${prefix}${chalk9.dim("While you wait...")} ${dots}`);
|
|
6786
|
+
lines.push("");
|
|
6787
|
+
lines.push(`${prefix}${BRAND(card.icon)} ${chalk9.bold(card.title)}`);
|
|
6788
|
+
for (const line of card.lines) {
|
|
6789
|
+
lines.push(`${prefix} ${chalk9.dim(highlightCommands(line))}`);
|
|
6790
|
+
}
|
|
6791
|
+
lines.push("");
|
|
6792
|
+
lines.push(`${prefix}${chalk9.dim("\u2190 \u2192 navigate auto-advances every 15s")}`);
|
|
6793
|
+
return lines;
|
|
6794
|
+
}
|
|
6795
|
+
|
|
6796
|
+
// src/utils/parallel-tasks.ts
|
|
6520
6797
|
var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
6521
6798
|
var SPINNER_INTERVAL_MS = 80;
|
|
6799
|
+
var CARD_ADVANCE_MS = 15e3;
|
|
6522
6800
|
var NAME_COL_WIDTH = 26;
|
|
6523
6801
|
var PREFIX = " ";
|
|
6524
6802
|
var ParallelTaskDisplay = class {
|
|
@@ -6528,6 +6806,14 @@ var ParallelTaskDisplay = class {
|
|
|
6528
6806
|
timer = null;
|
|
6529
6807
|
startTime = 0;
|
|
6530
6808
|
rendered = false;
|
|
6809
|
+
waitingEnabled = false;
|
|
6810
|
+
waitingCards = [];
|
|
6811
|
+
currentCard = 0;
|
|
6812
|
+
cardTimer = null;
|
|
6813
|
+
keypressHandler = null;
|
|
6814
|
+
cachedCardLines = null;
|
|
6815
|
+
cachedCardIndex = -1;
|
|
6816
|
+
cachedCardCols = -1;
|
|
6531
6817
|
add(name) {
|
|
6532
6818
|
const index = this.tasks.length;
|
|
6533
6819
|
this.tasks.push({ name, status: "pending", message: "" });
|
|
@@ -6553,13 +6839,78 @@ var ParallelTaskDisplay = class {
|
|
|
6553
6839
|
task.status = status;
|
|
6554
6840
|
if (message !== void 0) task.message = message;
|
|
6555
6841
|
}
|
|
6842
|
+
enableWaitingContent() {
|
|
6843
|
+
if (!process.stdin.isTTY) return;
|
|
6844
|
+
this.waitingCards = WAITING_CARDS;
|
|
6845
|
+
if (this.waitingCards.length === 0) return;
|
|
6846
|
+
this.waitingEnabled = true;
|
|
6847
|
+
this.currentCard = 0;
|
|
6848
|
+
this.cardTimer = setInterval(() => {
|
|
6849
|
+
this.advanceCard(1);
|
|
6850
|
+
}, CARD_ADVANCE_MS);
|
|
6851
|
+
const { stdin } = process;
|
|
6852
|
+
stdin.setRawMode(true);
|
|
6853
|
+
stdin.resume();
|
|
6854
|
+
stdin.setEncoding("utf8");
|
|
6855
|
+
this.keypressHandler = (key) => {
|
|
6856
|
+
const str = String(key);
|
|
6857
|
+
switch (str) {
|
|
6858
|
+
case "\x1B[C":
|
|
6859
|
+
case "n":
|
|
6860
|
+
this.advanceCard(1);
|
|
6861
|
+
this.resetCardTimer();
|
|
6862
|
+
break;
|
|
6863
|
+
case "\x1B[D":
|
|
6864
|
+
case "p":
|
|
6865
|
+
this.advanceCard(-1);
|
|
6866
|
+
this.resetCardTimer();
|
|
6867
|
+
break;
|
|
6868
|
+
case "":
|
|
6869
|
+
this.disableWaitingContent();
|
|
6870
|
+
process.kill(process.pid, "SIGINT");
|
|
6871
|
+
break;
|
|
6872
|
+
}
|
|
6873
|
+
};
|
|
6874
|
+
stdin.on("data", this.keypressHandler);
|
|
6875
|
+
}
|
|
6556
6876
|
stop() {
|
|
6877
|
+
this.disableWaitingContent();
|
|
6557
6878
|
if (this.timer) {
|
|
6558
6879
|
clearInterval(this.timer);
|
|
6559
6880
|
this.timer = null;
|
|
6560
6881
|
}
|
|
6561
6882
|
this.draw(false);
|
|
6562
6883
|
}
|
|
6884
|
+
advanceCard(offset) {
|
|
6885
|
+
this.currentCard = (this.currentCard + offset + this.waitingCards.length) % this.waitingCards.length;
|
|
6886
|
+
this.cachedCardLines = null;
|
|
6887
|
+
}
|
|
6888
|
+
disableWaitingContent() {
|
|
6889
|
+
if (!this.waitingEnabled) return;
|
|
6890
|
+
if (this.cardTimer) {
|
|
6891
|
+
clearInterval(this.cardTimer);
|
|
6892
|
+
this.cardTimer = null;
|
|
6893
|
+
}
|
|
6894
|
+
if (this.keypressHandler) {
|
|
6895
|
+
const { stdin } = process;
|
|
6896
|
+
stdin.removeListener("data", this.keypressHandler);
|
|
6897
|
+
if (stdin.isTTY) {
|
|
6898
|
+
stdin.setRawMode(false);
|
|
6899
|
+
stdin.pause();
|
|
6900
|
+
}
|
|
6901
|
+
this.keypressHandler = null;
|
|
6902
|
+
}
|
|
6903
|
+
this.waitingEnabled = false;
|
|
6904
|
+
this.cachedCardLines = null;
|
|
6905
|
+
}
|
|
6906
|
+
resetCardTimer() {
|
|
6907
|
+
if (this.cardTimer) {
|
|
6908
|
+
clearInterval(this.cardTimer);
|
|
6909
|
+
this.cardTimer = setInterval(() => {
|
|
6910
|
+
this.advanceCard(1);
|
|
6911
|
+
}, CARD_ADVANCE_MS);
|
|
6912
|
+
}
|
|
6913
|
+
}
|
|
6563
6914
|
formatTime(ms) {
|
|
6564
6915
|
const secs = Math.floor(ms / 1e3);
|
|
6565
6916
|
if (secs < 60) return `${secs}s`;
|
|
@@ -6575,31 +6926,31 @@ var ParallelTaskDisplay = class {
|
|
|
6575
6926
|
renderLine(task) {
|
|
6576
6927
|
const cols = process.stdout.columns || 80;
|
|
6577
6928
|
const elapsed = task.startTime ? this.formatTime((task.endTime ?? Date.now()) - task.startTime) : "";
|
|
6578
|
-
const timeStr = elapsed ? ` ${
|
|
6929
|
+
const timeStr = elapsed ? ` ${chalk10.dim(elapsed)}` : "";
|
|
6579
6930
|
const timePlain = elapsed ? ` ${elapsed}` : "";
|
|
6580
6931
|
let icon;
|
|
6581
6932
|
let nameStyle;
|
|
6582
6933
|
let msgStyle;
|
|
6583
6934
|
switch (task.status) {
|
|
6584
6935
|
case "pending":
|
|
6585
|
-
icon =
|
|
6586
|
-
nameStyle =
|
|
6587
|
-
msgStyle =
|
|
6936
|
+
icon = chalk10.dim("\u25CB");
|
|
6937
|
+
nameStyle = chalk10.dim;
|
|
6938
|
+
msgStyle = chalk10.dim;
|
|
6588
6939
|
break;
|
|
6589
6940
|
case "running":
|
|
6590
|
-
icon =
|
|
6591
|
-
nameStyle =
|
|
6592
|
-
msgStyle =
|
|
6941
|
+
icon = chalk10.cyan(SPINNER_FRAMES[this.spinnerFrame]);
|
|
6942
|
+
nameStyle = chalk10.white;
|
|
6943
|
+
msgStyle = chalk10.dim;
|
|
6593
6944
|
break;
|
|
6594
6945
|
case "done":
|
|
6595
|
-
icon =
|
|
6596
|
-
nameStyle =
|
|
6597
|
-
msgStyle =
|
|
6946
|
+
icon = chalk10.green("\u2713");
|
|
6947
|
+
nameStyle = chalk10.white;
|
|
6948
|
+
msgStyle = chalk10.dim;
|
|
6598
6949
|
break;
|
|
6599
6950
|
case "failed":
|
|
6600
|
-
icon =
|
|
6601
|
-
nameStyle =
|
|
6602
|
-
msgStyle =
|
|
6951
|
+
icon = chalk10.red("\u2717");
|
|
6952
|
+
nameStyle = chalk10.white;
|
|
6953
|
+
msgStyle = chalk10.red;
|
|
6603
6954
|
break;
|
|
6604
6955
|
}
|
|
6605
6956
|
const paddedName = task.name.padEnd(NAME_COL_WIDTH);
|
|
@@ -6615,6 +6966,16 @@ var ParallelTaskDisplay = class {
|
|
|
6615
6966
|
}
|
|
6616
6967
|
stdout.write("\x1B[0J");
|
|
6617
6968
|
const lines = this.tasks.map((t) => this.renderLine(t));
|
|
6969
|
+
if (this.waitingEnabled && this.waitingCards.length > 0 && stdout.isTTY) {
|
|
6970
|
+
const cols = stdout.columns || 80;
|
|
6971
|
+
if (this.currentCard !== this.cachedCardIndex || cols !== this.cachedCardCols || !this.cachedCardLines) {
|
|
6972
|
+
const card = this.waitingCards[this.currentCard];
|
|
6973
|
+
this.cachedCardLines = renderCard(card, this.currentCard, this.waitingCards.length, cols);
|
|
6974
|
+
this.cachedCardIndex = this.currentCard;
|
|
6975
|
+
this.cachedCardCols = cols;
|
|
6976
|
+
}
|
|
6977
|
+
lines.push(...this.cachedCardLines);
|
|
6978
|
+
}
|
|
6618
6979
|
const output = lines.join("\n");
|
|
6619
6980
|
stdout.write(output + "\n");
|
|
6620
6981
|
this.lineCount = output.split("\n").length;
|
|
@@ -6624,11 +6985,11 @@ var ParallelTaskDisplay = class {
|
|
|
6624
6985
|
|
|
6625
6986
|
// src/commands/init.ts
|
|
6626
6987
|
function log(verbose, ...args) {
|
|
6627
|
-
if (verbose) console.log(
|
|
6988
|
+
if (verbose) console.log(chalk11.dim(` [verbose] ${args.map(String).join(" ")}`));
|
|
6628
6989
|
}
|
|
6629
6990
|
async function initCommand(options) {
|
|
6630
|
-
const brand =
|
|
6631
|
-
const title =
|
|
6991
|
+
const brand = chalk11.hex("#EB9D83");
|
|
6992
|
+
const title = chalk11.hex("#83D1EB");
|
|
6632
6993
|
console.log(brand.bold(`
|
|
6633
6994
|
\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
|
|
6634
6995
|
\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
|
|
@@ -6637,33 +6998,33 @@ async function initCommand(options) {
|
|
|
6637
6998
|
\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
|
|
6638
6999
|
\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
|
|
6639
7000
|
`));
|
|
6640
|
-
console.log(
|
|
6641
|
-
console.log(
|
|
7001
|
+
console.log(chalk11.dim(" Scan your project and generate tailored config files for"));
|
|
7002
|
+
console.log(chalk11.dim(" Claude Code, Cursor, and Codex.\n"));
|
|
6642
7003
|
const report = options.debugReport ? new DebugReport() : null;
|
|
6643
7004
|
console.log(title.bold(" How it works:\n"));
|
|
6644
|
-
console.log(
|
|
6645
|
-
console.log(
|
|
6646
|
-
console.log(
|
|
6647
|
-
console.log(
|
|
7005
|
+
console.log(chalk11.dim(" 1. Setup Connect your LLM provider and select your agents"));
|
|
7006
|
+
console.log(chalk11.dim(" 2. Engine Detect stack, generate configs & skills in parallel"));
|
|
7007
|
+
console.log(chalk11.dim(" 3. Review See all changes \u2014 accept, refine, or decline"));
|
|
7008
|
+
console.log(chalk11.dim(" 4. Finalize Score check and auto-sync hooks\n"));
|
|
6648
7009
|
console.log(title.bold(" Step 1/4 \u2014 Setup\n"));
|
|
6649
7010
|
let config = loadConfig();
|
|
6650
7011
|
if (!config) {
|
|
6651
|
-
console.log(
|
|
7012
|
+
console.log(chalk11.dim(" No LLM provider configured yet.\n"));
|
|
6652
7013
|
await runInteractiveProviderSetup({
|
|
6653
7014
|
selectMessage: "How do you want to use Caliber? (choose LLM provider)"
|
|
6654
7015
|
});
|
|
6655
7016
|
config = loadConfig();
|
|
6656
7017
|
if (!config) {
|
|
6657
|
-
console.log(
|
|
7018
|
+
console.log(chalk11.red(" Setup was cancelled or failed.\n"));
|
|
6658
7019
|
throw new Error("__exit__");
|
|
6659
7020
|
}
|
|
6660
|
-
console.log(
|
|
7021
|
+
console.log(chalk11.green(" \u2713 Provider saved\n"));
|
|
6661
7022
|
}
|
|
6662
7023
|
trackInitProviderSelected(config.provider, config.model);
|
|
6663
7024
|
const displayModel = getDisplayModel(config);
|
|
6664
7025
|
const fastModel = getFastModel();
|
|
6665
7026
|
const modelLine = fastModel ? ` Provider: ${config.provider} | Model: ${displayModel} | Scan: ${fastModel}` : ` Provider: ${config.provider} | Model: ${displayModel}`;
|
|
6666
|
-
console.log(
|
|
7027
|
+
console.log(chalk11.dim(modelLine + "\n"));
|
|
6667
7028
|
if (report) {
|
|
6668
7029
|
report.markStep("Provider setup");
|
|
6669
7030
|
report.addSection("LLM Provider", `- **Provider**: ${config.provider}
|
|
@@ -6680,7 +7041,7 @@ async function initCommand(options) {
|
|
|
6680
7041
|
} else {
|
|
6681
7042
|
targetAgent = await promptAgent();
|
|
6682
7043
|
}
|
|
6683
|
-
console.log(
|
|
7044
|
+
console.log(chalk11.dim(` Target: ${targetAgent.join(", ")}
|
|
6684
7045
|
`));
|
|
6685
7046
|
trackInitAgentSelected(targetAgent);
|
|
6686
7047
|
let wantsSkills = false;
|
|
@@ -6694,7 +7055,7 @@ async function initCommand(options) {
|
|
|
6694
7055
|
});
|
|
6695
7056
|
}
|
|
6696
7057
|
let baselineScore = computeLocalScore(process.cwd(), targetAgent);
|
|
6697
|
-
console.log(
|
|
7058
|
+
console.log(chalk11.dim("\n Current setup score:"));
|
|
6698
7059
|
displayScoreSummary(baselineScore);
|
|
6699
7060
|
if (options.verbose) {
|
|
6700
7061
|
for (const c of baselineScore.checks) {
|
|
@@ -6723,29 +7084,29 @@ async function initCommand(options) {
|
|
|
6723
7084
|
const failingCount = baselineScore.checks.filter((c) => !c.passed).length;
|
|
6724
7085
|
if (hasExistingConfig && baselineScore.score === 100) {
|
|
6725
7086
|
trackInitScoreComputed(baselineScore.score, passingCount, failingCount, true);
|
|
6726
|
-
console.log(
|
|
6727
|
-
console.log(
|
|
7087
|
+
console.log(chalk11.bold.green(" Your setup is already optimal \u2014 nothing to change.\n"));
|
|
7088
|
+
console.log(chalk11.dim(" Run ") + chalk11.hex("#83D1EB")("caliber init --force") + chalk11.dim(" to regenerate anyway.\n"));
|
|
6728
7089
|
if (!options.force) return;
|
|
6729
7090
|
}
|
|
6730
7091
|
const allFailingChecks = baselineScore.checks.filter((c) => !c.passed && c.maxPoints > 0);
|
|
6731
7092
|
const llmFixableChecks = allFailingChecks.filter((c) => !NON_LLM_CHECKS.has(c.id));
|
|
6732
7093
|
trackInitScoreComputed(baselineScore.score, passingCount, failingCount, false);
|
|
6733
7094
|
if (hasExistingConfig && llmFixableChecks.length === 0 && allFailingChecks.length > 0 && !options.force) {
|
|
6734
|
-
console.log(
|
|
6735
|
-
console.log(
|
|
7095
|
+
console.log(chalk11.bold.green("\n Your config is fully optimized for LLM generation.\n"));
|
|
7096
|
+
console.log(chalk11.dim(" Remaining items need CLI actions:\n"));
|
|
6736
7097
|
for (const check of allFailingChecks) {
|
|
6737
|
-
console.log(
|
|
7098
|
+
console.log(chalk11.dim(` \u2022 ${check.name}`));
|
|
6738
7099
|
if (check.suggestion) {
|
|
6739
|
-
console.log(` ${
|
|
7100
|
+
console.log(` ${chalk11.hex("#83D1EB")(check.suggestion)}`);
|
|
6740
7101
|
}
|
|
6741
7102
|
}
|
|
6742
7103
|
console.log("");
|
|
6743
|
-
console.log(
|
|
7104
|
+
console.log(chalk11.dim(" Run ") + chalk11.hex("#83D1EB")("caliber init --force") + chalk11.dim(" to regenerate anyway.\n"));
|
|
6744
7105
|
return;
|
|
6745
7106
|
}
|
|
6746
7107
|
console.log(title.bold(" Step 2/4 \u2014 Engine\n"));
|
|
6747
7108
|
const genModelInfo = fastModel ? ` Using ${displayModel} for docs, ${fastModel} for skills` : ` Using ${displayModel}`;
|
|
6748
|
-
console.log(
|
|
7109
|
+
console.log(chalk11.dim(genModelInfo + "\n"));
|
|
6749
7110
|
if (report) report.markStep("Generation");
|
|
6750
7111
|
trackInitGenerationStarted(false);
|
|
6751
7112
|
const genStartTime = Date.now();
|
|
@@ -6760,6 +7121,7 @@ async function initCommand(options) {
|
|
|
6760
7121
|
const TASK_SKILLS_GEN = display.add("Generating skills");
|
|
6761
7122
|
const TASK_SKILLS_SEARCH = wantsSkills ? display.add("Searching community skills") : -1;
|
|
6762
7123
|
display.start();
|
|
7124
|
+
display.enableWaitingContent();
|
|
6763
7125
|
try {
|
|
6764
7126
|
display.update(TASK_STACK, "running");
|
|
6765
7127
|
fingerprint = await collectFingerprint(process.cwd());
|
|
@@ -6869,7 +7231,7 @@ async function initCommand(options) {
|
|
|
6869
7231
|
} catch (err) {
|
|
6870
7232
|
display.stop();
|
|
6871
7233
|
const msg = err instanceof Error ? err.message : "Unknown error";
|
|
6872
|
-
console.log(
|
|
7234
|
+
console.log(chalk11.red(`
|
|
6873
7235
|
Engine failed: ${msg}
|
|
6874
7236
|
`));
|
|
6875
7237
|
writeErrorLog(config, void 0, msg, "exception");
|
|
@@ -6881,15 +7243,15 @@ async function initCommand(options) {
|
|
|
6881
7243
|
const mins = Math.floor(elapsedMs / 6e4);
|
|
6882
7244
|
const secs = Math.floor(elapsedMs % 6e4 / 1e3);
|
|
6883
7245
|
const timeStr = mins > 0 ? `${mins}m ${secs}s` : `${secs}s`;
|
|
6884
|
-
console.log(
|
|
7246
|
+
console.log(chalk11.dim(`
|
|
6885
7247
|
Done in ${timeStr}
|
|
6886
7248
|
`));
|
|
6887
7249
|
if (!generatedSetup) {
|
|
6888
|
-
console.log(
|
|
7250
|
+
console.log(chalk11.red(" Failed to generate setup."));
|
|
6889
7251
|
writeErrorLog(config, rawOutput, void 0, genStopReason);
|
|
6890
7252
|
if (rawOutput) {
|
|
6891
|
-
console.log(
|
|
6892
|
-
console.log(
|
|
7253
|
+
console.log(chalk11.dim("\nRaw LLM output (JSON parse failed):"));
|
|
7254
|
+
console.log(chalk11.dim(rawOutput.slice(0, 500)));
|
|
6893
7255
|
}
|
|
6894
7256
|
throw new Error("__exit__");
|
|
6895
7257
|
}
|
|
@@ -6898,19 +7260,19 @@ async function initCommand(options) {
|
|
|
6898
7260
|
report.addJson("Generation: Parsed Setup", generatedSetup);
|
|
6899
7261
|
}
|
|
6900
7262
|
log(options.verbose, `Generation completed: ${elapsedMs}ms, stopReason: ${genStopReason || "end_turn"}`);
|
|
6901
|
-
printSetupSummary(generatedSetup);
|
|
6902
7263
|
const sessionHistory = [];
|
|
6903
7264
|
sessionHistory.push({
|
|
6904
7265
|
role: "assistant",
|
|
6905
7266
|
content: summarizeSetup("Initial generation", generatedSetup)
|
|
6906
7267
|
});
|
|
7268
|
+
generatedSetup = await runScoreRefineWithSpinner(generatedSetup, process.cwd(), sessionHistory);
|
|
6907
7269
|
console.log(title.bold(" Step 3/4 \u2014 Review\n"));
|
|
6908
7270
|
const setupFiles = collectSetupFiles(generatedSetup, targetAgent);
|
|
6909
7271
|
const staged = stageFiles(setupFiles, process.cwd());
|
|
6910
7272
|
const totalChanges = staged.newFiles + staged.modifiedFiles;
|
|
6911
|
-
console.log(
|
|
7273
|
+
console.log(chalk11.dim(` ${chalk11.green(`${staged.newFiles} new`)} / ${chalk11.yellow(`${staged.modifiedFiles} modified`)} file${totalChanges !== 1 ? "s" : ""}`));
|
|
6912
7274
|
if (skillSearchResult.results.length > 0) {
|
|
6913
|
-
console.log(
|
|
7275
|
+
console.log(chalk11.dim(` ${chalk11.cyan(`${skillSearchResult.results.length}`)} community skills available to install
|
|
6914
7276
|
`));
|
|
6915
7277
|
} else {
|
|
6916
7278
|
console.log("");
|
|
@@ -6918,7 +7280,7 @@ async function initCommand(options) {
|
|
|
6918
7280
|
const hasSkillResults = skillSearchResult.results.length > 0;
|
|
6919
7281
|
let action;
|
|
6920
7282
|
if (totalChanges === 0 && !hasSkillResults) {
|
|
6921
|
-
console.log(
|
|
7283
|
+
console.log(chalk11.dim(" No changes needed \u2014 your configs are already up to date.\n"));
|
|
6922
7284
|
cleanupStaging();
|
|
6923
7285
|
action = "accept";
|
|
6924
7286
|
} else if (options.autoApprove) {
|
|
@@ -6950,12 +7312,12 @@ async function initCommand(options) {
|
|
|
6950
7312
|
trackInitRefinementRound(refinementRound, !!generatedSetup);
|
|
6951
7313
|
if (!generatedSetup) {
|
|
6952
7314
|
cleanupStaging();
|
|
6953
|
-
console.log(
|
|
7315
|
+
console.log(chalk11.dim("Refinement cancelled. No files were modified."));
|
|
6954
7316
|
return;
|
|
6955
7317
|
}
|
|
6956
7318
|
const updatedFiles = collectSetupFiles(generatedSetup, targetAgent);
|
|
6957
7319
|
const restaged = stageFiles(updatedFiles, process.cwd());
|
|
6958
|
-
console.log(
|
|
7320
|
+
console.log(chalk11.dim(` ${chalk11.green(`${restaged.newFiles} new`)} / ${chalk11.yellow(`${restaged.modifiedFiles} modified`)} file${restaged.newFiles + restaged.modifiedFiles !== 1 ? "s" : ""}
|
|
6959
7321
|
`));
|
|
6960
7322
|
printSetupSummary(generatedSetup);
|
|
6961
7323
|
await openReview("terminal", restaged.stagedFiles);
|
|
@@ -6964,16 +7326,16 @@ async function initCommand(options) {
|
|
|
6964
7326
|
}
|
|
6965
7327
|
cleanupStaging();
|
|
6966
7328
|
if (action === "decline") {
|
|
6967
|
-
console.log(
|
|
7329
|
+
console.log(chalk11.dim("Setup declined. No files were modified."));
|
|
6968
7330
|
return;
|
|
6969
7331
|
}
|
|
6970
7332
|
console.log(title.bold("\n Step 4/4 \u2014 Finalize\n"));
|
|
6971
7333
|
if (options.dryRun) {
|
|
6972
|
-
console.log(
|
|
7334
|
+
console.log(chalk11.yellow("\n[Dry run] Would write the following files:"));
|
|
6973
7335
|
console.log(JSON.stringify(generatedSetup, null, 2));
|
|
6974
7336
|
return;
|
|
6975
7337
|
}
|
|
6976
|
-
const writeSpinner =
|
|
7338
|
+
const writeSpinner = ora3("Writing config files...").start();
|
|
6977
7339
|
try {
|
|
6978
7340
|
if (targetAgent.includes("codex") && !fs25.existsSync("AGENTS.md") && !generatedSetup.codex) {
|
|
6979
7341
|
const claude = generatedSetup.claude;
|
|
@@ -6998,23 +7360,23 @@ ${agentRefs.join(" ")}
|
|
|
6998
7360
|
0,
|
|
6999
7361
|
result.deleted.length
|
|
7000
7362
|
);
|
|
7001
|
-
console.log(
|
|
7363
|
+
console.log(chalk11.bold("\nFiles created/updated:"));
|
|
7002
7364
|
for (const file of result.written) {
|
|
7003
|
-
console.log(` ${
|
|
7365
|
+
console.log(` ${chalk11.green("\u2713")} ${file}`);
|
|
7004
7366
|
}
|
|
7005
7367
|
if (result.deleted.length > 0) {
|
|
7006
|
-
console.log(
|
|
7368
|
+
console.log(chalk11.bold("\nFiles removed:"));
|
|
7007
7369
|
for (const file of result.deleted) {
|
|
7008
|
-
console.log(` ${
|
|
7370
|
+
console.log(` ${chalk11.red("\u2717")} ${file}`);
|
|
7009
7371
|
}
|
|
7010
7372
|
}
|
|
7011
7373
|
if (result.backupDir) {
|
|
7012
|
-
console.log(
|
|
7374
|
+
console.log(chalk11.dim(`
|
|
7013
7375
|
Backups saved to ${result.backupDir}`));
|
|
7014
7376
|
}
|
|
7015
7377
|
} catch (err) {
|
|
7016
7378
|
writeSpinner.fail("Failed to write files");
|
|
7017
|
-
console.error(
|
|
7379
|
+
console.error(chalk11.red(err instanceof Error ? err.message : "Unknown error"));
|
|
7018
7380
|
throw new Error("__exit__");
|
|
7019
7381
|
}
|
|
7020
7382
|
if (fingerprint) ensurePermissions(fingerprint);
|
|
@@ -7028,15 +7390,15 @@ ${agentRefs.join(" ")}
|
|
|
7028
7390
|
if (afterScore.score < baselineScore.score) {
|
|
7029
7391
|
trackInitScoreRegression(baselineScore.score, afterScore.score);
|
|
7030
7392
|
console.log("");
|
|
7031
|
-
console.log(
|
|
7393
|
+
console.log(chalk11.yellow(` Score would drop from ${baselineScore.score} to ${afterScore.score} \u2014 reverting changes.`));
|
|
7032
7394
|
try {
|
|
7033
7395
|
const { restored, removed } = undoSetup();
|
|
7034
7396
|
if (restored.length > 0 || removed.length > 0) {
|
|
7035
|
-
console.log(
|
|
7397
|
+
console.log(chalk11.dim(` Reverted ${restored.length + removed.length} file${restored.length + removed.length === 1 ? "" : "s"} from backup.`));
|
|
7036
7398
|
}
|
|
7037
7399
|
} catch {
|
|
7038
7400
|
}
|
|
7039
|
-
console.log(
|
|
7401
|
+
console.log(chalk11.dim(" Run ") + chalk11.hex("#83D1EB")("caliber init --force") + chalk11.dim(" to override.\n"));
|
|
7040
7402
|
return;
|
|
7041
7403
|
}
|
|
7042
7404
|
if (report) {
|
|
@@ -7055,7 +7417,7 @@ ${agentRefs.join(" ")}
|
|
|
7055
7417
|
}
|
|
7056
7418
|
}
|
|
7057
7419
|
if (skillSearchResult.results.length > 0 && !options.autoApprove) {
|
|
7058
|
-
console.log(
|
|
7420
|
+
console.log(chalk11.dim(" Community skills matched to your project:\n"));
|
|
7059
7421
|
const selected = await interactiveSelect(skillSearchResult.results);
|
|
7060
7422
|
if (selected?.length) {
|
|
7061
7423
|
await installSkills(selected, targetAgent, skillSearchResult.contentMap);
|
|
@@ -7074,37 +7436,37 @@ ${agentRefs.join(" ")}
|
|
|
7074
7436
|
if (hookChoice === "claude" || hookChoice === "both") {
|
|
7075
7437
|
const hookResult = installHook();
|
|
7076
7438
|
if (hookResult.installed) {
|
|
7077
|
-
console.log(` ${
|
|
7078
|
-
console.log(
|
|
7439
|
+
console.log(` ${chalk11.green("\u2713")} Claude Code hook installed \u2014 docs update on session end`);
|
|
7440
|
+
console.log(chalk11.dim(" Run ") + chalk11.hex("#83D1EB")("caliber hooks --remove") + chalk11.dim(" to disable"));
|
|
7079
7441
|
} else if (hookResult.alreadyInstalled) {
|
|
7080
|
-
console.log(
|
|
7442
|
+
console.log(chalk11.dim(" Claude Code hook already installed"));
|
|
7081
7443
|
}
|
|
7082
7444
|
const learnResult = installLearningHooks();
|
|
7083
7445
|
if (learnResult.installed) {
|
|
7084
|
-
console.log(` ${
|
|
7085
|
-
console.log(
|
|
7446
|
+
console.log(` ${chalk11.green("\u2713")} Learning hooks installed \u2014 session insights captured automatically`);
|
|
7447
|
+
console.log(chalk11.dim(" Run ") + chalk11.hex("#83D1EB")("caliber learn remove") + chalk11.dim(" to disable"));
|
|
7086
7448
|
} else if (learnResult.alreadyInstalled) {
|
|
7087
|
-
console.log(
|
|
7449
|
+
console.log(chalk11.dim(" Learning hooks already installed"));
|
|
7088
7450
|
}
|
|
7089
7451
|
}
|
|
7090
7452
|
if (hookChoice === "precommit" || hookChoice === "both") {
|
|
7091
7453
|
const precommitResult = installPreCommitHook();
|
|
7092
7454
|
if (precommitResult.installed) {
|
|
7093
|
-
console.log(` ${
|
|
7094
|
-
console.log(
|
|
7455
|
+
console.log(` ${chalk11.green("\u2713")} Pre-commit hook installed \u2014 docs refresh before each commit`);
|
|
7456
|
+
console.log(chalk11.dim(" Run ") + chalk11.hex("#83D1EB")("caliber hooks --remove") + chalk11.dim(" to disable"));
|
|
7095
7457
|
} else if (precommitResult.alreadyInstalled) {
|
|
7096
|
-
console.log(
|
|
7458
|
+
console.log(chalk11.dim(" Pre-commit hook already installed"));
|
|
7097
7459
|
} else {
|
|
7098
|
-
console.log(
|
|
7460
|
+
console.log(chalk11.yellow(" Could not install pre-commit hook (not a git repository?)"));
|
|
7099
7461
|
}
|
|
7100
7462
|
}
|
|
7101
7463
|
if (hookChoice === "skip") {
|
|
7102
|
-
console.log(
|
|
7464
|
+
console.log(chalk11.dim(" Skipped auto-sync hooks. Run ") + chalk11.hex("#83D1EB")("caliber hooks --install") + chalk11.dim(" later to enable."));
|
|
7103
7465
|
}
|
|
7104
|
-
console.log(
|
|
7105
|
-
console.log(
|
|
7106
|
-
console.log(
|
|
7107
|
-
console.log(
|
|
7466
|
+
console.log(chalk11.bold.green("\n Setup complete!"));
|
|
7467
|
+
console.log(chalk11.dim(" Your AI agents now understand your project's architecture, build commands,"));
|
|
7468
|
+
console.log(chalk11.dim(" testing patterns, and conventions. All changes are backed up automatically.\n"));
|
|
7469
|
+
console.log(chalk11.bold(" Next steps:\n"));
|
|
7108
7470
|
console.log(` ${title("caliber score")} See your full config breakdown`);
|
|
7109
7471
|
console.log(` ${title("caliber refresh")} Update docs after code changes`);
|
|
7110
7472
|
console.log(` ${title("caliber hooks")} Toggle auto-refresh hooks`);
|
|
@@ -7118,7 +7480,7 @@ ${agentRefs.join(" ")}
|
|
|
7118
7480
|
report.markStep("Finished");
|
|
7119
7481
|
const reportPath = path20.join(process.cwd(), ".caliber", "debug-report.md");
|
|
7120
7482
|
report.write(reportPath);
|
|
7121
|
-
console.log(
|
|
7483
|
+
console.log(chalk11.dim(` Debug report written to ${path20.relative(process.cwd(), reportPath)}
|
|
7122
7484
|
`));
|
|
7123
7485
|
}
|
|
7124
7486
|
}
|
|
@@ -7133,12 +7495,12 @@ async function refineLoop(currentSetup, _targetAgent, sessionHistory) {
|
|
|
7133
7495
|
}
|
|
7134
7496
|
const isValid = await classifyRefineIntent(message);
|
|
7135
7497
|
if (!isValid) {
|
|
7136
|
-
console.log(
|
|
7137
|
-
console.log(
|
|
7138
|
-
console.log(
|
|
7498
|
+
console.log(chalk11.dim(" This doesn't look like a config change request."));
|
|
7499
|
+
console.log(chalk11.dim(" Describe what to add, remove, or modify in your configs."));
|
|
7500
|
+
console.log(chalk11.dim(' Type "done" to accept the current setup.\n'));
|
|
7139
7501
|
continue;
|
|
7140
7502
|
}
|
|
7141
|
-
const refineSpinner =
|
|
7503
|
+
const refineSpinner = ora3("Refining setup...").start();
|
|
7142
7504
|
const refineMessages = new SpinnerMessages(refineSpinner, REFINE_MESSAGES);
|
|
7143
7505
|
refineMessages.start();
|
|
7144
7506
|
const refined = await refineSetup(
|
|
@@ -7156,10 +7518,10 @@ async function refineLoop(currentSetup, _targetAgent, sessionHistory) {
|
|
|
7156
7518
|
});
|
|
7157
7519
|
refineSpinner.succeed("Setup updated");
|
|
7158
7520
|
printSetupSummary(refined);
|
|
7159
|
-
console.log(
|
|
7521
|
+
console.log(chalk11.dim('Type "done" to accept, or describe more changes.'));
|
|
7160
7522
|
} else {
|
|
7161
7523
|
refineSpinner.fail("Refinement failed \u2014 could not parse AI response.");
|
|
7162
|
-
console.log(
|
|
7524
|
+
console.log(chalk11.dim('Try rephrasing your request, or type "done" to keep the current setup.'));
|
|
7163
7525
|
}
|
|
7164
7526
|
}
|
|
7165
7527
|
}
|
|
@@ -7274,26 +7636,26 @@ function printSetupSummary(setup) {
|
|
|
7274
7636
|
const fileDescriptions = setup.fileDescriptions;
|
|
7275
7637
|
const deletions = setup.deletions;
|
|
7276
7638
|
console.log("");
|
|
7277
|
-
console.log(
|
|
7639
|
+
console.log(chalk11.bold(" Your tailored setup:\n"));
|
|
7278
7640
|
const getDescription = (filePath) => {
|
|
7279
7641
|
return fileDescriptions?.[filePath];
|
|
7280
7642
|
};
|
|
7281
7643
|
if (claude) {
|
|
7282
7644
|
if (claude.claudeMd) {
|
|
7283
|
-
const icon = fs25.existsSync("CLAUDE.md") ?
|
|
7645
|
+
const icon = fs25.existsSync("CLAUDE.md") ? chalk11.yellow("~") : chalk11.green("+");
|
|
7284
7646
|
const desc = getDescription("CLAUDE.md");
|
|
7285
|
-
console.log(` ${icon} ${
|
|
7286
|
-
if (desc) console.log(
|
|
7647
|
+
console.log(` ${icon} ${chalk11.bold("CLAUDE.md")}`);
|
|
7648
|
+
if (desc) console.log(chalk11.dim(` ${desc}`));
|
|
7287
7649
|
console.log("");
|
|
7288
7650
|
}
|
|
7289
7651
|
const skills = claude.skills;
|
|
7290
7652
|
if (Array.isArray(skills) && skills.length > 0) {
|
|
7291
7653
|
for (const skill of skills) {
|
|
7292
7654
|
const skillPath = `.claude/skills/${skill.name}/SKILL.md`;
|
|
7293
|
-
const icon = fs25.existsSync(skillPath) ?
|
|
7655
|
+
const icon = fs25.existsSync(skillPath) ? chalk11.yellow("~") : chalk11.green("+");
|
|
7294
7656
|
const desc = getDescription(skillPath);
|
|
7295
|
-
console.log(` ${icon} ${
|
|
7296
|
-
console.log(
|
|
7657
|
+
console.log(` ${icon} ${chalk11.bold(skillPath)}`);
|
|
7658
|
+
console.log(chalk11.dim(` ${desc || skill.description || skill.name}`));
|
|
7297
7659
|
console.log("");
|
|
7298
7660
|
}
|
|
7299
7661
|
}
|
|
@@ -7301,40 +7663,40 @@ function printSetupSummary(setup) {
|
|
|
7301
7663
|
const codex = setup.codex;
|
|
7302
7664
|
if (codex) {
|
|
7303
7665
|
if (codex.agentsMd) {
|
|
7304
|
-
const icon = fs25.existsSync("AGENTS.md") ?
|
|
7666
|
+
const icon = fs25.existsSync("AGENTS.md") ? chalk11.yellow("~") : chalk11.green("+");
|
|
7305
7667
|
const desc = getDescription("AGENTS.md");
|
|
7306
|
-
console.log(` ${icon} ${
|
|
7307
|
-
if (desc) console.log(
|
|
7668
|
+
console.log(` ${icon} ${chalk11.bold("AGENTS.md")}`);
|
|
7669
|
+
if (desc) console.log(chalk11.dim(` ${desc}`));
|
|
7308
7670
|
console.log("");
|
|
7309
7671
|
}
|
|
7310
7672
|
const codexSkills = codex.skills;
|
|
7311
7673
|
if (Array.isArray(codexSkills) && codexSkills.length > 0) {
|
|
7312
7674
|
for (const skill of codexSkills) {
|
|
7313
7675
|
const skillPath = `.agents/skills/${skill.name}/SKILL.md`;
|
|
7314
|
-
const icon = fs25.existsSync(skillPath) ?
|
|
7676
|
+
const icon = fs25.existsSync(skillPath) ? chalk11.yellow("~") : chalk11.green("+");
|
|
7315
7677
|
const desc = getDescription(skillPath);
|
|
7316
|
-
console.log(` ${icon} ${
|
|
7317
|
-
console.log(
|
|
7678
|
+
console.log(` ${icon} ${chalk11.bold(skillPath)}`);
|
|
7679
|
+
console.log(chalk11.dim(` ${desc || skill.description || skill.name}`));
|
|
7318
7680
|
console.log("");
|
|
7319
7681
|
}
|
|
7320
7682
|
}
|
|
7321
7683
|
}
|
|
7322
7684
|
if (cursor) {
|
|
7323
7685
|
if (cursor.cursorrules) {
|
|
7324
|
-
const icon = fs25.existsSync(".cursorrules") ?
|
|
7686
|
+
const icon = fs25.existsSync(".cursorrules") ? chalk11.yellow("~") : chalk11.green("+");
|
|
7325
7687
|
const desc = getDescription(".cursorrules");
|
|
7326
|
-
console.log(` ${icon} ${
|
|
7327
|
-
if (desc) console.log(
|
|
7688
|
+
console.log(` ${icon} ${chalk11.bold(".cursorrules")}`);
|
|
7689
|
+
if (desc) console.log(chalk11.dim(` ${desc}`));
|
|
7328
7690
|
console.log("");
|
|
7329
7691
|
}
|
|
7330
7692
|
const cursorSkills = cursor.skills;
|
|
7331
7693
|
if (Array.isArray(cursorSkills) && cursorSkills.length > 0) {
|
|
7332
7694
|
for (const skill of cursorSkills) {
|
|
7333
7695
|
const skillPath = `.cursor/skills/${skill.name}/SKILL.md`;
|
|
7334
|
-
const icon = fs25.existsSync(skillPath) ?
|
|
7696
|
+
const icon = fs25.existsSync(skillPath) ? chalk11.yellow("~") : chalk11.green("+");
|
|
7335
7697
|
const desc = getDescription(skillPath);
|
|
7336
|
-
console.log(` ${icon} ${
|
|
7337
|
-
console.log(
|
|
7698
|
+
console.log(` ${icon} ${chalk11.bold(skillPath)}`);
|
|
7699
|
+
console.log(chalk11.dim(` ${desc || skill.description || skill.name}`));
|
|
7338
7700
|
console.log("");
|
|
7339
7701
|
}
|
|
7340
7702
|
}
|
|
@@ -7342,14 +7704,14 @@ function printSetupSummary(setup) {
|
|
|
7342
7704
|
if (Array.isArray(rules) && rules.length > 0) {
|
|
7343
7705
|
for (const rule of rules) {
|
|
7344
7706
|
const rulePath = `.cursor/rules/${rule.filename}`;
|
|
7345
|
-
const icon = fs25.existsSync(rulePath) ?
|
|
7707
|
+
const icon = fs25.existsSync(rulePath) ? chalk11.yellow("~") : chalk11.green("+");
|
|
7346
7708
|
const desc = getDescription(rulePath);
|
|
7347
|
-
console.log(` ${icon} ${
|
|
7709
|
+
console.log(` ${icon} ${chalk11.bold(rulePath)}`);
|
|
7348
7710
|
if (desc) {
|
|
7349
|
-
console.log(
|
|
7711
|
+
console.log(chalk11.dim(` ${desc}`));
|
|
7350
7712
|
} else {
|
|
7351
7713
|
const firstLine = rule.content.split("\n").filter((l) => l.trim() && !l.trim().startsWith("#"))[0];
|
|
7352
|
-
if (firstLine) console.log(
|
|
7714
|
+
if (firstLine) console.log(chalk11.dim(` ${firstLine.trim().slice(0, 80)}`));
|
|
7353
7715
|
}
|
|
7354
7716
|
console.log("");
|
|
7355
7717
|
}
|
|
@@ -7357,12 +7719,12 @@ function printSetupSummary(setup) {
|
|
|
7357
7719
|
}
|
|
7358
7720
|
if (Array.isArray(deletions) && deletions.length > 0) {
|
|
7359
7721
|
for (const del of deletions) {
|
|
7360
|
-
console.log(` ${
|
|
7361
|
-
console.log(
|
|
7722
|
+
console.log(` ${chalk11.red("-")} ${chalk11.bold(del.filePath)}`);
|
|
7723
|
+
console.log(chalk11.dim(` ${del.reason}`));
|
|
7362
7724
|
console.log("");
|
|
7363
7725
|
}
|
|
7364
7726
|
}
|
|
7365
|
-
console.log(` ${
|
|
7727
|
+
console.log(` ${chalk11.green("+")} ${chalk11.dim("new")} ${chalk11.yellow("~")} ${chalk11.dim("modified")} ${chalk11.red("-")} ${chalk11.dim("removed")}`);
|
|
7366
7728
|
console.log("");
|
|
7367
7729
|
}
|
|
7368
7730
|
function derivePermissions(fingerprint) {
|
|
@@ -7422,20 +7784,20 @@ function ensurePermissions(fingerprint) {
|
|
|
7422
7784
|
function displayTokenUsage() {
|
|
7423
7785
|
const summary = getUsageSummary();
|
|
7424
7786
|
if (summary.length === 0) {
|
|
7425
|
-
console.log(
|
|
7787
|
+
console.log(chalk11.dim(" Token tracking not available for this provider.\n"));
|
|
7426
7788
|
return;
|
|
7427
7789
|
}
|
|
7428
|
-
console.log(
|
|
7790
|
+
console.log(chalk11.bold(" Token usage:\n"));
|
|
7429
7791
|
let totalIn = 0;
|
|
7430
7792
|
let totalOut = 0;
|
|
7431
7793
|
for (const m of summary) {
|
|
7432
7794
|
totalIn += m.inputTokens;
|
|
7433
7795
|
totalOut += m.outputTokens;
|
|
7434
|
-
const cacheInfo = m.cacheReadTokens > 0 || m.cacheWriteTokens > 0 ?
|
|
7435
|
-
console.log(` ${
|
|
7796
|
+
const cacheInfo = m.cacheReadTokens > 0 || m.cacheWriteTokens > 0 ? chalk11.dim(` (cache: ${m.cacheReadTokens.toLocaleString()} read, ${m.cacheWriteTokens.toLocaleString()} write)`) : "";
|
|
7797
|
+
console.log(` ${chalk11.dim(m.model)}: ${m.inputTokens.toLocaleString()} in / ${m.outputTokens.toLocaleString()} out (${m.calls} call${m.calls === 1 ? "" : "s"})${cacheInfo}`);
|
|
7436
7798
|
}
|
|
7437
7799
|
if (summary.length > 1) {
|
|
7438
|
-
console.log(` ${
|
|
7800
|
+
console.log(` ${chalk11.dim("Total")}: ${totalIn.toLocaleString()} in / ${totalOut.toLocaleString()} out`);
|
|
7439
7801
|
}
|
|
7440
7802
|
console.log("");
|
|
7441
7803
|
}
|
|
@@ -7456,17 +7818,17 @@ function writeErrorLog(config, rawOutput, error, stopReason) {
|
|
|
7456
7818
|
lines.push("## Raw LLM Output", "```", rawOutput || "(empty)", "```");
|
|
7457
7819
|
fs25.mkdirSync(path20.join(process.cwd(), ".caliber"), { recursive: true });
|
|
7458
7820
|
fs25.writeFileSync(logPath, lines.join("\n"));
|
|
7459
|
-
console.log(
|
|
7821
|
+
console.log(chalk11.dim(`
|
|
7460
7822
|
Error log written to .caliber/error-log.md`));
|
|
7461
7823
|
} catch {
|
|
7462
7824
|
}
|
|
7463
7825
|
}
|
|
7464
7826
|
|
|
7465
7827
|
// src/commands/undo.ts
|
|
7466
|
-
import
|
|
7467
|
-
import
|
|
7828
|
+
import chalk12 from "chalk";
|
|
7829
|
+
import ora4 from "ora";
|
|
7468
7830
|
function undoCommand() {
|
|
7469
|
-
const spinner =
|
|
7831
|
+
const spinner = ora4("Reverting setup...").start();
|
|
7470
7832
|
try {
|
|
7471
7833
|
const { restored, removed } = undoSetup();
|
|
7472
7834
|
if (restored.length === 0 && removed.length === 0) {
|
|
@@ -7476,26 +7838,26 @@ function undoCommand() {
|
|
|
7476
7838
|
trackUndoExecuted();
|
|
7477
7839
|
spinner.succeed("Setup reverted successfully.\n");
|
|
7478
7840
|
if (restored.length > 0) {
|
|
7479
|
-
console.log(
|
|
7841
|
+
console.log(chalk12.cyan(" Restored from backup:"));
|
|
7480
7842
|
for (const file of restored) {
|
|
7481
|
-
console.log(` ${
|
|
7843
|
+
console.log(` ${chalk12.green("\u21A9")} ${file}`);
|
|
7482
7844
|
}
|
|
7483
7845
|
}
|
|
7484
7846
|
if (removed.length > 0) {
|
|
7485
|
-
console.log(
|
|
7847
|
+
console.log(chalk12.cyan(" Removed:"));
|
|
7486
7848
|
for (const file of removed) {
|
|
7487
|
-
console.log(` ${
|
|
7849
|
+
console.log(` ${chalk12.red("\u2717")} ${file}`);
|
|
7488
7850
|
}
|
|
7489
7851
|
}
|
|
7490
7852
|
console.log("");
|
|
7491
7853
|
} catch (err) {
|
|
7492
|
-
spinner.fail(
|
|
7854
|
+
spinner.fail(chalk12.red(err instanceof Error ? err.message : "Undo failed"));
|
|
7493
7855
|
throw new Error("__exit__");
|
|
7494
7856
|
}
|
|
7495
7857
|
}
|
|
7496
7858
|
|
|
7497
7859
|
// src/commands/status.ts
|
|
7498
|
-
import
|
|
7860
|
+
import chalk13 from "chalk";
|
|
7499
7861
|
import fs26 from "fs";
|
|
7500
7862
|
init_config();
|
|
7501
7863
|
async function statusCommand(options) {
|
|
@@ -7510,54 +7872,54 @@ async function statusCommand(options) {
|
|
|
7510
7872
|
}, null, 2));
|
|
7511
7873
|
return;
|
|
7512
7874
|
}
|
|
7513
|
-
console.log(
|
|
7875
|
+
console.log(chalk13.bold("\nCaliber Status\n"));
|
|
7514
7876
|
if (config) {
|
|
7515
|
-
console.log(` LLM: ${
|
|
7877
|
+
console.log(` LLM: ${chalk13.green(config.provider)} (${config.model})`);
|
|
7516
7878
|
} else {
|
|
7517
|
-
console.log(` LLM: ${
|
|
7879
|
+
console.log(` LLM: ${chalk13.yellow("Not configured")} \u2014 run ${chalk13.hex("#83D1EB")("caliber config")}`);
|
|
7518
7880
|
}
|
|
7519
7881
|
if (!manifest) {
|
|
7520
|
-
console.log(` Setup: ${
|
|
7521
|
-
console.log(
|
|
7882
|
+
console.log(` Setup: ${chalk13.dim("No setup applied")}`);
|
|
7883
|
+
console.log(chalk13.dim("\n Run ") + chalk13.hex("#83D1EB")("caliber init") + chalk13.dim(" to get started.\n"));
|
|
7522
7884
|
return;
|
|
7523
7885
|
}
|
|
7524
|
-
console.log(` Files managed: ${
|
|
7886
|
+
console.log(` Files managed: ${chalk13.cyan(manifest.entries.length.toString())}`);
|
|
7525
7887
|
for (const entry of manifest.entries) {
|
|
7526
7888
|
const exists = fs26.existsSync(entry.path);
|
|
7527
|
-
const icon = exists ?
|
|
7889
|
+
const icon = exists ? chalk13.green("\u2713") : chalk13.red("\u2717");
|
|
7528
7890
|
console.log(` ${icon} ${entry.path} (${entry.action})`);
|
|
7529
7891
|
}
|
|
7530
7892
|
console.log("");
|
|
7531
7893
|
}
|
|
7532
7894
|
|
|
7533
7895
|
// src/commands/regenerate.ts
|
|
7534
|
-
import
|
|
7535
|
-
import
|
|
7896
|
+
import chalk14 from "chalk";
|
|
7897
|
+
import ora5 from "ora";
|
|
7536
7898
|
import select6 from "@inquirer/select";
|
|
7537
7899
|
init_config();
|
|
7538
7900
|
async function regenerateCommand(options) {
|
|
7539
7901
|
const config = loadConfig();
|
|
7540
7902
|
if (!config) {
|
|
7541
|
-
console.log(
|
|
7903
|
+
console.log(chalk14.red("No LLM provider configured. Run ") + chalk14.hex("#83D1EB")("caliber config") + chalk14.red(" first."));
|
|
7542
7904
|
throw new Error("__exit__");
|
|
7543
7905
|
}
|
|
7544
7906
|
const manifest = readManifest();
|
|
7545
7907
|
if (!manifest) {
|
|
7546
|
-
console.log(
|
|
7908
|
+
console.log(chalk14.yellow("No existing setup found. Run ") + chalk14.hex("#83D1EB")("caliber init") + chalk14.yellow(" first."));
|
|
7547
7909
|
throw new Error("__exit__");
|
|
7548
7910
|
}
|
|
7549
7911
|
const targetAgent = readState()?.targetAgent ?? ["claude", "cursor"];
|
|
7550
7912
|
await validateModel({ fast: true });
|
|
7551
|
-
const spinner =
|
|
7913
|
+
const spinner = ora5("Analyzing project...").start();
|
|
7552
7914
|
const fingerprint = await collectFingerprint(process.cwd());
|
|
7553
7915
|
spinner.succeed("Project analyzed");
|
|
7554
7916
|
const baselineScore = computeLocalScore(process.cwd(), targetAgent);
|
|
7555
7917
|
displayScoreSummary(baselineScore);
|
|
7556
7918
|
if (baselineScore.score === 100) {
|
|
7557
|
-
console.log(
|
|
7919
|
+
console.log(chalk14.green(" Your setup is already at 100/100 \u2014 nothing to regenerate.\n"));
|
|
7558
7920
|
return;
|
|
7559
7921
|
}
|
|
7560
|
-
const genSpinner =
|
|
7922
|
+
const genSpinner = ora5("Regenerating setup...").start();
|
|
7561
7923
|
const genMessages = new SpinnerMessages(genSpinner, GENERATION_MESSAGES, { showElapsedTime: true });
|
|
7562
7924
|
genMessages.start();
|
|
7563
7925
|
let generatedSetup = null;
|
|
@@ -7592,21 +7954,22 @@ async function regenerateCommand(options) {
|
|
|
7592
7954
|
throw new Error("__exit__");
|
|
7593
7955
|
}
|
|
7594
7956
|
genSpinner.succeed("Setup regenerated");
|
|
7957
|
+
generatedSetup = await runScoreRefineWithSpinner(generatedSetup, process.cwd(), []);
|
|
7595
7958
|
const setupFiles = collectSetupFiles(generatedSetup, targetAgent);
|
|
7596
7959
|
const staged = stageFiles(setupFiles, process.cwd());
|
|
7597
7960
|
const totalChanges = staged.newFiles + staged.modifiedFiles;
|
|
7598
|
-
console.log(
|
|
7599
|
-
${
|
|
7961
|
+
console.log(chalk14.dim(`
|
|
7962
|
+
${chalk14.green(`${staged.newFiles} new`)} / ${chalk14.yellow(`${staged.modifiedFiles} modified`)} file${totalChanges !== 1 ? "s" : ""}
|
|
7600
7963
|
`));
|
|
7601
7964
|
if (totalChanges === 0) {
|
|
7602
|
-
console.log(
|
|
7965
|
+
console.log(chalk14.dim(" No changes needed \u2014 your configs are already up to date.\n"));
|
|
7603
7966
|
cleanupStaging();
|
|
7604
7967
|
return;
|
|
7605
7968
|
}
|
|
7606
7969
|
if (options.dryRun) {
|
|
7607
|
-
console.log(
|
|
7970
|
+
console.log(chalk14.yellow("[Dry run] Would write:"));
|
|
7608
7971
|
for (const f of staged.stagedFiles) {
|
|
7609
|
-
console.log(` ${f.isNew ?
|
|
7972
|
+
console.log(` ${f.isNew ? chalk14.green("+") : chalk14.yellow("~")} ${f.relativePath}`);
|
|
7610
7973
|
}
|
|
7611
7974
|
cleanupStaging();
|
|
7612
7975
|
return;
|
|
@@ -7625,28 +7988,28 @@ async function regenerateCommand(options) {
|
|
|
7625
7988
|
});
|
|
7626
7989
|
cleanupStaging();
|
|
7627
7990
|
if (action === "decline") {
|
|
7628
|
-
console.log(
|
|
7991
|
+
console.log(chalk14.dim("Regeneration cancelled. No files were modified."));
|
|
7629
7992
|
return;
|
|
7630
7993
|
}
|
|
7631
|
-
const writeSpinner =
|
|
7994
|
+
const writeSpinner = ora5("Writing config files...").start();
|
|
7632
7995
|
try {
|
|
7633
7996
|
const result = writeSetup(generatedSetup);
|
|
7634
7997
|
writeSpinner.succeed("Config files written");
|
|
7635
7998
|
for (const file of result.written) {
|
|
7636
|
-
console.log(` ${
|
|
7999
|
+
console.log(` ${chalk14.green("\u2713")} ${file}`);
|
|
7637
8000
|
}
|
|
7638
8001
|
if (result.deleted.length > 0) {
|
|
7639
8002
|
for (const file of result.deleted) {
|
|
7640
|
-
console.log(` ${
|
|
8003
|
+
console.log(` ${chalk14.red("\u2717")} ${file}`);
|
|
7641
8004
|
}
|
|
7642
8005
|
}
|
|
7643
8006
|
if (result.backupDir) {
|
|
7644
|
-
console.log(
|
|
8007
|
+
console.log(chalk14.dim(`
|
|
7645
8008
|
Backups saved to ${result.backupDir}`));
|
|
7646
8009
|
}
|
|
7647
8010
|
} catch (err) {
|
|
7648
8011
|
writeSpinner.fail("Failed to write files");
|
|
7649
|
-
console.error(
|
|
8012
|
+
console.error(chalk14.red(err instanceof Error ? err.message : "Unknown error"));
|
|
7650
8013
|
throw new Error("__exit__");
|
|
7651
8014
|
}
|
|
7652
8015
|
const sha = getCurrentHeadSha();
|
|
@@ -7658,25 +8021,25 @@ async function regenerateCommand(options) {
|
|
|
7658
8021
|
const afterScore = computeLocalScore(process.cwd(), targetAgent);
|
|
7659
8022
|
if (afterScore.score < baselineScore.score) {
|
|
7660
8023
|
console.log("");
|
|
7661
|
-
console.log(
|
|
8024
|
+
console.log(chalk14.yellow(` Score would drop from ${baselineScore.score} to ${afterScore.score} \u2014 reverting changes.`));
|
|
7662
8025
|
try {
|
|
7663
8026
|
const { restored, removed } = undoSetup();
|
|
7664
8027
|
if (restored.length > 0 || removed.length > 0) {
|
|
7665
|
-
console.log(
|
|
8028
|
+
console.log(chalk14.dim(` Reverted ${restored.length + removed.length} file${restored.length + removed.length === 1 ? "" : "s"} from backup.`));
|
|
7666
8029
|
}
|
|
7667
8030
|
} catch {
|
|
7668
8031
|
}
|
|
7669
|
-
console.log(
|
|
8032
|
+
console.log(chalk14.dim(" Run ") + chalk14.hex("#83D1EB")("caliber init --force") + chalk14.dim(" to override.\n"));
|
|
7670
8033
|
return;
|
|
7671
8034
|
}
|
|
7672
8035
|
displayScoreDelta(baselineScore, afterScore);
|
|
7673
8036
|
trackRegenerateCompleted(action, Date.now());
|
|
7674
|
-
console.log(
|
|
7675
|
-
console.log(
|
|
8037
|
+
console.log(chalk14.bold.green(" Regeneration complete!"));
|
|
8038
|
+
console.log(chalk14.dim(" Run ") + chalk14.hex("#83D1EB")("caliber undo") + chalk14.dim(" to revert changes.\n"));
|
|
7676
8039
|
}
|
|
7677
8040
|
|
|
7678
8041
|
// src/commands/score.ts
|
|
7679
|
-
import
|
|
8042
|
+
import chalk15 from "chalk";
|
|
7680
8043
|
async function scoreCommand(options) {
|
|
7681
8044
|
const dir = process.cwd();
|
|
7682
8045
|
const target = options.agent ?? readState()?.targetAgent;
|
|
@@ -7691,14 +8054,14 @@ async function scoreCommand(options) {
|
|
|
7691
8054
|
return;
|
|
7692
8055
|
}
|
|
7693
8056
|
displayScore(result);
|
|
7694
|
-
const separator =
|
|
8057
|
+
const separator = chalk15.gray(" " + "\u2500".repeat(53));
|
|
7695
8058
|
console.log(separator);
|
|
7696
8059
|
if (result.score < 40) {
|
|
7697
|
-
console.log(
|
|
8060
|
+
console.log(chalk15.gray(" Run ") + chalk15.hex("#83D1EB")("caliber init") + chalk15.gray(" to generate a complete, optimized setup."));
|
|
7698
8061
|
} else if (result.score < 70) {
|
|
7699
|
-
console.log(
|
|
8062
|
+
console.log(chalk15.gray(" Run ") + chalk15.hex("#83D1EB")("caliber init") + chalk15.gray(" to improve your setup."));
|
|
7700
8063
|
} else {
|
|
7701
|
-
console.log(
|
|
8064
|
+
console.log(chalk15.green(" Looking good!") + chalk15.gray(" Run ") + chalk15.hex("#83D1EB")("caliber regenerate") + chalk15.gray(" to rebuild from scratch."));
|
|
7702
8065
|
}
|
|
7703
8066
|
console.log("");
|
|
7704
8067
|
}
|
|
@@ -7706,8 +8069,8 @@ async function scoreCommand(options) {
|
|
|
7706
8069
|
// src/commands/refresh.ts
|
|
7707
8070
|
import fs30 from "fs";
|
|
7708
8071
|
import path24 from "path";
|
|
7709
|
-
import
|
|
7710
|
-
import
|
|
8072
|
+
import chalk16 from "chalk";
|
|
8073
|
+
import ora6 from "ora";
|
|
7711
8074
|
|
|
7712
8075
|
// src/lib/git-diff.ts
|
|
7713
8076
|
import { execSync as execSync13 } from "child_process";
|
|
@@ -8049,7 +8412,7 @@ function discoverGitRepos(parentDir) {
|
|
|
8049
8412
|
}
|
|
8050
8413
|
async function refreshSingleRepo(repoDir, options) {
|
|
8051
8414
|
const quiet = !!options.quiet;
|
|
8052
|
-
const prefix = options.label ? `${
|
|
8415
|
+
const prefix = options.label ? `${chalk16.bold(options.label)} ` : "";
|
|
8053
8416
|
const state = readState();
|
|
8054
8417
|
const lastSha = state?.lastRefreshSha ?? null;
|
|
8055
8418
|
const diff = collectDiff(lastSha);
|
|
@@ -8058,10 +8421,10 @@ async function refreshSingleRepo(repoDir, options) {
|
|
|
8058
8421
|
if (currentSha) {
|
|
8059
8422
|
writeState({ lastRefreshSha: currentSha, lastRefreshTimestamp: (/* @__PURE__ */ new Date()).toISOString() });
|
|
8060
8423
|
}
|
|
8061
|
-
log2(quiet,
|
|
8424
|
+
log2(quiet, chalk16.dim(`${prefix}No changes since last refresh.`));
|
|
8062
8425
|
return;
|
|
8063
8426
|
}
|
|
8064
|
-
const spinner = quiet ? null :
|
|
8427
|
+
const spinner = quiet ? null : ora6(`${prefix}Analyzing changes...`).start();
|
|
8065
8428
|
const existingDocs = readExistingConfigs(repoDir);
|
|
8066
8429
|
const learnedSection = readLearnedSection();
|
|
8067
8430
|
const fingerprint = await collectFingerprint(repoDir);
|
|
@@ -8092,10 +8455,10 @@ async function refreshSingleRepo(repoDir, options) {
|
|
|
8092
8455
|
if (options.dryRun) {
|
|
8093
8456
|
spinner?.info(`${prefix}Dry run \u2014 would update:`);
|
|
8094
8457
|
for (const doc of response.docsUpdated) {
|
|
8095
|
-
console.log(` ${
|
|
8458
|
+
console.log(` ${chalk16.yellow("~")} ${doc}`);
|
|
8096
8459
|
}
|
|
8097
8460
|
if (response.changesSummary) {
|
|
8098
|
-
console.log(
|
|
8461
|
+
console.log(chalk16.dim(`
|
|
8099
8462
|
${response.changesSummary}`));
|
|
8100
8463
|
}
|
|
8101
8464
|
return;
|
|
@@ -8104,10 +8467,10 @@ async function refreshSingleRepo(repoDir, options) {
|
|
|
8104
8467
|
trackRefreshCompleted(written.length, Date.now());
|
|
8105
8468
|
spinner?.succeed(`${prefix}Updated ${written.length} doc${written.length === 1 ? "" : "s"}`);
|
|
8106
8469
|
for (const file of written) {
|
|
8107
|
-
log2(quiet, ` ${
|
|
8470
|
+
log2(quiet, ` ${chalk16.green("\u2713")} ${file}`);
|
|
8108
8471
|
}
|
|
8109
8472
|
if (response.changesSummary) {
|
|
8110
|
-
log2(quiet,
|
|
8473
|
+
log2(quiet, chalk16.dim(`
|
|
8111
8474
|
${response.changesSummary}`));
|
|
8112
8475
|
}
|
|
8113
8476
|
if (currentSha) {
|
|
@@ -8124,7 +8487,7 @@ async function refreshCommand(options) {
|
|
|
8124
8487
|
const config = loadConfig();
|
|
8125
8488
|
if (!config) {
|
|
8126
8489
|
if (quiet) return;
|
|
8127
|
-
console.log(
|
|
8490
|
+
console.log(chalk16.red("No LLM provider configured. Run ") + chalk16.hex("#83D1EB")("caliber config") + chalk16.red(" (e.g. choose Cursor) or set an API key."));
|
|
8128
8491
|
throw new Error("__exit__");
|
|
8129
8492
|
}
|
|
8130
8493
|
await validateModel({ fast: true });
|
|
@@ -8135,10 +8498,10 @@ async function refreshCommand(options) {
|
|
|
8135
8498
|
const repos = discoverGitRepos(process.cwd());
|
|
8136
8499
|
if (repos.length === 0) {
|
|
8137
8500
|
if (quiet) return;
|
|
8138
|
-
console.log(
|
|
8501
|
+
console.log(chalk16.red("Not inside a git repository and no git repos found in child directories."));
|
|
8139
8502
|
throw new Error("__exit__");
|
|
8140
8503
|
}
|
|
8141
|
-
log2(quiet,
|
|
8504
|
+
log2(quiet, chalk16.dim(`Found ${repos.length} git repo${repos.length === 1 ? "" : "s"}
|
|
8142
8505
|
`));
|
|
8143
8506
|
const originalDir = process.cwd();
|
|
8144
8507
|
for (const repo of repos) {
|
|
@@ -8148,7 +8511,7 @@ async function refreshCommand(options) {
|
|
|
8148
8511
|
await refreshSingleRepo(repo, { ...options, label: repoName });
|
|
8149
8512
|
} catch (err) {
|
|
8150
8513
|
if (err instanceof Error && err.message === "__exit__") continue;
|
|
8151
|
-
log2(quiet,
|
|
8514
|
+
log2(quiet, chalk16.yellow(`${repoName}: refresh failed \u2014 ${err instanceof Error ? err.message : "unknown error"}`));
|
|
8152
8515
|
}
|
|
8153
8516
|
}
|
|
8154
8517
|
process.chdir(originalDir);
|
|
@@ -8156,13 +8519,13 @@ async function refreshCommand(options) {
|
|
|
8156
8519
|
if (err instanceof Error && err.message === "__exit__") throw err;
|
|
8157
8520
|
if (quiet) return;
|
|
8158
8521
|
const msg = err instanceof Error ? err.message : "Unknown error";
|
|
8159
|
-
console.log(
|
|
8522
|
+
console.log(chalk16.red(`Refresh failed: ${msg}`));
|
|
8160
8523
|
throw new Error("__exit__");
|
|
8161
8524
|
}
|
|
8162
8525
|
}
|
|
8163
8526
|
|
|
8164
8527
|
// src/commands/hooks.ts
|
|
8165
|
-
import
|
|
8528
|
+
import chalk17 from "chalk";
|
|
8166
8529
|
var HOOKS = [
|
|
8167
8530
|
{
|
|
8168
8531
|
id: "session-end",
|
|
@@ -8182,13 +8545,13 @@ var HOOKS = [
|
|
|
8182
8545
|
}
|
|
8183
8546
|
];
|
|
8184
8547
|
function printStatus() {
|
|
8185
|
-
console.log(
|
|
8548
|
+
console.log(chalk17.bold("\n Hooks\n"));
|
|
8186
8549
|
for (const hook of HOOKS) {
|
|
8187
8550
|
const installed = hook.isInstalled();
|
|
8188
|
-
const icon = installed ?
|
|
8189
|
-
const state = installed ?
|
|
8551
|
+
const icon = installed ? chalk17.green("\u2713") : chalk17.dim("\u2717");
|
|
8552
|
+
const state = installed ? chalk17.green("enabled") : chalk17.dim("disabled");
|
|
8190
8553
|
console.log(` ${icon} ${hook.label.padEnd(26)} ${state}`);
|
|
8191
|
-
console.log(
|
|
8554
|
+
console.log(chalk17.dim(` ${hook.description}`));
|
|
8192
8555
|
}
|
|
8193
8556
|
console.log("");
|
|
8194
8557
|
}
|
|
@@ -8197,9 +8560,9 @@ async function hooksCommand(options) {
|
|
|
8197
8560
|
for (const hook of HOOKS) {
|
|
8198
8561
|
const result = hook.install();
|
|
8199
8562
|
if (result.alreadyInstalled) {
|
|
8200
|
-
console.log(
|
|
8563
|
+
console.log(chalk17.dim(` ${hook.label} already enabled.`));
|
|
8201
8564
|
} else {
|
|
8202
|
-
console.log(
|
|
8565
|
+
console.log(chalk17.green(" \u2713") + ` ${hook.label} enabled`);
|
|
8203
8566
|
}
|
|
8204
8567
|
}
|
|
8205
8568
|
return;
|
|
@@ -8208,9 +8571,9 @@ async function hooksCommand(options) {
|
|
|
8208
8571
|
for (const hook of HOOKS) {
|
|
8209
8572
|
const result = hook.remove();
|
|
8210
8573
|
if (result.notFound) {
|
|
8211
|
-
console.log(
|
|
8574
|
+
console.log(chalk17.dim(` ${hook.label} already disabled.`));
|
|
8212
8575
|
} else {
|
|
8213
|
-
console.log(
|
|
8576
|
+
console.log(chalk17.green(" \u2713") + ` ${hook.label} removed`);
|
|
8214
8577
|
}
|
|
8215
8578
|
}
|
|
8216
8579
|
return;
|
|
@@ -8225,18 +8588,18 @@ async function hooksCommand(options) {
|
|
|
8225
8588
|
const states = HOOKS.map((h) => h.isInstalled());
|
|
8226
8589
|
function render() {
|
|
8227
8590
|
const lines = [];
|
|
8228
|
-
lines.push(
|
|
8591
|
+
lines.push(chalk17.bold(" Hooks"));
|
|
8229
8592
|
lines.push("");
|
|
8230
8593
|
for (let i = 0; i < HOOKS.length; i++) {
|
|
8231
8594
|
const hook = HOOKS[i];
|
|
8232
8595
|
const enabled = states[i];
|
|
8233
|
-
const toggle = enabled ?
|
|
8234
|
-
const ptr = i === cursor ?
|
|
8596
|
+
const toggle = enabled ? chalk17.green("[on] ") : chalk17.dim("[off]");
|
|
8597
|
+
const ptr = i === cursor ? chalk17.cyan(">") : " ";
|
|
8235
8598
|
lines.push(` ${ptr} ${toggle} ${hook.label}`);
|
|
8236
|
-
lines.push(
|
|
8599
|
+
lines.push(chalk17.dim(` ${hook.description}`));
|
|
8237
8600
|
}
|
|
8238
8601
|
lines.push("");
|
|
8239
|
-
lines.push(
|
|
8602
|
+
lines.push(chalk17.dim(" \u2191\u2193 navigate \u23B5 toggle a all on n all off \u23CE apply q cancel"));
|
|
8240
8603
|
return lines.join("\n");
|
|
8241
8604
|
}
|
|
8242
8605
|
function draw(initial) {
|
|
@@ -8267,16 +8630,16 @@ async function hooksCommand(options) {
|
|
|
8267
8630
|
const wantEnabled = states[i];
|
|
8268
8631
|
if (wantEnabled && !wasInstalled) {
|
|
8269
8632
|
hook.install();
|
|
8270
|
-
console.log(
|
|
8633
|
+
console.log(chalk17.green(" \u2713") + ` ${hook.label} enabled`);
|
|
8271
8634
|
changed++;
|
|
8272
8635
|
} else if (!wantEnabled && wasInstalled) {
|
|
8273
8636
|
hook.remove();
|
|
8274
|
-
console.log(
|
|
8637
|
+
console.log(chalk17.green(" \u2713") + ` ${hook.label} disabled`);
|
|
8275
8638
|
changed++;
|
|
8276
8639
|
}
|
|
8277
8640
|
}
|
|
8278
8641
|
if (changed === 0) {
|
|
8279
|
-
console.log(
|
|
8642
|
+
console.log(chalk17.dim(" No changes."));
|
|
8280
8643
|
}
|
|
8281
8644
|
console.log("");
|
|
8282
8645
|
}
|
|
@@ -8312,7 +8675,7 @@ async function hooksCommand(options) {
|
|
|
8312
8675
|
case "\x1B":
|
|
8313
8676
|
case "":
|
|
8314
8677
|
cleanup();
|
|
8315
|
-
console.log(
|
|
8678
|
+
console.log(chalk17.dim("\n Cancelled.\n"));
|
|
8316
8679
|
resolve2();
|
|
8317
8680
|
break;
|
|
8318
8681
|
}
|
|
@@ -8323,51 +8686,51 @@ async function hooksCommand(options) {
|
|
|
8323
8686
|
|
|
8324
8687
|
// src/commands/config.ts
|
|
8325
8688
|
init_config();
|
|
8326
|
-
import
|
|
8689
|
+
import chalk18 from "chalk";
|
|
8327
8690
|
async function configCommand() {
|
|
8328
8691
|
const existing = loadConfig();
|
|
8329
8692
|
if (existing) {
|
|
8330
8693
|
const displayModel = getDisplayModel(existing);
|
|
8331
8694
|
const fastModel = getFastModel();
|
|
8332
|
-
console.log(
|
|
8333
|
-
console.log(` Provider: ${
|
|
8334
|
-
console.log(` Model: ${
|
|
8695
|
+
console.log(chalk18.bold("\nCurrent Configuration\n"));
|
|
8696
|
+
console.log(` Provider: ${chalk18.cyan(existing.provider)}`);
|
|
8697
|
+
console.log(` Model: ${chalk18.cyan(displayModel)}`);
|
|
8335
8698
|
if (fastModel) {
|
|
8336
|
-
console.log(` Scan: ${
|
|
8699
|
+
console.log(` Scan: ${chalk18.cyan(fastModel)}`);
|
|
8337
8700
|
}
|
|
8338
8701
|
if (existing.apiKey) {
|
|
8339
8702
|
const masked = existing.apiKey.slice(0, 8) + "..." + existing.apiKey.slice(-4);
|
|
8340
|
-
console.log(` API Key: ${
|
|
8703
|
+
console.log(` API Key: ${chalk18.dim(masked)}`);
|
|
8341
8704
|
}
|
|
8342
8705
|
if (existing.provider === "cursor") {
|
|
8343
|
-
console.log(` Seat: ${
|
|
8706
|
+
console.log(` Seat: ${chalk18.dim("Cursor (agent acp)")}`);
|
|
8344
8707
|
}
|
|
8345
8708
|
if (existing.provider === "claude-cli") {
|
|
8346
|
-
console.log(` Seat: ${
|
|
8709
|
+
console.log(` Seat: ${chalk18.dim("Claude Code (claude -p)")}`);
|
|
8347
8710
|
}
|
|
8348
8711
|
if (existing.baseUrl) {
|
|
8349
|
-
console.log(` Base URL: ${
|
|
8712
|
+
console.log(` Base URL: ${chalk18.dim(existing.baseUrl)}`);
|
|
8350
8713
|
}
|
|
8351
8714
|
if (existing.vertexProjectId) {
|
|
8352
|
-
console.log(` Vertex Project: ${
|
|
8353
|
-
console.log(` Vertex Region: ${
|
|
8715
|
+
console.log(` Vertex Project: ${chalk18.dim(existing.vertexProjectId)}`);
|
|
8716
|
+
console.log(` Vertex Region: ${chalk18.dim(existing.vertexRegion || "us-east5")}`);
|
|
8354
8717
|
}
|
|
8355
|
-
console.log(` Source: ${
|
|
8718
|
+
console.log(` Source: ${chalk18.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())}`);
|
|
8356
8719
|
console.log("");
|
|
8357
8720
|
}
|
|
8358
8721
|
await runInteractiveProviderSetup();
|
|
8359
8722
|
const updated = loadConfig();
|
|
8360
8723
|
if (updated) trackConfigProviderSet(updated.provider);
|
|
8361
|
-
console.log(
|
|
8362
|
-
console.log(
|
|
8724
|
+
console.log(chalk18.green("\n\u2713 Configuration saved"));
|
|
8725
|
+
console.log(chalk18.dim(` ${getConfigFilePath()}
|
|
8363
8726
|
`));
|
|
8364
|
-
console.log(
|
|
8365
|
-
console.log(
|
|
8727
|
+
console.log(chalk18.dim(" You can also set environment variables instead:"));
|
|
8728
|
+
console.log(chalk18.dim(" ANTHROPIC_API_KEY, OPENAI_API_KEY, VERTEX_PROJECT_ID, CALIBER_USE_CURSOR_SEAT=1, or CALIBER_USE_CLAUDE_CLI=1\n"));
|
|
8366
8729
|
}
|
|
8367
8730
|
|
|
8368
8731
|
// src/commands/learn.ts
|
|
8369
8732
|
import fs33 from "fs";
|
|
8370
|
-
import
|
|
8733
|
+
import chalk19 from "chalk";
|
|
8371
8734
|
|
|
8372
8735
|
// src/learner/stdin.ts
|
|
8373
8736
|
var STDIN_TIMEOUT_MS = 5e3;
|
|
@@ -8798,26 +9161,26 @@ async function learnFinalizeCommand(options) {
|
|
|
8798
9161
|
if (!options?.force) {
|
|
8799
9162
|
const { isCaliberRunning: isCaliberRunning2 } = await Promise.resolve().then(() => (init_lock(), lock_exports));
|
|
8800
9163
|
if (isCaliberRunning2()) {
|
|
8801
|
-
console.log(
|
|
9164
|
+
console.log(chalk19.dim("caliber: skipping finalize \u2014 another caliber process is running"));
|
|
8802
9165
|
return;
|
|
8803
9166
|
}
|
|
8804
9167
|
}
|
|
8805
9168
|
if (!acquireFinalizeLock()) {
|
|
8806
|
-
console.log(
|
|
9169
|
+
console.log(chalk19.dim("caliber: skipping finalize \u2014 another finalize is in progress"));
|
|
8807
9170
|
return;
|
|
8808
9171
|
}
|
|
8809
9172
|
let analyzed = false;
|
|
8810
9173
|
try {
|
|
8811
9174
|
const config = loadConfig();
|
|
8812
9175
|
if (!config) {
|
|
8813
|
-
console.log(
|
|
9176
|
+
console.log(chalk19.yellow("caliber: no LLM provider configured \u2014 run `caliber config` first"));
|
|
8814
9177
|
clearSession();
|
|
8815
9178
|
resetState();
|
|
8816
9179
|
return;
|
|
8817
9180
|
}
|
|
8818
9181
|
const events = readAllEvents();
|
|
8819
9182
|
if (events.length < MIN_EVENTS_FOR_ANALYSIS) {
|
|
8820
|
-
console.log(
|
|
9183
|
+
console.log(chalk19.dim(`caliber: ${events.length}/${MIN_EVENTS_FOR_ANALYSIS} events recorded \u2014 need more before analysis`));
|
|
8821
9184
|
return;
|
|
8822
9185
|
}
|
|
8823
9186
|
await validateModel({ fast: true });
|
|
@@ -8845,9 +9208,9 @@ async function learnFinalizeCommand(options) {
|
|
|
8845
9208
|
newLearningsProduced = result.newItemCount;
|
|
8846
9209
|
if (result.newItemCount > 0) {
|
|
8847
9210
|
const wasteLabel = waste.totalWasteTokens > 0 ? ` (~${waste.totalWasteTokens.toLocaleString()} wasted tokens captured)` : "";
|
|
8848
|
-
console.log(
|
|
9211
|
+
console.log(chalk19.dim(`caliber: learned ${result.newItemCount} new pattern${result.newItemCount === 1 ? "" : "s"}${wasteLabel}`));
|
|
8849
9212
|
for (const item of result.newItems) {
|
|
8850
|
-
console.log(
|
|
9213
|
+
console.log(chalk19.dim(` + ${item.replace(/^- /, "").slice(0, 80)}`));
|
|
8851
9214
|
}
|
|
8852
9215
|
const wastePerLearning = Math.round(waste.totalWasteTokens / result.newItemCount);
|
|
8853
9216
|
const TYPE_RE = /^\*\*\[([^\]]+)\]\*\*/;
|
|
@@ -8906,11 +9269,11 @@ async function learnFinalizeCommand(options) {
|
|
|
8906
9269
|
});
|
|
8907
9270
|
if (t.estimatedSavingsTokens > 0) {
|
|
8908
9271
|
const totalLearnings = existingLearnedItems + newLearningsProduced;
|
|
8909
|
-
console.log(
|
|
9272
|
+
console.log(chalk19.dim(`caliber: ${totalLearnings} learnings active \u2014 est. ~${t.estimatedSavingsTokens.toLocaleString()} tokens saved across ${t.totalSessionsWithLearnings} sessions`));
|
|
8910
9273
|
}
|
|
8911
9274
|
} catch (err) {
|
|
8912
9275
|
if (options?.force) {
|
|
8913
|
-
console.error(
|
|
9276
|
+
console.error(chalk19.red("caliber: finalize failed \u2014"), err instanceof Error ? err.message : err);
|
|
8914
9277
|
}
|
|
8915
9278
|
} finally {
|
|
8916
9279
|
if (analyzed) {
|
|
@@ -8925,45 +9288,45 @@ async function learnInstallCommand() {
|
|
|
8925
9288
|
if (fs33.existsSync(".claude")) {
|
|
8926
9289
|
const r = installLearningHooks();
|
|
8927
9290
|
if (r.installed) {
|
|
8928
|
-
console.log(
|
|
9291
|
+
console.log(chalk19.green("\u2713") + " Claude Code learning hooks installed");
|
|
8929
9292
|
anyInstalled = true;
|
|
8930
9293
|
} else if (r.alreadyInstalled) {
|
|
8931
|
-
console.log(
|
|
9294
|
+
console.log(chalk19.dim(" Claude Code hooks already installed"));
|
|
8932
9295
|
}
|
|
8933
9296
|
}
|
|
8934
9297
|
if (fs33.existsSync(".cursor")) {
|
|
8935
9298
|
const r = installCursorLearningHooks();
|
|
8936
9299
|
if (r.installed) {
|
|
8937
|
-
console.log(
|
|
9300
|
+
console.log(chalk19.green("\u2713") + " Cursor learning hooks installed");
|
|
8938
9301
|
anyInstalled = true;
|
|
8939
9302
|
} else if (r.alreadyInstalled) {
|
|
8940
|
-
console.log(
|
|
9303
|
+
console.log(chalk19.dim(" Cursor hooks already installed"));
|
|
8941
9304
|
}
|
|
8942
9305
|
}
|
|
8943
9306
|
if (!fs33.existsSync(".claude") && !fs33.existsSync(".cursor")) {
|
|
8944
|
-
console.log(
|
|
8945
|
-
console.log(
|
|
9307
|
+
console.log(chalk19.yellow("No .claude/ or .cursor/ directory found."));
|
|
9308
|
+
console.log(chalk19.dim(" Run `caliber init` first, or create the directory manually."));
|
|
8946
9309
|
return;
|
|
8947
9310
|
}
|
|
8948
9311
|
if (anyInstalled) {
|
|
8949
|
-
console.log(
|
|
8950
|
-
console.log(
|
|
9312
|
+
console.log(chalk19.dim(` Tool usage will be recorded and learnings extracted after \u2265${MIN_EVENTS_FOR_ANALYSIS} events.`));
|
|
9313
|
+
console.log(chalk19.dim(" Learnings written to CALIBER_LEARNINGS.md."));
|
|
8951
9314
|
}
|
|
8952
9315
|
}
|
|
8953
9316
|
async function learnRemoveCommand() {
|
|
8954
9317
|
let anyRemoved = false;
|
|
8955
9318
|
const r1 = removeLearningHooks();
|
|
8956
9319
|
if (r1.removed) {
|
|
8957
|
-
console.log(
|
|
9320
|
+
console.log(chalk19.green("\u2713") + " Claude Code learning hooks removed");
|
|
8958
9321
|
anyRemoved = true;
|
|
8959
9322
|
}
|
|
8960
9323
|
const r2 = removeCursorLearningHooks();
|
|
8961
9324
|
if (r2.removed) {
|
|
8962
|
-
console.log(
|
|
9325
|
+
console.log(chalk19.green("\u2713") + " Cursor learning hooks removed");
|
|
8963
9326
|
anyRemoved = true;
|
|
8964
9327
|
}
|
|
8965
9328
|
if (!anyRemoved) {
|
|
8966
|
-
console.log(
|
|
9329
|
+
console.log(chalk19.dim("No learning hooks found."));
|
|
8967
9330
|
}
|
|
8968
9331
|
}
|
|
8969
9332
|
async function learnStatusCommand() {
|
|
@@ -8971,40 +9334,40 @@ async function learnStatusCommand() {
|
|
|
8971
9334
|
const cursorInstalled = areCursorLearningHooksInstalled();
|
|
8972
9335
|
const state = readState2();
|
|
8973
9336
|
const eventCount = getEventCount();
|
|
8974
|
-
console.log(
|
|
9337
|
+
console.log(chalk19.bold("Session Learning Status"));
|
|
8975
9338
|
console.log();
|
|
8976
9339
|
if (claudeInstalled) {
|
|
8977
|
-
console.log(
|
|
9340
|
+
console.log(chalk19.green("\u2713") + " Claude Code hooks " + chalk19.green("installed"));
|
|
8978
9341
|
} else {
|
|
8979
|
-
console.log(
|
|
9342
|
+
console.log(chalk19.dim("\u2717") + " Claude Code hooks " + chalk19.dim("not installed"));
|
|
8980
9343
|
}
|
|
8981
9344
|
if (cursorInstalled) {
|
|
8982
|
-
console.log(
|
|
9345
|
+
console.log(chalk19.green("\u2713") + " Cursor hooks " + chalk19.green("installed"));
|
|
8983
9346
|
} else {
|
|
8984
|
-
console.log(
|
|
9347
|
+
console.log(chalk19.dim("\u2717") + " Cursor hooks " + chalk19.dim("not installed"));
|
|
8985
9348
|
}
|
|
8986
9349
|
if (!claudeInstalled && !cursorInstalled) {
|
|
8987
|
-
console.log(
|
|
9350
|
+
console.log(chalk19.dim(" Run `caliber learn install` to enable session learning."));
|
|
8988
9351
|
}
|
|
8989
9352
|
console.log();
|
|
8990
|
-
console.log(`Events recorded: ${
|
|
8991
|
-
console.log(`Threshold for analysis: ${
|
|
9353
|
+
console.log(`Events recorded: ${chalk19.cyan(String(eventCount))}`);
|
|
9354
|
+
console.log(`Threshold for analysis: ${chalk19.cyan(String(MIN_EVENTS_FOR_ANALYSIS))}`);
|
|
8992
9355
|
if (state.lastAnalysisTimestamp) {
|
|
8993
|
-
console.log(`Last analysis: ${
|
|
9356
|
+
console.log(`Last analysis: ${chalk19.cyan(state.lastAnalysisTimestamp)}`);
|
|
8994
9357
|
} else {
|
|
8995
|
-
console.log(`Last analysis: ${
|
|
9358
|
+
console.log(`Last analysis: ${chalk19.dim("none")}`);
|
|
8996
9359
|
}
|
|
8997
9360
|
const learnedSection = readLearnedSection();
|
|
8998
9361
|
if (learnedSection) {
|
|
8999
9362
|
const lineCount = learnedSection.split("\n").filter(Boolean).length;
|
|
9000
9363
|
console.log(`
|
|
9001
|
-
Learned items in CALIBER_LEARNINGS.md: ${
|
|
9364
|
+
Learned items in CALIBER_LEARNINGS.md: ${chalk19.cyan(String(lineCount))}`);
|
|
9002
9365
|
}
|
|
9003
9366
|
const roiStats = readROIStats();
|
|
9004
9367
|
const roiSummary = formatROISummary(roiStats);
|
|
9005
9368
|
if (roiSummary) {
|
|
9006
9369
|
console.log();
|
|
9007
|
-
console.log(
|
|
9370
|
+
console.log(chalk19.bold(roiSummary.split("\n")[0]));
|
|
9008
9371
|
for (const line of roiSummary.split("\n").slice(1)) {
|
|
9009
9372
|
console.log(line);
|
|
9010
9373
|
}
|
|
@@ -9092,8 +9455,8 @@ import fs35 from "fs";
|
|
|
9092
9455
|
import path28 from "path";
|
|
9093
9456
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
9094
9457
|
import { execSync as execSync14 } from "child_process";
|
|
9095
|
-
import
|
|
9096
|
-
import
|
|
9458
|
+
import chalk20 from "chalk";
|
|
9459
|
+
import ora7 from "ora";
|
|
9097
9460
|
import confirm2 from "@inquirer/confirm";
|
|
9098
9461
|
var __dirname_vc = path28.dirname(fileURLToPath2(import.meta.url));
|
|
9099
9462
|
var pkg2 = JSON.parse(
|
|
@@ -9148,17 +9511,17 @@ async function checkForUpdates() {
|
|
|
9148
9511
|
if (!isInteractive) {
|
|
9149
9512
|
const installTag = channel === "latest" ? "" : `@${channel}`;
|
|
9150
9513
|
console.log(
|
|
9151
|
-
|
|
9514
|
+
chalk20.yellow(
|
|
9152
9515
|
`
|
|
9153
9516
|
Update available: ${current} -> ${latest}
|
|
9154
|
-
Run ${
|
|
9517
|
+
Run ${chalk20.bold(`npm install -g @rely-ai/caliber${installTag}`)} to upgrade.
|
|
9155
9518
|
`
|
|
9156
9519
|
)
|
|
9157
9520
|
);
|
|
9158
9521
|
return;
|
|
9159
9522
|
}
|
|
9160
9523
|
console.log(
|
|
9161
|
-
|
|
9524
|
+
chalk20.yellow(`
|
|
9162
9525
|
Update available: ${current} -> ${latest}`)
|
|
9163
9526
|
);
|
|
9164
9527
|
const shouldUpdate = await confirm2({ message: "Would you like to update now? (Y/n)", default: true });
|
|
@@ -9167,7 +9530,7 @@ Update available: ${current} -> ${latest}`)
|
|
|
9167
9530
|
return;
|
|
9168
9531
|
}
|
|
9169
9532
|
const tag = channel === "latest" ? latest : channel;
|
|
9170
|
-
const spinner =
|
|
9533
|
+
const spinner = ora7("Updating caliber...").start();
|
|
9171
9534
|
try {
|
|
9172
9535
|
execSync14(`npm install -g @rely-ai/caliber@${tag}`, {
|
|
9173
9536
|
stdio: "pipe",
|
|
@@ -9177,13 +9540,13 @@ Update available: ${current} -> ${latest}`)
|
|
|
9177
9540
|
const installed = getInstalledVersion();
|
|
9178
9541
|
if (installed !== latest) {
|
|
9179
9542
|
spinner.fail(`Update incomplete \u2014 got ${installed ?? "unknown"}, expected ${latest}`);
|
|
9180
|
-
console.log(
|
|
9543
|
+
console.log(chalk20.yellow(`Run ${chalk20.bold(`npm install -g @rely-ai/caliber@${tag}`)} manually.
|
|
9181
9544
|
`));
|
|
9182
9545
|
return;
|
|
9183
9546
|
}
|
|
9184
|
-
spinner.succeed(
|
|
9547
|
+
spinner.succeed(chalk20.green(`Updated to ${latest}`));
|
|
9185
9548
|
const args = process.argv.slice(2);
|
|
9186
|
-
console.log(
|
|
9549
|
+
console.log(chalk20.dim(`
|
|
9187
9550
|
Restarting: caliber ${args.join(" ")}
|
|
9188
9551
|
`));
|
|
9189
9552
|
execSync14(`caliber ${args.map((a) => JSON.stringify(a)).join(" ")}`, {
|
|
@@ -9196,11 +9559,11 @@ Restarting: caliber ${args.join(" ")}
|
|
|
9196
9559
|
if (err instanceof Error) {
|
|
9197
9560
|
const stderr = err.stderr;
|
|
9198
9561
|
const errMsg = stderr ? String(stderr).trim().split("\n").pop() : err.message.split("\n")[0];
|
|
9199
|
-
if (errMsg && !errMsg.includes("SIGTERM")) console.log(
|
|
9562
|
+
if (errMsg && !errMsg.includes("SIGTERM")) console.log(chalk20.dim(` ${errMsg}`));
|
|
9200
9563
|
}
|
|
9201
9564
|
console.log(
|
|
9202
|
-
|
|
9203
|
-
`Run ${
|
|
9565
|
+
chalk20.yellow(
|
|
9566
|
+
`Run ${chalk20.bold(`npm install -g @rely-ai/caliber@${tag}`)} manually to upgrade.
|
|
9204
9567
|
`
|
|
9205
9568
|
)
|
|
9206
9569
|
);
|