@rely-ai/caliber 1.7.0 → 1.7.2
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 +578 -342
- package/package.json +3 -2
package/dist/bin.js
CHANGED
|
@@ -165,17 +165,17 @@ var init_constants = __esm({
|
|
|
165
165
|
|
|
166
166
|
// src/cli.ts
|
|
167
167
|
import { Command } from "commander";
|
|
168
|
-
import
|
|
169
|
-
import
|
|
168
|
+
import fs28 from "fs";
|
|
169
|
+
import path22 from "path";
|
|
170
170
|
import { fileURLToPath } from "url";
|
|
171
171
|
|
|
172
172
|
// src/commands/onboard.ts
|
|
173
|
-
import
|
|
173
|
+
import chalk8 from "chalk";
|
|
174
174
|
import ora2 from "ora";
|
|
175
175
|
import readline3 from "readline";
|
|
176
176
|
import select5 from "@inquirer/select";
|
|
177
177
|
import checkbox from "@inquirer/checkbox";
|
|
178
|
-
import
|
|
178
|
+
import fs22 from "fs";
|
|
179
179
|
|
|
180
180
|
// src/fingerprint/index.ts
|
|
181
181
|
import fs6 from "fs";
|
|
@@ -3205,15 +3205,15 @@ function computeGrade(score) {
|
|
|
3205
3205
|
// src/scoring/checks/coverage.ts
|
|
3206
3206
|
import { readFileSync, readdirSync } from "fs";
|
|
3207
3207
|
import { join } from "path";
|
|
3208
|
-
function readFileOrNull(
|
|
3208
|
+
function readFileOrNull(path24) {
|
|
3209
3209
|
try {
|
|
3210
|
-
return readFileSync(
|
|
3210
|
+
return readFileSync(path24, "utf-8");
|
|
3211
3211
|
} catch {
|
|
3212
3212
|
return null;
|
|
3213
3213
|
}
|
|
3214
3214
|
}
|
|
3215
|
-
function readJsonOrNull(
|
|
3216
|
-
const content = readFileOrNull(
|
|
3215
|
+
function readJsonOrNull(path24) {
|
|
3216
|
+
const content = readFileOrNull(path24);
|
|
3217
3217
|
if (!content) return null;
|
|
3218
3218
|
try {
|
|
3219
3219
|
return JSON.parse(content);
|
|
@@ -3581,9 +3581,9 @@ function checkExistence(dir) {
|
|
|
3581
3581
|
// src/scoring/checks/quality.ts
|
|
3582
3582
|
import { readFileSync as readFileSync3 } from "fs";
|
|
3583
3583
|
import { join as join3 } from "path";
|
|
3584
|
-
function readFileOrNull2(
|
|
3584
|
+
function readFileOrNull2(path24) {
|
|
3585
3585
|
try {
|
|
3586
|
-
return readFileSync3(
|
|
3586
|
+
return readFileSync3(path24, "utf-8");
|
|
3587
3587
|
} catch {
|
|
3588
3588
|
return null;
|
|
3589
3589
|
}
|
|
@@ -3736,15 +3736,15 @@ function checkQuality(dir) {
|
|
|
3736
3736
|
// src/scoring/checks/accuracy.ts
|
|
3737
3737
|
import { existsSync as existsSync5, readFileSync as readFileSync4, readdirSync as readdirSync3, statSync } from "fs";
|
|
3738
3738
|
import { join as join4 } from "path";
|
|
3739
|
-
function readFileOrNull3(
|
|
3739
|
+
function readFileOrNull3(path24) {
|
|
3740
3740
|
try {
|
|
3741
|
-
return readFileSync4(
|
|
3741
|
+
return readFileSync4(path24, "utf-8");
|
|
3742
3742
|
} catch {
|
|
3743
3743
|
return null;
|
|
3744
3744
|
}
|
|
3745
3745
|
}
|
|
3746
|
-
function readJsonOrNull2(
|
|
3747
|
-
const content = readFileOrNull3(
|
|
3746
|
+
function readJsonOrNull2(path24) {
|
|
3747
|
+
const content = readFileOrNull3(path24);
|
|
3748
3748
|
if (!content) return null;
|
|
3749
3749
|
try {
|
|
3750
3750
|
return JSON.parse(content);
|
|
@@ -3927,9 +3927,9 @@ function checkAccuracy(dir) {
|
|
|
3927
3927
|
// src/scoring/checks/freshness.ts
|
|
3928
3928
|
import { existsSync as existsSync6, readFileSync as readFileSync5, statSync as statSync2 } from "fs";
|
|
3929
3929
|
import { join as join5 } from "path";
|
|
3930
|
-
function readFileOrNull4(
|
|
3930
|
+
function readFileOrNull4(path24) {
|
|
3931
3931
|
try {
|
|
3932
|
-
return readFileSync5(
|
|
3932
|
+
return readFileSync5(path24, "utf-8");
|
|
3933
3933
|
} catch {
|
|
3934
3934
|
return null;
|
|
3935
3935
|
}
|
|
@@ -4043,9 +4043,9 @@ function checkFreshness(dir) {
|
|
|
4043
4043
|
import { existsSync as existsSync7, readFileSync as readFileSync6, readdirSync as readdirSync4 } from "fs";
|
|
4044
4044
|
import { execSync as execSync7 } from "child_process";
|
|
4045
4045
|
import { join as join6 } from "path";
|
|
4046
|
-
function readFileOrNull5(
|
|
4046
|
+
function readFileOrNull5(path24) {
|
|
4047
4047
|
try {
|
|
4048
|
-
return readFileSync6(
|
|
4048
|
+
return readFileSync6(path24, "utf-8");
|
|
4049
4049
|
} catch {
|
|
4050
4050
|
return null;
|
|
4051
4051
|
}
|
|
@@ -4343,7 +4343,7 @@ function displayScoreDelta(before, after) {
|
|
|
4343
4343
|
}
|
|
4344
4344
|
|
|
4345
4345
|
// src/commands/recommend.ts
|
|
4346
|
-
import
|
|
4346
|
+
import chalk7 from "chalk";
|
|
4347
4347
|
import ora from "ora";
|
|
4348
4348
|
import select4 from "@inquirer/select";
|
|
4349
4349
|
import { mkdirSync, readFileSync as readFileSync7, readdirSync as readdirSync5, existsSync as existsSync9, writeFileSync } from "fs";
|
|
@@ -4495,6 +4495,167 @@ function hashJson(obj) {
|
|
|
4495
4495
|
|
|
4496
4496
|
// src/commands/recommend.ts
|
|
4497
4497
|
init_config();
|
|
4498
|
+
|
|
4499
|
+
// src/telemetry/index.ts
|
|
4500
|
+
import { PostHog } from "posthog-node";
|
|
4501
|
+
import chalk6 from "chalk";
|
|
4502
|
+
|
|
4503
|
+
// src/telemetry/config.ts
|
|
4504
|
+
import fs21 from "fs";
|
|
4505
|
+
import path17 from "path";
|
|
4506
|
+
import os3 from "os";
|
|
4507
|
+
import crypto3 from "crypto";
|
|
4508
|
+
import { execSync as execSync8 } from "child_process";
|
|
4509
|
+
var CONFIG_DIR2 = path17.join(os3.homedir(), ".caliber");
|
|
4510
|
+
var CONFIG_FILE2 = path17.join(CONFIG_DIR2, "config.json");
|
|
4511
|
+
var runtimeDisabled = false;
|
|
4512
|
+
function readConfig() {
|
|
4513
|
+
try {
|
|
4514
|
+
if (!fs21.existsSync(CONFIG_FILE2)) return {};
|
|
4515
|
+
return JSON.parse(fs21.readFileSync(CONFIG_FILE2, "utf-8"));
|
|
4516
|
+
} catch {
|
|
4517
|
+
return {};
|
|
4518
|
+
}
|
|
4519
|
+
}
|
|
4520
|
+
function writeConfig(config) {
|
|
4521
|
+
if (!fs21.existsSync(CONFIG_DIR2)) {
|
|
4522
|
+
fs21.mkdirSync(CONFIG_DIR2, { recursive: true });
|
|
4523
|
+
}
|
|
4524
|
+
fs21.writeFileSync(CONFIG_FILE2, JSON.stringify(config, null, 2) + "\n", { mode: 384 });
|
|
4525
|
+
}
|
|
4526
|
+
function getMachineId() {
|
|
4527
|
+
const config = readConfig();
|
|
4528
|
+
if (config.machineId) return config.machineId;
|
|
4529
|
+
const machineId = crypto3.randomUUID();
|
|
4530
|
+
writeConfig({ ...config, machineId });
|
|
4531
|
+
return machineId;
|
|
4532
|
+
}
|
|
4533
|
+
function getGitEmailHash() {
|
|
4534
|
+
try {
|
|
4535
|
+
const email = execSync8("git config user.email", { encoding: "utf-8" }).trim();
|
|
4536
|
+
if (!email) return void 0;
|
|
4537
|
+
return crypto3.createHash("sha256").update(email).digest("hex");
|
|
4538
|
+
} catch {
|
|
4539
|
+
return void 0;
|
|
4540
|
+
}
|
|
4541
|
+
}
|
|
4542
|
+
function isTelemetryDisabled() {
|
|
4543
|
+
if (runtimeDisabled) return true;
|
|
4544
|
+
const envVal = process.env.CALIBER_TELEMETRY_DISABLED;
|
|
4545
|
+
return envVal === "1" || envVal === "true";
|
|
4546
|
+
}
|
|
4547
|
+
function setTelemetryDisabled(disabled) {
|
|
4548
|
+
runtimeDisabled = disabled;
|
|
4549
|
+
}
|
|
4550
|
+
function wasNoticeShown() {
|
|
4551
|
+
return readConfig().telemetryNoticeShown === true;
|
|
4552
|
+
}
|
|
4553
|
+
function markNoticeShown() {
|
|
4554
|
+
const config = readConfig();
|
|
4555
|
+
writeConfig({ ...config, telemetryNoticeShown: true });
|
|
4556
|
+
}
|
|
4557
|
+
|
|
4558
|
+
// src/telemetry/index.ts
|
|
4559
|
+
var POSTHOG_KEY = "phc_XXrV0pSX4s2QVxVoOaeuyXDvtlRwPAjovt1ttMGVMPp";
|
|
4560
|
+
var client = null;
|
|
4561
|
+
var distinctId = null;
|
|
4562
|
+
function initTelemetry() {
|
|
4563
|
+
if (isTelemetryDisabled()) return;
|
|
4564
|
+
const machineId = getMachineId();
|
|
4565
|
+
distinctId = machineId;
|
|
4566
|
+
client = new PostHog(POSTHOG_KEY, {
|
|
4567
|
+
host: "https://us.i.posthog.com",
|
|
4568
|
+
flushAt: 20,
|
|
4569
|
+
flushInterval: 1e4
|
|
4570
|
+
});
|
|
4571
|
+
if (!wasNoticeShown()) {
|
|
4572
|
+
console.log(
|
|
4573
|
+
chalk6.dim(" Caliber collects anonymous usage data to improve the product.") + "\n" + chalk6.dim(" Disable with --no-traces or CALIBER_TELEMETRY_DISABLED=1\n")
|
|
4574
|
+
);
|
|
4575
|
+
markNoticeShown();
|
|
4576
|
+
}
|
|
4577
|
+
const gitEmailHash = getGitEmailHash();
|
|
4578
|
+
client.identify({
|
|
4579
|
+
distinctId: machineId,
|
|
4580
|
+
properties: {
|
|
4581
|
+
...gitEmailHash ? { git_email_hash: gitEmailHash } : {}
|
|
4582
|
+
}
|
|
4583
|
+
});
|
|
4584
|
+
}
|
|
4585
|
+
function trackEvent(name, properties) {
|
|
4586
|
+
if (!client || !distinctId || isTelemetryDisabled()) return;
|
|
4587
|
+
client.capture({
|
|
4588
|
+
distinctId,
|
|
4589
|
+
event: name,
|
|
4590
|
+
properties: properties ?? {}
|
|
4591
|
+
});
|
|
4592
|
+
}
|
|
4593
|
+
async function flushTelemetry() {
|
|
4594
|
+
if (!client) return;
|
|
4595
|
+
try {
|
|
4596
|
+
await client.shutdown();
|
|
4597
|
+
} catch {
|
|
4598
|
+
}
|
|
4599
|
+
client = null;
|
|
4600
|
+
}
|
|
4601
|
+
|
|
4602
|
+
// src/telemetry/events.ts
|
|
4603
|
+
function trackInitProviderSelected(provider, model) {
|
|
4604
|
+
trackEvent("init_provider_selected", { provider, model });
|
|
4605
|
+
}
|
|
4606
|
+
function trackInitProjectDiscovered(languageCount, dependencyCount, fileCount) {
|
|
4607
|
+
trackEvent("init_project_discovered", { language_count: languageCount, dependency_count: dependencyCount, file_count: fileCount });
|
|
4608
|
+
}
|
|
4609
|
+
function trackInitAgentSelected(agents) {
|
|
4610
|
+
trackEvent("init_agent_selected", { agents });
|
|
4611
|
+
}
|
|
4612
|
+
function trackInitScoreComputed(score, passingCount, failingCount, earlyExit) {
|
|
4613
|
+
trackEvent("init_score_computed", { score, passing_count: passingCount, failing_count: failingCount, early_exit: earlyExit });
|
|
4614
|
+
}
|
|
4615
|
+
function trackInitGenerationStarted(isTargetedFix) {
|
|
4616
|
+
trackEvent("init_generation_started", { is_targeted_fix: isTargetedFix });
|
|
4617
|
+
}
|
|
4618
|
+
function trackInitGenerationCompleted(durationMs, retryCount) {
|
|
4619
|
+
trackEvent("init_generation_completed", { duration_ms: durationMs, retry_count: retryCount });
|
|
4620
|
+
}
|
|
4621
|
+
function trackInitReviewAction(action, reviewMethod) {
|
|
4622
|
+
trackEvent("init_review_action", { action, review_method: reviewMethod });
|
|
4623
|
+
}
|
|
4624
|
+
function trackInitRefinementRound(roundNumber, wasValid) {
|
|
4625
|
+
trackEvent("init_refinement_round", { round_number: roundNumber, was_valid: wasValid });
|
|
4626
|
+
}
|
|
4627
|
+
function trackInitFilesWritten(fileCount, createdCount, modifiedCount, deletedCount) {
|
|
4628
|
+
trackEvent("init_files_written", { file_count: fileCount, created_count: createdCount, modified_count: modifiedCount, deleted_count: deletedCount });
|
|
4629
|
+
}
|
|
4630
|
+
function trackInitHookSelected(hookType) {
|
|
4631
|
+
trackEvent("init_hook_selected", { hook_type: hookType });
|
|
4632
|
+
}
|
|
4633
|
+
function trackInitSkillsSearch(searched, installedCount) {
|
|
4634
|
+
trackEvent("init_skills_search", { searched, installed_count: installedCount });
|
|
4635
|
+
}
|
|
4636
|
+
function trackInitScoreRegression(oldScore, newScore) {
|
|
4637
|
+
trackEvent("init_score_regression", { old_score: oldScore, new_score: newScore });
|
|
4638
|
+
}
|
|
4639
|
+
function trackRegenerateCompleted(action, durationMs) {
|
|
4640
|
+
trackEvent("regenerate_completed", { action, duration_ms: durationMs });
|
|
4641
|
+
}
|
|
4642
|
+
function trackRefreshCompleted(changesCount, durationMs) {
|
|
4643
|
+
trackEvent("refresh_completed", { changes_count: changesCount, duration_ms: durationMs });
|
|
4644
|
+
}
|
|
4645
|
+
function trackScoreComputed(score, agent) {
|
|
4646
|
+
trackEvent("score_computed", { score, agent });
|
|
4647
|
+
}
|
|
4648
|
+
function trackConfigProviderSet(provider) {
|
|
4649
|
+
trackEvent("config_provider_set", { provider });
|
|
4650
|
+
}
|
|
4651
|
+
function trackSkillsInstalled(count) {
|
|
4652
|
+
trackEvent("skills_installed", { count });
|
|
4653
|
+
}
|
|
4654
|
+
function trackUndoExecuted() {
|
|
4655
|
+
trackEvent("undo_executed");
|
|
4656
|
+
}
|
|
4657
|
+
|
|
4658
|
+
// src/commands/recommend.ts
|
|
4498
4659
|
function detectLocalPlatforms() {
|
|
4499
4660
|
const items = scanLocalState(process.cwd());
|
|
4500
4661
|
const platforms = /* @__PURE__ */ new Set();
|
|
@@ -4802,7 +4963,7 @@ async function recommendCommand() {
|
|
|
4802
4963
|
]
|
|
4803
4964
|
});
|
|
4804
4965
|
if (!proceed) {
|
|
4805
|
-
console.log(
|
|
4966
|
+
console.log(chalk7.dim(" Cancelled.\n"));
|
|
4806
4967
|
return;
|
|
4807
4968
|
}
|
|
4808
4969
|
await searchAndInstallSkills();
|
|
@@ -4817,7 +4978,7 @@ async function searchAndInstallSkills() {
|
|
|
4817
4978
|
...extractTopDeps()
|
|
4818
4979
|
].filter(Boolean))];
|
|
4819
4980
|
if (technologies.length === 0) {
|
|
4820
|
-
console.log(
|
|
4981
|
+
console.log(chalk7.yellow("Could not detect any languages or dependencies. Try running from a project root."));
|
|
4821
4982
|
throw new Error("__exit__");
|
|
4822
4983
|
}
|
|
4823
4984
|
const primaryPlatform = platforms.includes("claude") ? "claude" : platforms[0];
|
|
@@ -4834,7 +4995,7 @@ async function searchAndInstallSkills() {
|
|
|
4834
4995
|
return;
|
|
4835
4996
|
}
|
|
4836
4997
|
searchSpinner.succeed(
|
|
4837
|
-
`Found ${allCandidates.length} skills` + (filteredCount > 0 ?
|
|
4998
|
+
`Found ${allCandidates.length} skills` + (filteredCount > 0 ? chalk7.dim(` (${filteredCount} already installed)`) : "")
|
|
4838
4999
|
);
|
|
4839
5000
|
let results;
|
|
4840
5001
|
const config = loadConfig();
|
|
@@ -4868,7 +5029,7 @@ async function searchAndInstallSkills() {
|
|
|
4868
5029
|
}
|
|
4869
5030
|
const unavailableCount = results.length - available.length;
|
|
4870
5031
|
fetchSpinner.succeed(
|
|
4871
|
-
`${available.length} installable skill${available.length > 1 ? "s" : ""}` + (unavailableCount > 0 ?
|
|
5032
|
+
`${available.length} installable skill${available.length > 1 ? "s" : ""}` + (unavailableCount > 0 ? chalk7.dim(` (${unavailableCount} unavailable)`) : "")
|
|
4872
5033
|
);
|
|
4873
5034
|
const selected = await interactiveSelect(available);
|
|
4874
5035
|
if (selected?.length) {
|
|
@@ -4891,30 +5052,30 @@ async function interactiveSelect(recs) {
|
|
|
4891
5052
|
const nameWidth = Math.max(...recs.map((r) => r.name.length), 4) + 2;
|
|
4892
5053
|
const prefixWidth = 8;
|
|
4893
5054
|
const scoreWidth = 6;
|
|
4894
|
-
lines.push(
|
|
5055
|
+
lines.push(chalk7.bold(" Skills"));
|
|
4895
5056
|
lines.push("");
|
|
4896
5057
|
if (hasScores) {
|
|
4897
|
-
const header = " ".repeat(prefixWidth) +
|
|
5058
|
+
const header = " ".repeat(prefixWidth) + chalk7.dim("Score".padEnd(scoreWidth)) + chalk7.dim("Name".padEnd(nameWidth)) + chalk7.dim("Why");
|
|
4898
5059
|
lines.push(header);
|
|
4899
5060
|
} else {
|
|
4900
|
-
const header = " ".repeat(prefixWidth) +
|
|
5061
|
+
const header = " ".repeat(prefixWidth) + chalk7.dim("Name".padEnd(nameWidth)) + chalk7.dim("Technology".padEnd(18)) + chalk7.dim("Source");
|
|
4901
5062
|
lines.push(header);
|
|
4902
5063
|
}
|
|
4903
|
-
lines.push(
|
|
5064
|
+
lines.push(chalk7.dim(" " + "\u2500".repeat(Math.min(cols - 4, 90))));
|
|
4904
5065
|
for (let i = 0; i < recs.length; i++) {
|
|
4905
5066
|
const rec = recs[i];
|
|
4906
|
-
const check = selected.has(i) ?
|
|
4907
|
-
const ptr = i === cursor ?
|
|
5067
|
+
const check = selected.has(i) ? chalk7.green("[x]") : "[ ]";
|
|
5068
|
+
const ptr = i === cursor ? chalk7.cyan(">") : " ";
|
|
4908
5069
|
if (hasScores) {
|
|
4909
|
-
const scoreColor = rec.score >= 90 ?
|
|
5070
|
+
const scoreColor = rec.score >= 90 ? chalk7.green : rec.score >= 70 ? chalk7.yellow : chalk7.dim;
|
|
4910
5071
|
const reasonMax = Math.max(cols - prefixWidth - scoreWidth - nameWidth - 2, 20);
|
|
4911
|
-
lines.push(` ${ptr} ${check} ${scoreColor(String(rec.score).padStart(3))} ${rec.name.padEnd(nameWidth)}${
|
|
5072
|
+
lines.push(` ${ptr} ${check} ${scoreColor(String(rec.score).padStart(3))} ${rec.name.padEnd(nameWidth)}${chalk7.dim(rec.reason.slice(0, reasonMax))}`);
|
|
4912
5073
|
} else {
|
|
4913
|
-
lines.push(` ${ptr} ${check} ${rec.name.padEnd(nameWidth)}${rec.detected_technology.padEnd(16)} ${
|
|
5074
|
+
lines.push(` ${ptr} ${check} ${rec.name.padEnd(nameWidth)}${rec.detected_technology.padEnd(16)} ${chalk7.dim(rec.source_url || "")}`);
|
|
4914
5075
|
}
|
|
4915
5076
|
}
|
|
4916
5077
|
lines.push("");
|
|
4917
|
-
lines.push(
|
|
5078
|
+
lines.push(chalk7.dim(" \u2191\u2193 navigate \u23B5 toggle a all n none \u23CE install q cancel"));
|
|
4918
5079
|
return lines.join("\n");
|
|
4919
5080
|
}
|
|
4920
5081
|
function draw(initial) {
|
|
@@ -4963,7 +5124,7 @@ async function interactiveSelect(recs) {
|
|
|
4963
5124
|
case "\n":
|
|
4964
5125
|
cleanup();
|
|
4965
5126
|
if (selected.size === 0) {
|
|
4966
|
-
console.log(
|
|
5127
|
+
console.log(chalk7.dim("\n No skills selected.\n"));
|
|
4967
5128
|
resolve2(null);
|
|
4968
5129
|
} else {
|
|
4969
5130
|
resolve2(Array.from(selected).sort().map((i) => recs[i]));
|
|
@@ -4973,7 +5134,7 @@ async function interactiveSelect(recs) {
|
|
|
4973
5134
|
case "\x1B":
|
|
4974
5135
|
case "":
|
|
4975
5136
|
cleanup();
|
|
4976
|
-
console.log(
|
|
5137
|
+
console.log(chalk7.dim("\n Cancelled.\n"));
|
|
4977
5138
|
resolve2(null);
|
|
4978
5139
|
break;
|
|
4979
5140
|
}
|
|
@@ -5034,9 +5195,10 @@ async function installSkills(recs, platforms, contentMap) {
|
|
|
5034
5195
|
}
|
|
5035
5196
|
}
|
|
5036
5197
|
if (installed.length > 0) {
|
|
5198
|
+
trackSkillsInstalled(installed.length);
|
|
5037
5199
|
spinner.succeed(`Installed ${installed.length} file${installed.length > 1 ? "s" : ""}`);
|
|
5038
5200
|
for (const p of installed) {
|
|
5039
|
-
console.log(
|
|
5201
|
+
console.log(chalk7.green(` \u2713 ${p}`));
|
|
5040
5202
|
}
|
|
5041
5203
|
} else {
|
|
5042
5204
|
spinner.fail("No skills were installed");
|
|
@@ -5049,19 +5211,19 @@ function printSkills(recs) {
|
|
|
5049
5211
|
const nameWidth = Math.max(...recs.map((r) => r.name.length), 4) + 2;
|
|
5050
5212
|
const scoreWidth = 6;
|
|
5051
5213
|
const prefixWidth = 2;
|
|
5052
|
-
console.log(
|
|
5214
|
+
console.log(chalk7.bold("\n Skills\n"));
|
|
5053
5215
|
if (hasScores) {
|
|
5054
|
-
console.log(" ".repeat(prefixWidth) +
|
|
5216
|
+
console.log(" ".repeat(prefixWidth) + chalk7.dim("Score".padEnd(scoreWidth)) + chalk7.dim("Name".padEnd(nameWidth)) + chalk7.dim("Why"));
|
|
5055
5217
|
} else {
|
|
5056
|
-
console.log(" ".repeat(prefixWidth) +
|
|
5218
|
+
console.log(" ".repeat(prefixWidth) + chalk7.dim("Name".padEnd(nameWidth)) + chalk7.dim("Technology".padEnd(18)) + chalk7.dim("Source"));
|
|
5057
5219
|
}
|
|
5058
|
-
console.log(
|
|
5220
|
+
console.log(chalk7.dim(" " + "\u2500".repeat(Math.min(cols - 4, 90))));
|
|
5059
5221
|
for (const rec of recs) {
|
|
5060
5222
|
if (hasScores) {
|
|
5061
5223
|
const reasonMax = Math.max(cols - prefixWidth - scoreWidth - nameWidth - 2, 20);
|
|
5062
|
-
console.log(` ${String(rec.score).padStart(3)} ${rec.name.padEnd(nameWidth)}${
|
|
5224
|
+
console.log(` ${String(rec.score).padStart(3)} ${rec.name.padEnd(nameWidth)}${chalk7.dim(rec.reason.slice(0, reasonMax))}`);
|
|
5063
5225
|
} else {
|
|
5064
|
-
console.log(` ${rec.name.padEnd(nameWidth)}${rec.detected_technology.padEnd(16)} ${
|
|
5226
|
+
console.log(` ${rec.name.padEnd(nameWidth)}${rec.detected_technology.padEnd(16)} ${chalk7.dim(rec.source_url || "")}`);
|
|
5065
5227
|
}
|
|
5066
5228
|
}
|
|
5067
5229
|
console.log("");
|
|
@@ -5069,8 +5231,8 @@ function printSkills(recs) {
|
|
|
5069
5231
|
|
|
5070
5232
|
// src/commands/onboard.ts
|
|
5071
5233
|
async function initCommand(options) {
|
|
5072
|
-
const brand =
|
|
5073
|
-
const title =
|
|
5234
|
+
const brand = chalk8.hex("#EB9D83");
|
|
5235
|
+
const title = chalk8.hex("#83D1EB");
|
|
5074
5236
|
console.log(brand.bold(`
|
|
5075
5237
|
\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
|
|
5076
5238
|
\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
|
|
@@ -5079,21 +5241,21 @@ async function initCommand(options) {
|
|
|
5079
5241
|
\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
|
|
5080
5242
|
\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
|
|
5081
5243
|
`));
|
|
5082
|
-
console.log(
|
|
5244
|
+
console.log(chalk8.dim(" Onboard your project for AI-assisted development\n"));
|
|
5083
5245
|
console.log(title.bold(" Welcome to Caliber\n"));
|
|
5084
|
-
console.log(
|
|
5085
|
-
console.log(
|
|
5246
|
+
console.log(chalk8.dim(" Caliber analyzes your codebase and creates tailored config files"));
|
|
5247
|
+
console.log(chalk8.dim(" so your AI coding agents understand your project from day one.\n"));
|
|
5086
5248
|
console.log(title.bold(" How onboarding works:\n"));
|
|
5087
|
-
console.log(
|
|
5088
|
-
console.log(
|
|
5089
|
-
console.log(
|
|
5090
|
-
console.log(
|
|
5091
|
-
console.log(
|
|
5092
|
-
console.log(
|
|
5249
|
+
console.log(chalk8.dim(" 1. Connect Set up your LLM provider"));
|
|
5250
|
+
console.log(chalk8.dim(" 2. Discover Analyze your code, dependencies, and structure"));
|
|
5251
|
+
console.log(chalk8.dim(" 3. Generate Create config files tailored to your project"));
|
|
5252
|
+
console.log(chalk8.dim(" 4. Review Preview, refine, and apply the changes"));
|
|
5253
|
+
console.log(chalk8.dim(" 5. Enhance Discover MCP servers for your tools"));
|
|
5254
|
+
console.log(chalk8.dim(" 6. Skills Browse community skills for your stack\n"));
|
|
5093
5255
|
console.log(title.bold(" Step 1/6 \u2014 Connect your LLM\n"));
|
|
5094
5256
|
let config = loadConfig();
|
|
5095
5257
|
if (!config) {
|
|
5096
|
-
console.log(
|
|
5258
|
+
console.log(chalk8.dim(" No LLM provider set yet. Choose how to run Caliber:\n"));
|
|
5097
5259
|
try {
|
|
5098
5260
|
await runInteractiveProviderSetup({
|
|
5099
5261
|
selectMessage: "How do you want to use Caliber? (choose LLM provider)"
|
|
@@ -5104,25 +5266,28 @@ async function initCommand(options) {
|
|
|
5104
5266
|
}
|
|
5105
5267
|
config = loadConfig();
|
|
5106
5268
|
if (!config) {
|
|
5107
|
-
console.log(
|
|
5269
|
+
console.log(chalk8.red(" Setup was cancelled or failed.\n"));
|
|
5108
5270
|
throw new Error("__exit__");
|
|
5109
5271
|
}
|
|
5110
|
-
console.log(
|
|
5272
|
+
console.log(chalk8.green(" \u2713 Provider saved. Let's continue.\n"));
|
|
5111
5273
|
}
|
|
5274
|
+
trackInitProviderSelected(config.provider, config.model);
|
|
5112
5275
|
const displayModel = config.model === "default" && config.provider === "claude-cli" ? process.env.ANTHROPIC_MODEL || "default (inherited from Claude Code)" : config.model;
|
|
5113
5276
|
const fastModel = getFastModel();
|
|
5114
5277
|
const modelLine = fastModel ? ` Provider: ${config.provider} | Model: ${displayModel} | Scan: ${fastModel}` : ` Provider: ${config.provider} | Model: ${displayModel}`;
|
|
5115
|
-
console.log(
|
|
5278
|
+
console.log(chalk8.dim(modelLine + "\n"));
|
|
5116
5279
|
await validateModel({ fast: true });
|
|
5117
5280
|
console.log(title.bold(" Step 2/6 \u2014 Discover your project\n"));
|
|
5118
|
-
console.log(
|
|
5281
|
+
console.log(chalk8.dim(" Learning about your languages, dependencies, structure, and existing configs.\n"));
|
|
5119
5282
|
const spinner = ora2("Analyzing project...").start();
|
|
5120
5283
|
const fingerprint = await collectFingerprint(process.cwd());
|
|
5121
5284
|
spinner.succeed("Project analyzed");
|
|
5122
|
-
|
|
5123
|
-
console.log(
|
|
5285
|
+
trackInitProjectDiscovered(fingerprint.languages.length, fingerprint.frameworks.length, fingerprint.fileTree.length);
|
|
5286
|
+
console.log(chalk8.dim(` Languages: ${fingerprint.languages.join(", ") || "none detected"}`));
|
|
5287
|
+
console.log(chalk8.dim(` Files: ${fingerprint.fileTree.length} found
|
|
5124
5288
|
`));
|
|
5125
5289
|
const targetAgent = options.agent || await promptAgent();
|
|
5290
|
+
trackInitAgentSelected(targetAgent);
|
|
5126
5291
|
const preScore = computeLocalScore(process.cwd(), targetAgent);
|
|
5127
5292
|
const failingForDismissal = preScore.checks.filter((c) => !c.passed && c.maxPoints > 0);
|
|
5128
5293
|
if (failingForDismissal.length > 0) {
|
|
@@ -5136,26 +5301,30 @@ async function initCommand(options) {
|
|
|
5136
5301
|
}
|
|
5137
5302
|
const baselineScore = computeLocalScore(process.cwd(), targetAgent);
|
|
5138
5303
|
displayScoreSummary(baselineScore);
|
|
5304
|
+
const passingCount = baselineScore.checks.filter((c) => c.passed).length;
|
|
5305
|
+
const failingCount = baselineScore.checks.filter((c) => !c.passed).length;
|
|
5139
5306
|
const hasExistingConfig = !!(fingerprint.existingConfigs.claudeMd || fingerprint.existingConfigs.claudeSettings || fingerprint.existingConfigs.claudeSkills?.length || fingerprint.existingConfigs.cursorrules || fingerprint.existingConfigs.cursorRules?.length || fingerprint.existingConfigs.agentsMd);
|
|
5140
5307
|
const NON_LLM_CHECKS = /* @__PURE__ */ new Set(["hooks_configured", "agents_md_exists", "permissions_configured", "mcp_servers"]);
|
|
5141
5308
|
if (hasExistingConfig && baselineScore.score === 100) {
|
|
5142
|
-
|
|
5143
|
-
console.log(
|
|
5309
|
+
trackInitScoreComputed(baselineScore.score, passingCount, failingCount, true);
|
|
5310
|
+
console.log(chalk8.bold.green(" Your setup is already optimal \u2014 nothing to change.\n"));
|
|
5311
|
+
console.log(chalk8.dim(" Run ") + chalk8.hex("#83D1EB")("caliber onboard --force") + chalk8.dim(" to regenerate anyway.\n"));
|
|
5144
5312
|
if (!options.force) return;
|
|
5145
5313
|
}
|
|
5146
5314
|
const allFailingChecks = baselineScore.checks.filter((c) => !c.passed && c.maxPoints > 0);
|
|
5147
5315
|
const llmFixableChecks = allFailingChecks.filter((c) => !NON_LLM_CHECKS.has(c.id));
|
|
5316
|
+
trackInitScoreComputed(baselineScore.score, passingCount, failingCount, false);
|
|
5148
5317
|
if (hasExistingConfig && llmFixableChecks.length === 0 && allFailingChecks.length > 0 && !options.force) {
|
|
5149
|
-
console.log(
|
|
5150
|
-
console.log(
|
|
5318
|
+
console.log(chalk8.bold.green("\n Your config is fully optimized for LLM generation.\n"));
|
|
5319
|
+
console.log(chalk8.dim(" Remaining items need CLI actions:\n"));
|
|
5151
5320
|
for (const check of allFailingChecks) {
|
|
5152
|
-
console.log(
|
|
5321
|
+
console.log(chalk8.dim(` \u2022 ${check.name}`));
|
|
5153
5322
|
if (check.suggestion) {
|
|
5154
|
-
console.log(` ${
|
|
5323
|
+
console.log(` ${chalk8.hex("#83D1EB")(check.suggestion)}`);
|
|
5155
5324
|
}
|
|
5156
5325
|
}
|
|
5157
5326
|
console.log("");
|
|
5158
|
-
console.log(
|
|
5327
|
+
console.log(chalk8.dim(" Run ") + chalk8.hex("#83D1EB")("caliber onboard --force") + chalk8.dim(" to regenerate anyway.\n"));
|
|
5159
5328
|
return;
|
|
5160
5329
|
}
|
|
5161
5330
|
const isEmpty = fingerprint.fileTree.length < 3;
|
|
@@ -5171,22 +5340,23 @@ async function initCommand(options) {
|
|
|
5171
5340
|
currentScore = baselineScore.score;
|
|
5172
5341
|
if (failingChecks.length > 0) {
|
|
5173
5342
|
console.log(title.bold(" Step 3/6 \u2014 Fine-tuning\n"));
|
|
5174
|
-
console.log(
|
|
5343
|
+
console.log(chalk8.dim(` Your setup scores ${baselineScore.score}/100 \u2014 fixing ${failingChecks.length} remaining issue${failingChecks.length === 1 ? "" : "s"}:
|
|
5175
5344
|
`));
|
|
5176
5345
|
for (const check of failingChecks) {
|
|
5177
|
-
console.log(
|
|
5346
|
+
console.log(chalk8.dim(` \u2022 ${check.name}`));
|
|
5178
5347
|
}
|
|
5179
5348
|
console.log("");
|
|
5180
5349
|
}
|
|
5181
5350
|
} else if (hasExistingConfig) {
|
|
5182
5351
|
console.log(title.bold(" Step 3/6 \u2014 Improve your setup\n"));
|
|
5183
|
-
console.log(
|
|
5184
|
-
console.log(
|
|
5352
|
+
console.log(chalk8.dim(" Reviewing your existing configs against your codebase"));
|
|
5353
|
+
console.log(chalk8.dim(" and preparing improvements.\n"));
|
|
5185
5354
|
} else {
|
|
5186
5355
|
console.log(title.bold(" Step 3/6 \u2014 Build your agent setup\n"));
|
|
5187
|
-
console.log(
|
|
5356
|
+
console.log(chalk8.dim(" Creating config files tailored to your project.\n"));
|
|
5188
5357
|
}
|
|
5189
|
-
console.log(
|
|
5358
|
+
console.log(chalk8.dim(" This can take a couple of minutes depending on your model and provider.\n"));
|
|
5359
|
+
trackInitGenerationStarted(!!failingChecks);
|
|
5190
5360
|
const genStartTime = Date.now();
|
|
5191
5361
|
const genSpinner = ora2("Generating setup...").start();
|
|
5192
5362
|
const genMessages = new SpinnerMessages(genSpinner, GENERATION_MESSAGES, { showElapsedTime: true });
|
|
@@ -5228,16 +5398,17 @@ async function initCommand(options) {
|
|
|
5228
5398
|
if (!generatedSetup) {
|
|
5229
5399
|
genSpinner.fail("Failed to generate setup.");
|
|
5230
5400
|
if (rawOutput) {
|
|
5231
|
-
console.log(
|
|
5232
|
-
console.log(
|
|
5401
|
+
console.log(chalk8.dim("\nRaw LLM output (JSON parse failed):"));
|
|
5402
|
+
console.log(chalk8.dim(rawOutput.slice(0, 500)));
|
|
5233
5403
|
}
|
|
5234
5404
|
throw new Error("__exit__");
|
|
5235
5405
|
}
|
|
5236
5406
|
const elapsedMs = Date.now() - genStartTime;
|
|
5407
|
+
trackInitGenerationCompleted(elapsedMs, 0);
|
|
5237
5408
|
const mins = Math.floor(elapsedMs / 6e4);
|
|
5238
5409
|
const secs = Math.floor(elapsedMs % 6e4 / 1e3);
|
|
5239
5410
|
const timeStr = mins > 0 ? `${mins}m ${secs}s` : `${secs}s`;
|
|
5240
|
-
genSpinner.succeed(`Setup generated ${
|
|
5411
|
+
genSpinner.succeed(`Setup generated ${chalk8.dim(`in ${timeStr}`)}`);
|
|
5241
5412
|
printSetupSummary(generatedSetup);
|
|
5242
5413
|
const sessionHistory = [];
|
|
5243
5414
|
sessionHistory.push({
|
|
@@ -5248,11 +5419,11 @@ async function initCommand(options) {
|
|
|
5248
5419
|
const setupFiles = collectSetupFiles(generatedSetup);
|
|
5249
5420
|
const staged = stageFiles(setupFiles, process.cwd());
|
|
5250
5421
|
const totalChanges = staged.newFiles + staged.modifiedFiles;
|
|
5251
|
-
console.log(
|
|
5422
|
+
console.log(chalk8.dim(` ${chalk8.green(`${staged.newFiles} new`)} / ${chalk8.yellow(`${staged.modifiedFiles} modified`)} file${totalChanges !== 1 ? "s" : ""}
|
|
5252
5423
|
`));
|
|
5253
5424
|
let action;
|
|
5254
5425
|
if (totalChanges === 0) {
|
|
5255
|
-
console.log(
|
|
5426
|
+
console.log(chalk8.dim(" No changes needed \u2014 your configs are already up to date.\n"));
|
|
5256
5427
|
cleanupStaging();
|
|
5257
5428
|
action = "accept";
|
|
5258
5429
|
} else {
|
|
@@ -5262,29 +5433,34 @@ async function initCommand(options) {
|
|
|
5262
5433
|
await openReview(reviewMethod, staged.stagedFiles);
|
|
5263
5434
|
}
|
|
5264
5435
|
action = await promptReviewAction();
|
|
5436
|
+
trackInitReviewAction(action, wantsReview ? "reviewed" : "skipped");
|
|
5265
5437
|
}
|
|
5438
|
+
let refinementRound = 0;
|
|
5266
5439
|
while (action === "refine") {
|
|
5440
|
+
refinementRound++;
|
|
5267
5441
|
generatedSetup = await refineLoop(generatedSetup, targetAgent, sessionHistory);
|
|
5442
|
+
trackInitRefinementRound(refinementRound, !!generatedSetup);
|
|
5268
5443
|
if (!generatedSetup) {
|
|
5269
5444
|
cleanupStaging();
|
|
5270
|
-
console.log(
|
|
5445
|
+
console.log(chalk8.dim("Refinement cancelled. No files were modified."));
|
|
5271
5446
|
return;
|
|
5272
5447
|
}
|
|
5273
5448
|
const updatedFiles = collectSetupFiles(generatedSetup);
|
|
5274
5449
|
const restaged = stageFiles(updatedFiles, process.cwd());
|
|
5275
|
-
console.log(
|
|
5450
|
+
console.log(chalk8.dim(` ${chalk8.green(`${restaged.newFiles} new`)} / ${chalk8.yellow(`${restaged.modifiedFiles} modified`)} file${restaged.newFiles + restaged.modifiedFiles !== 1 ? "s" : ""}
|
|
5276
5451
|
`));
|
|
5277
5452
|
printSetupSummary(generatedSetup);
|
|
5278
5453
|
await openReview("terminal", restaged.stagedFiles);
|
|
5279
5454
|
action = await promptReviewAction();
|
|
5455
|
+
trackInitReviewAction(action, "terminal");
|
|
5280
5456
|
}
|
|
5281
5457
|
cleanupStaging();
|
|
5282
5458
|
if (action === "decline") {
|
|
5283
|
-
console.log(
|
|
5459
|
+
console.log(chalk8.dim("Setup declined. No files were modified."));
|
|
5284
5460
|
return;
|
|
5285
5461
|
}
|
|
5286
5462
|
if (options.dryRun) {
|
|
5287
|
-
console.log(
|
|
5463
|
+
console.log(chalk8.yellow("\n[Dry run] Would write the following files:"));
|
|
5288
5464
|
console.log(JSON.stringify(generatedSetup, null, 2));
|
|
5289
5465
|
return;
|
|
5290
5466
|
}
|
|
@@ -5292,23 +5468,29 @@ async function initCommand(options) {
|
|
|
5292
5468
|
try {
|
|
5293
5469
|
const result = writeSetup(generatedSetup);
|
|
5294
5470
|
writeSpinner.succeed("Config files written");
|
|
5295
|
-
|
|
5471
|
+
trackInitFilesWritten(
|
|
5472
|
+
result.written.length + result.deleted.length,
|
|
5473
|
+
result.written.length,
|
|
5474
|
+
0,
|
|
5475
|
+
result.deleted.length
|
|
5476
|
+
);
|
|
5477
|
+
console.log(chalk8.bold("\nFiles created/updated:"));
|
|
5296
5478
|
for (const file of result.written) {
|
|
5297
|
-
console.log(` ${
|
|
5479
|
+
console.log(` ${chalk8.green("\u2713")} ${file}`);
|
|
5298
5480
|
}
|
|
5299
5481
|
if (result.deleted.length > 0) {
|
|
5300
|
-
console.log(
|
|
5482
|
+
console.log(chalk8.bold("\nFiles removed:"));
|
|
5301
5483
|
for (const file of result.deleted) {
|
|
5302
|
-
console.log(` ${
|
|
5484
|
+
console.log(` ${chalk8.red("\u2717")} ${file}`);
|
|
5303
5485
|
}
|
|
5304
5486
|
}
|
|
5305
5487
|
if (result.backupDir) {
|
|
5306
|
-
console.log(
|
|
5488
|
+
console.log(chalk8.dim(`
|
|
5307
5489
|
Backups saved to ${result.backupDir}`));
|
|
5308
5490
|
}
|
|
5309
5491
|
} catch (err) {
|
|
5310
5492
|
writeSpinner.fail("Failed to write files");
|
|
5311
|
-
console.error(
|
|
5493
|
+
console.error(chalk8.red(err instanceof Error ? err.message : "Unknown error"));
|
|
5312
5494
|
throw new Error("__exit__");
|
|
5313
5495
|
}
|
|
5314
5496
|
ensurePermissions();
|
|
@@ -5320,55 +5502,57 @@ async function initCommand(options) {
|
|
|
5320
5502
|
});
|
|
5321
5503
|
console.log("");
|
|
5322
5504
|
console.log(title.bold(" Keep your configs fresh\n"));
|
|
5323
|
-
console.log(
|
|
5505
|
+
console.log(chalk8.dim(" Caliber can automatically update your agent configs when your code changes.\n"));
|
|
5324
5506
|
const hookChoice = await promptHookType(targetAgent);
|
|
5507
|
+
trackInitHookSelected(hookChoice);
|
|
5325
5508
|
if (hookChoice === "claude" || hookChoice === "both") {
|
|
5326
5509
|
const hookResult = installHook();
|
|
5327
5510
|
if (hookResult.installed) {
|
|
5328
|
-
console.log(` ${
|
|
5329
|
-
console.log(
|
|
5511
|
+
console.log(` ${chalk8.green("\u2713")} Claude Code hook installed \u2014 docs update on session end`);
|
|
5512
|
+
console.log(chalk8.dim(" Run ") + chalk8.hex("#83D1EB")("caliber hooks --remove") + chalk8.dim(" to disable"));
|
|
5330
5513
|
} else if (hookResult.alreadyInstalled) {
|
|
5331
|
-
console.log(
|
|
5514
|
+
console.log(chalk8.dim(" Claude Code hook already installed"));
|
|
5332
5515
|
}
|
|
5333
5516
|
const learnResult = installLearningHooks();
|
|
5334
5517
|
if (learnResult.installed) {
|
|
5335
|
-
console.log(` ${
|
|
5336
|
-
console.log(
|
|
5518
|
+
console.log(` ${chalk8.green("\u2713")} Learning hooks installed \u2014 session insights captured automatically`);
|
|
5519
|
+
console.log(chalk8.dim(" Run ") + chalk8.hex("#83D1EB")("caliber learn remove") + chalk8.dim(" to disable"));
|
|
5337
5520
|
} else if (learnResult.alreadyInstalled) {
|
|
5338
|
-
console.log(
|
|
5521
|
+
console.log(chalk8.dim(" Learning hooks already installed"));
|
|
5339
5522
|
}
|
|
5340
5523
|
}
|
|
5341
5524
|
if (hookChoice === "precommit" || hookChoice === "both") {
|
|
5342
5525
|
const precommitResult = installPreCommitHook();
|
|
5343
5526
|
if (precommitResult.installed) {
|
|
5344
|
-
console.log(` ${
|
|
5345
|
-
console.log(
|
|
5527
|
+
console.log(` ${chalk8.green("\u2713")} Pre-commit hook installed \u2014 docs refresh before each commit`);
|
|
5528
|
+
console.log(chalk8.dim(" Run ") + chalk8.hex("#83D1EB")("caliber hooks --remove") + chalk8.dim(" to disable"));
|
|
5346
5529
|
} else if (precommitResult.alreadyInstalled) {
|
|
5347
|
-
console.log(
|
|
5530
|
+
console.log(chalk8.dim(" Pre-commit hook already installed"));
|
|
5348
5531
|
} else {
|
|
5349
|
-
console.log(
|
|
5532
|
+
console.log(chalk8.yellow(" Could not install pre-commit hook (not a git repository?)"));
|
|
5350
5533
|
}
|
|
5351
5534
|
}
|
|
5352
5535
|
if (hookChoice === "skip") {
|
|
5353
|
-
console.log(
|
|
5536
|
+
console.log(chalk8.dim(" Skipped auto-refresh hooks. Run ") + chalk8.hex("#83D1EB")("caliber hooks --install") + chalk8.dim(" later to enable."));
|
|
5354
5537
|
}
|
|
5355
5538
|
const afterScore = computeLocalScore(process.cwd(), targetAgent);
|
|
5356
5539
|
if (afterScore.score < baselineScore.score) {
|
|
5540
|
+
trackInitScoreRegression(baselineScore.score, afterScore.score);
|
|
5357
5541
|
console.log("");
|
|
5358
|
-
console.log(
|
|
5542
|
+
console.log(chalk8.yellow(` Score would drop from ${baselineScore.score} to ${afterScore.score} \u2014 reverting changes.`));
|
|
5359
5543
|
try {
|
|
5360
5544
|
const { restored, removed } = undoSetup();
|
|
5361
5545
|
if (restored.length > 0 || removed.length > 0) {
|
|
5362
|
-
console.log(
|
|
5546
|
+
console.log(chalk8.dim(` Reverted ${restored.length + removed.length} file${restored.length + removed.length === 1 ? "" : "s"} from backup.`));
|
|
5363
5547
|
}
|
|
5364
5548
|
} catch {
|
|
5365
5549
|
}
|
|
5366
|
-
console.log(
|
|
5550
|
+
console.log(chalk8.dim(" Run ") + chalk8.hex("#83D1EB")("caliber onboard --force") + chalk8.dim(" to override.\n"));
|
|
5367
5551
|
return;
|
|
5368
5552
|
}
|
|
5369
5553
|
displayScoreDelta(baselineScore, afterScore);
|
|
5370
5554
|
console.log(title.bold("\n Step 6/6 \u2014 Community skills\n"));
|
|
5371
|
-
console.log(
|
|
5555
|
+
console.log(chalk8.dim(" Search public skill registries for skills that match your tech stack.\n"));
|
|
5372
5556
|
const wantsSkills = await select5({
|
|
5373
5557
|
message: "Search public repos for relevant skills to add to this project?",
|
|
5374
5558
|
choices: [
|
|
@@ -5377,20 +5561,22 @@ async function initCommand(options) {
|
|
|
5377
5561
|
]
|
|
5378
5562
|
});
|
|
5379
5563
|
if (wantsSkills) {
|
|
5564
|
+
trackInitSkillsSearch(true, 0);
|
|
5380
5565
|
try {
|
|
5381
5566
|
await searchAndInstallSkills();
|
|
5382
5567
|
} catch (err) {
|
|
5383
5568
|
if (err.message !== "__exit__") {
|
|
5384
|
-
console.log(
|
|
5569
|
+
console.log(chalk8.dim(" Skills search failed: " + (err.message || "unknown error")));
|
|
5385
5570
|
}
|
|
5386
|
-
console.log(
|
|
5571
|
+
console.log(chalk8.dim(" Run ") + chalk8.hex("#83D1EB")("caliber skills") + chalk8.dim(" later to try again.\n"));
|
|
5387
5572
|
}
|
|
5388
5573
|
} else {
|
|
5389
|
-
|
|
5574
|
+
trackInitSkillsSearch(false, 0);
|
|
5575
|
+
console.log(chalk8.dim(" Skipped. Run ") + chalk8.hex("#83D1EB")("caliber skills") + chalk8.dim(" later to browse.\n"));
|
|
5390
5576
|
}
|
|
5391
|
-
console.log(
|
|
5392
|
-
console.log(
|
|
5393
|
-
console.log(
|
|
5577
|
+
console.log(chalk8.bold.green(" Onboarding complete! Your project is ready for AI-assisted development."));
|
|
5578
|
+
console.log(chalk8.dim(" Run ") + chalk8.hex("#83D1EB")("caliber undo") + chalk8.dim(" to revert changes.\n"));
|
|
5579
|
+
console.log(chalk8.bold(" Next steps:\n"));
|
|
5394
5580
|
console.log(` ${title("caliber score")} See your full config breakdown`);
|
|
5395
5581
|
console.log(` ${title("caliber skills")} Discover community skills for your stack`);
|
|
5396
5582
|
console.log(` ${title("caliber undo")} Revert all changes from this run`);
|
|
@@ -5407,9 +5593,9 @@ async function refineLoop(currentSetup, _targetAgent, sessionHistory) {
|
|
|
5407
5593
|
}
|
|
5408
5594
|
const isValid = await classifyRefineIntent(message);
|
|
5409
5595
|
if (!isValid) {
|
|
5410
|
-
console.log(
|
|
5411
|
-
console.log(
|
|
5412
|
-
console.log(
|
|
5596
|
+
console.log(chalk8.dim(" This doesn't look like a config change request."));
|
|
5597
|
+
console.log(chalk8.dim(" Describe what to add, remove, or modify in your configs."));
|
|
5598
|
+
console.log(chalk8.dim(' Type "done" to accept the current setup.\n'));
|
|
5413
5599
|
continue;
|
|
5414
5600
|
}
|
|
5415
5601
|
const refineSpinner = ora2("Refining setup...").start();
|
|
@@ -5430,16 +5616,16 @@ async function refineLoop(currentSetup, _targetAgent, sessionHistory) {
|
|
|
5430
5616
|
});
|
|
5431
5617
|
refineSpinner.succeed("Setup updated");
|
|
5432
5618
|
printSetupSummary(refined);
|
|
5433
|
-
console.log(
|
|
5619
|
+
console.log(chalk8.dim('Type "done" to accept, or describe more changes.'));
|
|
5434
5620
|
} else {
|
|
5435
5621
|
refineSpinner.fail("Refinement failed \u2014 could not parse AI response.");
|
|
5436
|
-
console.log(
|
|
5622
|
+
console.log(chalk8.dim('Try rephrasing your request, or type "done" to keep the current setup.'));
|
|
5437
5623
|
}
|
|
5438
5624
|
}
|
|
5439
5625
|
}
|
|
5440
5626
|
function summarizeSetup(action, setup) {
|
|
5441
5627
|
const descriptions = setup.fileDescriptions;
|
|
5442
|
-
const files = descriptions ? Object.entries(descriptions).map(([
|
|
5628
|
+
const files = descriptions ? Object.entries(descriptions).map(([path24, desc]) => ` ${path24}: ${desc}`).join("\n") : Object.keys(setup).filter((k) => k !== "targetAgent" && k !== "fileDescriptions").join(", ");
|
|
5443
5629
|
return `${action}. Files:
|
|
5444
5630
|
${files}`;
|
|
5445
5631
|
}
|
|
@@ -5493,7 +5679,7 @@ ${JSON.stringify(checkList, null, 2)}`,
|
|
|
5493
5679
|
function promptInput2(question) {
|
|
5494
5680
|
const rl = readline3.createInterface({ input: process.stdin, output: process.stdout });
|
|
5495
5681
|
return new Promise((resolve2) => {
|
|
5496
|
-
rl.question(
|
|
5682
|
+
rl.question(chalk8.cyan(`${question} `), (answer) => {
|
|
5497
5683
|
rl.close();
|
|
5498
5684
|
resolve2(answer.trim());
|
|
5499
5685
|
});
|
|
@@ -5546,26 +5732,26 @@ function printSetupSummary(setup) {
|
|
|
5546
5732
|
const fileDescriptions = setup.fileDescriptions;
|
|
5547
5733
|
const deletions = setup.deletions;
|
|
5548
5734
|
console.log("");
|
|
5549
|
-
console.log(
|
|
5735
|
+
console.log(chalk8.bold(" Proposed changes:\n"));
|
|
5550
5736
|
const getDescription = (filePath) => {
|
|
5551
5737
|
return fileDescriptions?.[filePath];
|
|
5552
5738
|
};
|
|
5553
5739
|
if (claude) {
|
|
5554
5740
|
if (claude.claudeMd) {
|
|
5555
|
-
const icon =
|
|
5741
|
+
const icon = fs22.existsSync("CLAUDE.md") ? chalk8.yellow("~") : chalk8.green("+");
|
|
5556
5742
|
const desc = getDescription("CLAUDE.md");
|
|
5557
|
-
console.log(` ${icon} ${
|
|
5558
|
-
if (desc) console.log(
|
|
5743
|
+
console.log(` ${icon} ${chalk8.bold("CLAUDE.md")}`);
|
|
5744
|
+
if (desc) console.log(chalk8.dim(` ${desc}`));
|
|
5559
5745
|
console.log("");
|
|
5560
5746
|
}
|
|
5561
5747
|
const skills = claude.skills;
|
|
5562
5748
|
if (Array.isArray(skills) && skills.length > 0) {
|
|
5563
5749
|
for (const skill of skills) {
|
|
5564
5750
|
const skillPath = `.claude/skills/${skill.name}/SKILL.md`;
|
|
5565
|
-
const icon =
|
|
5751
|
+
const icon = fs22.existsSync(skillPath) ? chalk8.yellow("~") : chalk8.green("+");
|
|
5566
5752
|
const desc = getDescription(skillPath);
|
|
5567
|
-
console.log(` ${icon} ${
|
|
5568
|
-
console.log(
|
|
5753
|
+
console.log(` ${icon} ${chalk8.bold(skillPath)}`);
|
|
5754
|
+
console.log(chalk8.dim(` ${desc || skill.description || skill.name}`));
|
|
5569
5755
|
console.log("");
|
|
5570
5756
|
}
|
|
5571
5757
|
}
|
|
@@ -5573,40 +5759,40 @@ function printSetupSummary(setup) {
|
|
|
5573
5759
|
const codex = setup.codex;
|
|
5574
5760
|
if (codex) {
|
|
5575
5761
|
if (codex.agentsMd) {
|
|
5576
|
-
const icon =
|
|
5762
|
+
const icon = fs22.existsSync("AGENTS.md") ? chalk8.yellow("~") : chalk8.green("+");
|
|
5577
5763
|
const desc = getDescription("AGENTS.md");
|
|
5578
|
-
console.log(` ${icon} ${
|
|
5579
|
-
if (desc) console.log(
|
|
5764
|
+
console.log(` ${icon} ${chalk8.bold("AGENTS.md")}`);
|
|
5765
|
+
if (desc) console.log(chalk8.dim(` ${desc}`));
|
|
5580
5766
|
console.log("");
|
|
5581
5767
|
}
|
|
5582
5768
|
const codexSkills = codex.skills;
|
|
5583
5769
|
if (Array.isArray(codexSkills) && codexSkills.length > 0) {
|
|
5584
5770
|
for (const skill of codexSkills) {
|
|
5585
5771
|
const skillPath = `.agents/skills/${skill.name}/SKILL.md`;
|
|
5586
|
-
const icon =
|
|
5772
|
+
const icon = fs22.existsSync(skillPath) ? chalk8.yellow("~") : chalk8.green("+");
|
|
5587
5773
|
const desc = getDescription(skillPath);
|
|
5588
|
-
console.log(` ${icon} ${
|
|
5589
|
-
console.log(
|
|
5774
|
+
console.log(` ${icon} ${chalk8.bold(skillPath)}`);
|
|
5775
|
+
console.log(chalk8.dim(` ${desc || skill.description || skill.name}`));
|
|
5590
5776
|
console.log("");
|
|
5591
5777
|
}
|
|
5592
5778
|
}
|
|
5593
5779
|
}
|
|
5594
5780
|
if (cursor) {
|
|
5595
5781
|
if (cursor.cursorrules) {
|
|
5596
|
-
const icon =
|
|
5782
|
+
const icon = fs22.existsSync(".cursorrules") ? chalk8.yellow("~") : chalk8.green("+");
|
|
5597
5783
|
const desc = getDescription(".cursorrules");
|
|
5598
|
-
console.log(` ${icon} ${
|
|
5599
|
-
if (desc) console.log(
|
|
5784
|
+
console.log(` ${icon} ${chalk8.bold(".cursorrules")}`);
|
|
5785
|
+
if (desc) console.log(chalk8.dim(` ${desc}`));
|
|
5600
5786
|
console.log("");
|
|
5601
5787
|
}
|
|
5602
5788
|
const cursorSkills = cursor.skills;
|
|
5603
5789
|
if (Array.isArray(cursorSkills) && cursorSkills.length > 0) {
|
|
5604
5790
|
for (const skill of cursorSkills) {
|
|
5605
5791
|
const skillPath = `.cursor/skills/${skill.name}/SKILL.md`;
|
|
5606
|
-
const icon =
|
|
5792
|
+
const icon = fs22.existsSync(skillPath) ? chalk8.yellow("~") : chalk8.green("+");
|
|
5607
5793
|
const desc = getDescription(skillPath);
|
|
5608
|
-
console.log(` ${icon} ${
|
|
5609
|
-
console.log(
|
|
5794
|
+
console.log(` ${icon} ${chalk8.bold(skillPath)}`);
|
|
5795
|
+
console.log(chalk8.dim(` ${desc || skill.description || skill.name}`));
|
|
5610
5796
|
console.log("");
|
|
5611
5797
|
}
|
|
5612
5798
|
}
|
|
@@ -5614,40 +5800,40 @@ function printSetupSummary(setup) {
|
|
|
5614
5800
|
if (Array.isArray(rules) && rules.length > 0) {
|
|
5615
5801
|
for (const rule of rules) {
|
|
5616
5802
|
const rulePath = `.cursor/rules/${rule.filename}`;
|
|
5617
|
-
const icon =
|
|
5803
|
+
const icon = fs22.existsSync(rulePath) ? chalk8.yellow("~") : chalk8.green("+");
|
|
5618
5804
|
const desc = getDescription(rulePath);
|
|
5619
|
-
console.log(` ${icon} ${
|
|
5805
|
+
console.log(` ${icon} ${chalk8.bold(rulePath)}`);
|
|
5620
5806
|
if (desc) {
|
|
5621
|
-
console.log(
|
|
5807
|
+
console.log(chalk8.dim(` ${desc}`));
|
|
5622
5808
|
} else {
|
|
5623
5809
|
const firstLine = rule.content.split("\n").filter((l) => l.trim() && !l.trim().startsWith("#"))[0];
|
|
5624
|
-
if (firstLine) console.log(
|
|
5810
|
+
if (firstLine) console.log(chalk8.dim(` ${firstLine.trim().slice(0, 80)}`));
|
|
5625
5811
|
}
|
|
5626
5812
|
console.log("");
|
|
5627
5813
|
}
|
|
5628
5814
|
}
|
|
5629
5815
|
}
|
|
5630
|
-
if (!codex && !
|
|
5631
|
-
console.log(` ${
|
|
5632
|
-
console.log(
|
|
5816
|
+
if (!codex && !fs22.existsSync("AGENTS.md")) {
|
|
5817
|
+
console.log(` ${chalk8.green("+")} ${chalk8.bold("AGENTS.md")}`);
|
|
5818
|
+
console.log(chalk8.dim(" Cross-agent coordination file"));
|
|
5633
5819
|
console.log("");
|
|
5634
5820
|
}
|
|
5635
5821
|
if (Array.isArray(deletions) && deletions.length > 0) {
|
|
5636
5822
|
for (const del of deletions) {
|
|
5637
|
-
console.log(` ${
|
|
5638
|
-
console.log(
|
|
5823
|
+
console.log(` ${chalk8.red("-")} ${chalk8.bold(del.filePath)}`);
|
|
5824
|
+
console.log(chalk8.dim(` ${del.reason}`));
|
|
5639
5825
|
console.log("");
|
|
5640
5826
|
}
|
|
5641
5827
|
}
|
|
5642
|
-
console.log(` ${
|
|
5828
|
+
console.log(` ${chalk8.green("+")} ${chalk8.dim("new")} ${chalk8.yellow("~")} ${chalk8.dim("modified")} ${chalk8.red("-")} ${chalk8.dim("removed")}`);
|
|
5643
5829
|
console.log("");
|
|
5644
5830
|
}
|
|
5645
5831
|
function ensurePermissions() {
|
|
5646
5832
|
const settingsPath = ".claude/settings.json";
|
|
5647
5833
|
let settings = {};
|
|
5648
5834
|
try {
|
|
5649
|
-
if (
|
|
5650
|
-
settings = JSON.parse(
|
|
5835
|
+
if (fs22.existsSync(settingsPath)) {
|
|
5836
|
+
settings = JSON.parse(fs22.readFileSync(settingsPath, "utf-8"));
|
|
5651
5837
|
}
|
|
5652
5838
|
} catch {
|
|
5653
5839
|
}
|
|
@@ -5661,12 +5847,12 @@ function ensurePermissions() {
|
|
|
5661
5847
|
"Bash(git *)"
|
|
5662
5848
|
];
|
|
5663
5849
|
settings.permissions = permissions;
|
|
5664
|
-
if (!
|
|
5665
|
-
|
|
5850
|
+
if (!fs22.existsSync(".claude")) fs22.mkdirSync(".claude", { recursive: true });
|
|
5851
|
+
fs22.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
|
|
5666
5852
|
}
|
|
5667
5853
|
|
|
5668
5854
|
// src/commands/undo.ts
|
|
5669
|
-
import
|
|
5855
|
+
import chalk9 from "chalk";
|
|
5670
5856
|
import ora3 from "ora";
|
|
5671
5857
|
function undoCommand() {
|
|
5672
5858
|
const spinner = ora3("Reverting setup...").start();
|
|
@@ -5676,29 +5862,30 @@ function undoCommand() {
|
|
|
5676
5862
|
spinner.info("Nothing to undo.");
|
|
5677
5863
|
return;
|
|
5678
5864
|
}
|
|
5865
|
+
trackUndoExecuted();
|
|
5679
5866
|
spinner.succeed("Setup reverted successfully.\n");
|
|
5680
5867
|
if (restored.length > 0) {
|
|
5681
|
-
console.log(
|
|
5868
|
+
console.log(chalk9.cyan(" Restored from backup:"));
|
|
5682
5869
|
for (const file of restored) {
|
|
5683
|
-
console.log(` ${
|
|
5870
|
+
console.log(` ${chalk9.green("\u21A9")} ${file}`);
|
|
5684
5871
|
}
|
|
5685
5872
|
}
|
|
5686
5873
|
if (removed.length > 0) {
|
|
5687
|
-
console.log(
|
|
5874
|
+
console.log(chalk9.cyan(" Removed:"));
|
|
5688
5875
|
for (const file of removed) {
|
|
5689
|
-
console.log(` ${
|
|
5876
|
+
console.log(` ${chalk9.red("\u2717")} ${file}`);
|
|
5690
5877
|
}
|
|
5691
5878
|
}
|
|
5692
5879
|
console.log("");
|
|
5693
5880
|
} catch (err) {
|
|
5694
|
-
spinner.fail(
|
|
5881
|
+
spinner.fail(chalk9.red(err instanceof Error ? err.message : "Undo failed"));
|
|
5695
5882
|
throw new Error("__exit__");
|
|
5696
5883
|
}
|
|
5697
5884
|
}
|
|
5698
5885
|
|
|
5699
5886
|
// src/commands/status.ts
|
|
5700
|
-
import
|
|
5701
|
-
import
|
|
5887
|
+
import chalk10 from "chalk";
|
|
5888
|
+
import fs23 from "fs";
|
|
5702
5889
|
init_config();
|
|
5703
5890
|
async function statusCommand(options) {
|
|
5704
5891
|
const config = loadConfig();
|
|
@@ -5712,40 +5899,40 @@ async function statusCommand(options) {
|
|
|
5712
5899
|
}, null, 2));
|
|
5713
5900
|
return;
|
|
5714
5901
|
}
|
|
5715
|
-
console.log(
|
|
5902
|
+
console.log(chalk10.bold("\nCaliber Status\n"));
|
|
5716
5903
|
if (config) {
|
|
5717
|
-
console.log(` LLM: ${
|
|
5904
|
+
console.log(` LLM: ${chalk10.green(config.provider)} (${config.model})`);
|
|
5718
5905
|
} else {
|
|
5719
|
-
console.log(` LLM: ${
|
|
5906
|
+
console.log(` LLM: ${chalk10.yellow("Not configured")} \u2014 run ${chalk10.hex("#83D1EB")("caliber config")}`);
|
|
5720
5907
|
}
|
|
5721
5908
|
if (!manifest) {
|
|
5722
|
-
console.log(` Setup: ${
|
|
5723
|
-
console.log(
|
|
5909
|
+
console.log(` Setup: ${chalk10.dim("No setup applied")}`);
|
|
5910
|
+
console.log(chalk10.dim("\n Run ") + chalk10.hex("#83D1EB")("caliber onboard") + chalk10.dim(" to get started.\n"));
|
|
5724
5911
|
return;
|
|
5725
5912
|
}
|
|
5726
|
-
console.log(` Files managed: ${
|
|
5913
|
+
console.log(` Files managed: ${chalk10.cyan(manifest.entries.length.toString())}`);
|
|
5727
5914
|
for (const entry of manifest.entries) {
|
|
5728
|
-
const exists =
|
|
5729
|
-
const icon = exists ?
|
|
5915
|
+
const exists = fs23.existsSync(entry.path);
|
|
5916
|
+
const icon = exists ? chalk10.green("\u2713") : chalk10.red("\u2717");
|
|
5730
5917
|
console.log(` ${icon} ${entry.path} (${entry.action})`);
|
|
5731
5918
|
}
|
|
5732
5919
|
console.log("");
|
|
5733
5920
|
}
|
|
5734
5921
|
|
|
5735
5922
|
// src/commands/regenerate.ts
|
|
5736
|
-
import
|
|
5923
|
+
import chalk11 from "chalk";
|
|
5737
5924
|
import ora4 from "ora";
|
|
5738
5925
|
import select6 from "@inquirer/select";
|
|
5739
5926
|
init_config();
|
|
5740
5927
|
async function regenerateCommand(options) {
|
|
5741
5928
|
const config = loadConfig();
|
|
5742
5929
|
if (!config) {
|
|
5743
|
-
console.log(
|
|
5930
|
+
console.log(chalk11.red("No LLM provider configured. Run ") + chalk11.hex("#83D1EB")("caliber config") + chalk11.red(" first."));
|
|
5744
5931
|
throw new Error("__exit__");
|
|
5745
5932
|
}
|
|
5746
5933
|
const manifest = readManifest();
|
|
5747
5934
|
if (!manifest) {
|
|
5748
|
-
console.log(
|
|
5935
|
+
console.log(chalk11.yellow("No existing setup found. Run ") + chalk11.hex("#83D1EB")("caliber onboard") + chalk11.yellow(" first."));
|
|
5749
5936
|
throw new Error("__exit__");
|
|
5750
5937
|
}
|
|
5751
5938
|
const targetAgent = readState()?.targetAgent ?? ["claude", "cursor"];
|
|
@@ -5756,7 +5943,7 @@ async function regenerateCommand(options) {
|
|
|
5756
5943
|
const baselineScore = computeLocalScore(process.cwd(), targetAgent);
|
|
5757
5944
|
displayScoreSummary(baselineScore);
|
|
5758
5945
|
if (baselineScore.score === 100) {
|
|
5759
|
-
console.log(
|
|
5946
|
+
console.log(chalk11.green(" Your setup is already at 100/100 \u2014 nothing to regenerate.\n"));
|
|
5760
5947
|
return;
|
|
5761
5948
|
}
|
|
5762
5949
|
const genSpinner = ora4("Regenerating setup...").start();
|
|
@@ -5797,18 +5984,18 @@ async function regenerateCommand(options) {
|
|
|
5797
5984
|
const setupFiles = collectSetupFiles(generatedSetup);
|
|
5798
5985
|
const staged = stageFiles(setupFiles, process.cwd());
|
|
5799
5986
|
const totalChanges = staged.newFiles + staged.modifiedFiles;
|
|
5800
|
-
console.log(
|
|
5801
|
-
${
|
|
5987
|
+
console.log(chalk11.dim(`
|
|
5988
|
+
${chalk11.green(`${staged.newFiles} new`)} / ${chalk11.yellow(`${staged.modifiedFiles} modified`)} file${totalChanges !== 1 ? "s" : ""}
|
|
5802
5989
|
`));
|
|
5803
5990
|
if (totalChanges === 0) {
|
|
5804
|
-
console.log(
|
|
5991
|
+
console.log(chalk11.dim(" No changes needed \u2014 your configs are already up to date.\n"));
|
|
5805
5992
|
cleanupStaging();
|
|
5806
5993
|
return;
|
|
5807
5994
|
}
|
|
5808
5995
|
if (options.dryRun) {
|
|
5809
|
-
console.log(
|
|
5996
|
+
console.log(chalk11.yellow("[Dry run] Would write:"));
|
|
5810
5997
|
for (const f of staged.stagedFiles) {
|
|
5811
|
-
console.log(` ${f.isNew ?
|
|
5998
|
+
console.log(` ${f.isNew ? chalk11.green("+") : chalk11.yellow("~")} ${f.relativePath}`);
|
|
5812
5999
|
}
|
|
5813
6000
|
cleanupStaging();
|
|
5814
6001
|
return;
|
|
@@ -5827,7 +6014,7 @@ async function regenerateCommand(options) {
|
|
|
5827
6014
|
});
|
|
5828
6015
|
cleanupStaging();
|
|
5829
6016
|
if (action === "decline") {
|
|
5830
|
-
console.log(
|
|
6017
|
+
console.log(chalk11.dim("Regeneration cancelled. No files were modified."));
|
|
5831
6018
|
return;
|
|
5832
6019
|
}
|
|
5833
6020
|
const writeSpinner = ora4("Writing config files...").start();
|
|
@@ -5835,20 +6022,20 @@ async function regenerateCommand(options) {
|
|
|
5835
6022
|
const result = writeSetup(generatedSetup);
|
|
5836
6023
|
writeSpinner.succeed("Config files written");
|
|
5837
6024
|
for (const file of result.written) {
|
|
5838
|
-
console.log(` ${
|
|
6025
|
+
console.log(` ${chalk11.green("\u2713")} ${file}`);
|
|
5839
6026
|
}
|
|
5840
6027
|
if (result.deleted.length > 0) {
|
|
5841
6028
|
for (const file of result.deleted) {
|
|
5842
|
-
console.log(` ${
|
|
6029
|
+
console.log(` ${chalk11.red("\u2717")} ${file}`);
|
|
5843
6030
|
}
|
|
5844
6031
|
}
|
|
5845
6032
|
if (result.backupDir) {
|
|
5846
|
-
console.log(
|
|
6033
|
+
console.log(chalk11.dim(`
|
|
5847
6034
|
Backups saved to ${result.backupDir}`));
|
|
5848
6035
|
}
|
|
5849
6036
|
} catch (err) {
|
|
5850
6037
|
writeSpinner.fail("Failed to write files");
|
|
5851
|
-
console.error(
|
|
6038
|
+
console.error(chalk11.red(err instanceof Error ? err.message : "Unknown error"));
|
|
5852
6039
|
throw new Error("__exit__");
|
|
5853
6040
|
}
|
|
5854
6041
|
const sha = getCurrentHeadSha();
|
|
@@ -5860,28 +6047,30 @@ async function regenerateCommand(options) {
|
|
|
5860
6047
|
const afterScore = computeLocalScore(process.cwd(), targetAgent);
|
|
5861
6048
|
if (afterScore.score < baselineScore.score) {
|
|
5862
6049
|
console.log("");
|
|
5863
|
-
console.log(
|
|
6050
|
+
console.log(chalk11.yellow(` Score would drop from ${baselineScore.score} to ${afterScore.score} \u2014 reverting changes.`));
|
|
5864
6051
|
try {
|
|
5865
6052
|
const { restored, removed } = undoSetup();
|
|
5866
6053
|
if (restored.length > 0 || removed.length > 0) {
|
|
5867
|
-
console.log(
|
|
6054
|
+
console.log(chalk11.dim(` Reverted ${restored.length + removed.length} file${restored.length + removed.length === 1 ? "" : "s"} from backup.`));
|
|
5868
6055
|
}
|
|
5869
6056
|
} catch {
|
|
5870
6057
|
}
|
|
5871
|
-
console.log(
|
|
6058
|
+
console.log(chalk11.dim(" Run ") + chalk11.hex("#83D1EB")("caliber onboard --force") + chalk11.dim(" to override.\n"));
|
|
5872
6059
|
return;
|
|
5873
6060
|
}
|
|
5874
6061
|
displayScoreDelta(baselineScore, afterScore);
|
|
5875
|
-
|
|
5876
|
-
console.log(
|
|
6062
|
+
trackRegenerateCompleted(action, Date.now());
|
|
6063
|
+
console.log(chalk11.bold.green(" Regeneration complete!"));
|
|
6064
|
+
console.log(chalk11.dim(" Run ") + chalk11.hex("#83D1EB")("caliber undo") + chalk11.dim(" to revert changes.\n"));
|
|
5877
6065
|
}
|
|
5878
6066
|
|
|
5879
6067
|
// src/commands/score.ts
|
|
5880
|
-
import
|
|
6068
|
+
import chalk12 from "chalk";
|
|
5881
6069
|
async function scoreCommand(options) {
|
|
5882
6070
|
const dir = process.cwd();
|
|
5883
6071
|
const target = options.agent ?? readState()?.targetAgent;
|
|
5884
6072
|
const result = computeLocalScore(dir, target);
|
|
6073
|
+
trackScoreComputed(result.score, target);
|
|
5885
6074
|
if (options.json) {
|
|
5886
6075
|
console.log(JSON.stringify(result, null, 2));
|
|
5887
6076
|
return;
|
|
@@ -5891,26 +6080,26 @@ async function scoreCommand(options) {
|
|
|
5891
6080
|
return;
|
|
5892
6081
|
}
|
|
5893
6082
|
displayScore(result);
|
|
5894
|
-
const separator =
|
|
6083
|
+
const separator = chalk12.gray(" " + "\u2500".repeat(53));
|
|
5895
6084
|
console.log(separator);
|
|
5896
6085
|
if (result.score < 40) {
|
|
5897
|
-
console.log(
|
|
6086
|
+
console.log(chalk12.gray(" Run ") + chalk12.hex("#83D1EB")("caliber onboard") + chalk12.gray(" to generate a complete, optimized setup."));
|
|
5898
6087
|
} else if (result.score < 70) {
|
|
5899
|
-
console.log(
|
|
6088
|
+
console.log(chalk12.gray(" Run ") + chalk12.hex("#83D1EB")("caliber onboard") + chalk12.gray(" to improve your setup."));
|
|
5900
6089
|
} else {
|
|
5901
|
-
console.log(
|
|
6090
|
+
console.log(chalk12.green(" Looking good!") + chalk12.gray(" Run ") + chalk12.hex("#83D1EB")("caliber regenerate") + chalk12.gray(" to rebuild from scratch."));
|
|
5902
6091
|
}
|
|
5903
6092
|
console.log("");
|
|
5904
6093
|
}
|
|
5905
6094
|
|
|
5906
6095
|
// src/commands/refresh.ts
|
|
5907
|
-
import
|
|
5908
|
-
import
|
|
5909
|
-
import
|
|
6096
|
+
import fs25 from "fs";
|
|
6097
|
+
import path19 from "path";
|
|
6098
|
+
import chalk13 from "chalk";
|
|
5910
6099
|
import ora5 from "ora";
|
|
5911
6100
|
|
|
5912
6101
|
// src/lib/git-diff.ts
|
|
5913
|
-
import { execSync as
|
|
6102
|
+
import { execSync as execSync9 } from "child_process";
|
|
5914
6103
|
var MAX_DIFF_BYTES = 1e5;
|
|
5915
6104
|
var DOC_PATTERNS = [
|
|
5916
6105
|
"CLAUDE.md",
|
|
@@ -5924,7 +6113,7 @@ function excludeArgs() {
|
|
|
5924
6113
|
}
|
|
5925
6114
|
function safeExec(cmd) {
|
|
5926
6115
|
try {
|
|
5927
|
-
return
|
|
6116
|
+
return execSync9(cmd, {
|
|
5928
6117
|
encoding: "utf-8",
|
|
5929
6118
|
stdio: ["pipe", "pipe", "pipe"],
|
|
5930
6119
|
maxBuffer: 10 * 1024 * 1024
|
|
@@ -5982,37 +6171,37 @@ function collectDiff(lastSha) {
|
|
|
5982
6171
|
}
|
|
5983
6172
|
|
|
5984
6173
|
// src/writers/refresh.ts
|
|
5985
|
-
import
|
|
5986
|
-
import
|
|
6174
|
+
import fs24 from "fs";
|
|
6175
|
+
import path18 from "path";
|
|
5987
6176
|
function writeRefreshDocs(docs) {
|
|
5988
6177
|
const written = [];
|
|
5989
6178
|
if (docs.claudeMd) {
|
|
5990
|
-
|
|
6179
|
+
fs24.writeFileSync("CLAUDE.md", docs.claudeMd);
|
|
5991
6180
|
written.push("CLAUDE.md");
|
|
5992
6181
|
}
|
|
5993
6182
|
if (docs.readmeMd) {
|
|
5994
|
-
|
|
6183
|
+
fs24.writeFileSync("README.md", docs.readmeMd);
|
|
5995
6184
|
written.push("README.md");
|
|
5996
6185
|
}
|
|
5997
6186
|
if (docs.cursorrules) {
|
|
5998
|
-
|
|
6187
|
+
fs24.writeFileSync(".cursorrules", docs.cursorrules);
|
|
5999
6188
|
written.push(".cursorrules");
|
|
6000
6189
|
}
|
|
6001
6190
|
if (docs.cursorRules) {
|
|
6002
|
-
const rulesDir =
|
|
6003
|
-
if (!
|
|
6191
|
+
const rulesDir = path18.join(".cursor", "rules");
|
|
6192
|
+
if (!fs24.existsSync(rulesDir)) fs24.mkdirSync(rulesDir, { recursive: true });
|
|
6004
6193
|
for (const rule of docs.cursorRules) {
|
|
6005
|
-
const filePath =
|
|
6006
|
-
|
|
6194
|
+
const filePath = path18.join(rulesDir, rule.filename);
|
|
6195
|
+
fs24.writeFileSync(filePath, rule.content);
|
|
6007
6196
|
written.push(filePath);
|
|
6008
6197
|
}
|
|
6009
6198
|
}
|
|
6010
6199
|
if (docs.claudeSkills) {
|
|
6011
|
-
const skillsDir =
|
|
6012
|
-
if (!
|
|
6200
|
+
const skillsDir = path18.join(".claude", "skills");
|
|
6201
|
+
if (!fs24.existsSync(skillsDir)) fs24.mkdirSync(skillsDir, { recursive: true });
|
|
6013
6202
|
for (const skill of docs.claudeSkills) {
|
|
6014
|
-
const filePath =
|
|
6015
|
-
|
|
6203
|
+
const filePath = path18.join(skillsDir, skill.filename);
|
|
6204
|
+
fs24.writeFileSync(filePath, skill.content);
|
|
6016
6205
|
written.push(filePath);
|
|
6017
6206
|
}
|
|
6018
6207
|
}
|
|
@@ -6091,11 +6280,11 @@ function log(quiet, ...args) {
|
|
|
6091
6280
|
function discoverGitRepos(parentDir) {
|
|
6092
6281
|
const repos = [];
|
|
6093
6282
|
try {
|
|
6094
|
-
const entries =
|
|
6283
|
+
const entries = fs25.readdirSync(parentDir, { withFileTypes: true });
|
|
6095
6284
|
for (const entry of entries) {
|
|
6096
6285
|
if (!entry.isDirectory() || entry.name.startsWith(".")) continue;
|
|
6097
|
-
const childPath =
|
|
6098
|
-
if (
|
|
6286
|
+
const childPath = path19.join(parentDir, entry.name);
|
|
6287
|
+
if (fs25.existsSync(path19.join(childPath, ".git"))) {
|
|
6099
6288
|
repos.push(childPath);
|
|
6100
6289
|
}
|
|
6101
6290
|
}
|
|
@@ -6105,7 +6294,7 @@ function discoverGitRepos(parentDir) {
|
|
|
6105
6294
|
}
|
|
6106
6295
|
async function refreshSingleRepo(repoDir, options) {
|
|
6107
6296
|
const quiet = !!options.quiet;
|
|
6108
|
-
const prefix = options.label ? `${
|
|
6297
|
+
const prefix = options.label ? `${chalk13.bold(options.label)} ` : "";
|
|
6109
6298
|
const state = readState();
|
|
6110
6299
|
const lastSha = state?.lastRefreshSha ?? null;
|
|
6111
6300
|
const diff = collectDiff(lastSha);
|
|
@@ -6114,7 +6303,7 @@ async function refreshSingleRepo(repoDir, options) {
|
|
|
6114
6303
|
if (currentSha) {
|
|
6115
6304
|
writeState({ lastRefreshSha: currentSha, lastRefreshTimestamp: (/* @__PURE__ */ new Date()).toISOString() });
|
|
6116
6305
|
}
|
|
6117
|
-
log(quiet,
|
|
6306
|
+
log(quiet, chalk13.dim(`${prefix}No changes since last refresh.`));
|
|
6118
6307
|
return;
|
|
6119
6308
|
}
|
|
6120
6309
|
const spinner = quiet ? null : ora5(`${prefix}Analyzing changes...`).start();
|
|
@@ -6146,21 +6335,22 @@ async function refreshSingleRepo(repoDir, options) {
|
|
|
6146
6335
|
if (options.dryRun) {
|
|
6147
6336
|
spinner?.info(`${prefix}Dry run \u2014 would update:`);
|
|
6148
6337
|
for (const doc of response.docsUpdated) {
|
|
6149
|
-
console.log(` ${
|
|
6338
|
+
console.log(` ${chalk13.yellow("~")} ${doc}`);
|
|
6150
6339
|
}
|
|
6151
6340
|
if (response.changesSummary) {
|
|
6152
|
-
console.log(
|
|
6341
|
+
console.log(chalk13.dim(`
|
|
6153
6342
|
${response.changesSummary}`));
|
|
6154
6343
|
}
|
|
6155
6344
|
return;
|
|
6156
6345
|
}
|
|
6157
6346
|
const written = writeRefreshDocs(response.updatedDocs);
|
|
6347
|
+
trackRefreshCompleted(written.length, Date.now());
|
|
6158
6348
|
spinner?.succeed(`${prefix}Updated ${written.length} doc${written.length === 1 ? "" : "s"}`);
|
|
6159
6349
|
for (const file of written) {
|
|
6160
|
-
log(quiet, ` ${
|
|
6350
|
+
log(quiet, ` ${chalk13.green("\u2713")} ${file}`);
|
|
6161
6351
|
}
|
|
6162
6352
|
if (response.changesSummary) {
|
|
6163
|
-
log(quiet,
|
|
6353
|
+
log(quiet, chalk13.dim(`
|
|
6164
6354
|
${response.changesSummary}`));
|
|
6165
6355
|
}
|
|
6166
6356
|
if (currentSha) {
|
|
@@ -6173,7 +6363,7 @@ async function refreshCommand(options) {
|
|
|
6173
6363
|
const config = loadConfig();
|
|
6174
6364
|
if (!config) {
|
|
6175
6365
|
if (quiet) return;
|
|
6176
|
-
console.log(
|
|
6366
|
+
console.log(chalk13.red("No LLM provider configured. Run ") + chalk13.hex("#83D1EB")("caliber config") + chalk13.red(" (e.g. choose Cursor) or set an API key."));
|
|
6177
6367
|
throw new Error("__exit__");
|
|
6178
6368
|
}
|
|
6179
6369
|
await validateModel({ fast: true });
|
|
@@ -6184,20 +6374,20 @@ async function refreshCommand(options) {
|
|
|
6184
6374
|
const repos = discoverGitRepos(process.cwd());
|
|
6185
6375
|
if (repos.length === 0) {
|
|
6186
6376
|
if (quiet) return;
|
|
6187
|
-
console.log(
|
|
6377
|
+
console.log(chalk13.red("Not inside a git repository and no git repos found in child directories."));
|
|
6188
6378
|
throw new Error("__exit__");
|
|
6189
6379
|
}
|
|
6190
|
-
log(quiet,
|
|
6380
|
+
log(quiet, chalk13.dim(`Found ${repos.length} git repo${repos.length === 1 ? "" : "s"}
|
|
6191
6381
|
`));
|
|
6192
6382
|
const originalDir = process.cwd();
|
|
6193
6383
|
for (const repo of repos) {
|
|
6194
|
-
const repoName =
|
|
6384
|
+
const repoName = path19.basename(repo);
|
|
6195
6385
|
try {
|
|
6196
6386
|
process.chdir(repo);
|
|
6197
6387
|
await refreshSingleRepo(repo, { ...options, label: repoName });
|
|
6198
6388
|
} catch (err) {
|
|
6199
6389
|
if (err instanceof Error && err.message === "__exit__") continue;
|
|
6200
|
-
log(quiet,
|
|
6390
|
+
log(quiet, chalk13.yellow(`${repoName}: refresh failed \u2014 ${err instanceof Error ? err.message : "unknown error"}`));
|
|
6201
6391
|
}
|
|
6202
6392
|
}
|
|
6203
6393
|
process.chdir(originalDir);
|
|
@@ -6205,13 +6395,13 @@ async function refreshCommand(options) {
|
|
|
6205
6395
|
if (err instanceof Error && err.message === "__exit__") throw err;
|
|
6206
6396
|
if (quiet) return;
|
|
6207
6397
|
const msg = err instanceof Error ? err.message : "Unknown error";
|
|
6208
|
-
console.log(
|
|
6398
|
+
console.log(chalk13.red(`Refresh failed: ${msg}`));
|
|
6209
6399
|
throw new Error("__exit__");
|
|
6210
6400
|
}
|
|
6211
6401
|
}
|
|
6212
6402
|
|
|
6213
6403
|
// src/commands/hooks.ts
|
|
6214
|
-
import
|
|
6404
|
+
import chalk14 from "chalk";
|
|
6215
6405
|
var HOOKS = [
|
|
6216
6406
|
{
|
|
6217
6407
|
id: "session-end",
|
|
@@ -6231,13 +6421,13 @@ var HOOKS = [
|
|
|
6231
6421
|
}
|
|
6232
6422
|
];
|
|
6233
6423
|
function printStatus() {
|
|
6234
|
-
console.log(
|
|
6424
|
+
console.log(chalk14.bold("\n Hooks\n"));
|
|
6235
6425
|
for (const hook of HOOKS) {
|
|
6236
6426
|
const installed = hook.isInstalled();
|
|
6237
|
-
const icon = installed ?
|
|
6238
|
-
const state = installed ?
|
|
6427
|
+
const icon = installed ? chalk14.green("\u2713") : chalk14.dim("\u2717");
|
|
6428
|
+
const state = installed ? chalk14.green("enabled") : chalk14.dim("disabled");
|
|
6239
6429
|
console.log(` ${icon} ${hook.label.padEnd(26)} ${state}`);
|
|
6240
|
-
console.log(
|
|
6430
|
+
console.log(chalk14.dim(` ${hook.description}`));
|
|
6241
6431
|
}
|
|
6242
6432
|
console.log("");
|
|
6243
6433
|
}
|
|
@@ -6246,9 +6436,9 @@ async function hooksCommand(options) {
|
|
|
6246
6436
|
for (const hook of HOOKS) {
|
|
6247
6437
|
const result = hook.install();
|
|
6248
6438
|
if (result.alreadyInstalled) {
|
|
6249
|
-
console.log(
|
|
6439
|
+
console.log(chalk14.dim(` ${hook.label} already enabled.`));
|
|
6250
6440
|
} else {
|
|
6251
|
-
console.log(
|
|
6441
|
+
console.log(chalk14.green(" \u2713") + ` ${hook.label} enabled`);
|
|
6252
6442
|
}
|
|
6253
6443
|
}
|
|
6254
6444
|
return;
|
|
@@ -6257,9 +6447,9 @@ async function hooksCommand(options) {
|
|
|
6257
6447
|
for (const hook of HOOKS) {
|
|
6258
6448
|
const result = hook.remove();
|
|
6259
6449
|
if (result.notFound) {
|
|
6260
|
-
console.log(
|
|
6450
|
+
console.log(chalk14.dim(` ${hook.label} already disabled.`));
|
|
6261
6451
|
} else {
|
|
6262
|
-
console.log(
|
|
6452
|
+
console.log(chalk14.green(" \u2713") + ` ${hook.label} removed`);
|
|
6263
6453
|
}
|
|
6264
6454
|
}
|
|
6265
6455
|
return;
|
|
@@ -6274,18 +6464,18 @@ async function hooksCommand(options) {
|
|
|
6274
6464
|
const states = HOOKS.map((h) => h.isInstalled());
|
|
6275
6465
|
function render() {
|
|
6276
6466
|
const lines = [];
|
|
6277
|
-
lines.push(
|
|
6467
|
+
lines.push(chalk14.bold(" Hooks"));
|
|
6278
6468
|
lines.push("");
|
|
6279
6469
|
for (let i = 0; i < HOOKS.length; i++) {
|
|
6280
6470
|
const hook = HOOKS[i];
|
|
6281
6471
|
const enabled = states[i];
|
|
6282
|
-
const toggle = enabled ?
|
|
6283
|
-
const ptr = i === cursor ?
|
|
6472
|
+
const toggle = enabled ? chalk14.green("[on] ") : chalk14.dim("[off]");
|
|
6473
|
+
const ptr = i === cursor ? chalk14.cyan(">") : " ";
|
|
6284
6474
|
lines.push(` ${ptr} ${toggle} ${hook.label}`);
|
|
6285
|
-
lines.push(
|
|
6475
|
+
lines.push(chalk14.dim(` ${hook.description}`));
|
|
6286
6476
|
}
|
|
6287
6477
|
lines.push("");
|
|
6288
|
-
lines.push(
|
|
6478
|
+
lines.push(chalk14.dim(" \u2191\u2193 navigate \u23B5 toggle a all on n all off \u23CE apply q cancel"));
|
|
6289
6479
|
return lines.join("\n");
|
|
6290
6480
|
}
|
|
6291
6481
|
function draw(initial) {
|
|
@@ -6316,16 +6506,16 @@ async function hooksCommand(options) {
|
|
|
6316
6506
|
const wantEnabled = states[i];
|
|
6317
6507
|
if (wantEnabled && !wasInstalled) {
|
|
6318
6508
|
hook.install();
|
|
6319
|
-
console.log(
|
|
6509
|
+
console.log(chalk14.green(" \u2713") + ` ${hook.label} enabled`);
|
|
6320
6510
|
changed++;
|
|
6321
6511
|
} else if (!wantEnabled && wasInstalled) {
|
|
6322
6512
|
hook.remove();
|
|
6323
|
-
console.log(
|
|
6513
|
+
console.log(chalk14.green(" \u2713") + ` ${hook.label} disabled`);
|
|
6324
6514
|
changed++;
|
|
6325
6515
|
}
|
|
6326
6516
|
}
|
|
6327
6517
|
if (changed === 0) {
|
|
6328
|
-
console.log(
|
|
6518
|
+
console.log(chalk14.dim(" No changes."));
|
|
6329
6519
|
}
|
|
6330
6520
|
console.log("");
|
|
6331
6521
|
}
|
|
@@ -6361,7 +6551,7 @@ async function hooksCommand(options) {
|
|
|
6361
6551
|
case "\x1B":
|
|
6362
6552
|
case "":
|
|
6363
6553
|
cleanup();
|
|
6364
|
-
console.log(
|
|
6554
|
+
console.log(chalk14.dim("\n Cancelled.\n"));
|
|
6365
6555
|
resolve2();
|
|
6366
6556
|
break;
|
|
6367
6557
|
}
|
|
@@ -6372,48 +6562,50 @@ async function hooksCommand(options) {
|
|
|
6372
6562
|
|
|
6373
6563
|
// src/commands/config.ts
|
|
6374
6564
|
init_config();
|
|
6375
|
-
import
|
|
6565
|
+
import chalk15 from "chalk";
|
|
6376
6566
|
async function configCommand() {
|
|
6377
6567
|
const existing = loadConfig();
|
|
6378
6568
|
if (existing) {
|
|
6379
6569
|
const displayModel = existing.model === "default" && existing.provider === "claude-cli" ? process.env.ANTHROPIC_MODEL || "default (inherited from Claude Code)" : existing.model;
|
|
6380
6570
|
const fastModel = getFastModel();
|
|
6381
|
-
console.log(
|
|
6382
|
-
console.log(` Provider: ${
|
|
6383
|
-
console.log(` Model: ${
|
|
6571
|
+
console.log(chalk15.bold("\nCurrent Configuration\n"));
|
|
6572
|
+
console.log(` Provider: ${chalk15.cyan(existing.provider)}`);
|
|
6573
|
+
console.log(` Model: ${chalk15.cyan(displayModel)}`);
|
|
6384
6574
|
if (fastModel) {
|
|
6385
|
-
console.log(` Scan: ${
|
|
6575
|
+
console.log(` Scan: ${chalk15.cyan(fastModel)}`);
|
|
6386
6576
|
}
|
|
6387
6577
|
if (existing.apiKey) {
|
|
6388
6578
|
const masked = existing.apiKey.slice(0, 8) + "..." + existing.apiKey.slice(-4);
|
|
6389
|
-
console.log(` API Key: ${
|
|
6579
|
+
console.log(` API Key: ${chalk15.dim(masked)}`);
|
|
6390
6580
|
}
|
|
6391
6581
|
if (existing.provider === "cursor") {
|
|
6392
|
-
console.log(` Seat: ${
|
|
6582
|
+
console.log(` Seat: ${chalk15.dim("Cursor (agent acp)")}`);
|
|
6393
6583
|
}
|
|
6394
6584
|
if (existing.provider === "claude-cli") {
|
|
6395
|
-
console.log(` Seat: ${
|
|
6585
|
+
console.log(` Seat: ${chalk15.dim("Claude Code (claude -p)")}`);
|
|
6396
6586
|
}
|
|
6397
6587
|
if (existing.baseUrl) {
|
|
6398
|
-
console.log(` Base URL: ${
|
|
6588
|
+
console.log(` Base URL: ${chalk15.dim(existing.baseUrl)}`);
|
|
6399
6589
|
}
|
|
6400
6590
|
if (existing.vertexProjectId) {
|
|
6401
|
-
console.log(` Vertex Project: ${
|
|
6402
|
-
console.log(` Vertex Region: ${
|
|
6591
|
+
console.log(` Vertex Project: ${chalk15.dim(existing.vertexProjectId)}`);
|
|
6592
|
+
console.log(` Vertex Region: ${chalk15.dim(existing.vertexRegion || "us-east5")}`);
|
|
6403
6593
|
}
|
|
6404
|
-
console.log(` Source: ${
|
|
6594
|
+
console.log(` Source: ${chalk15.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())}`);
|
|
6405
6595
|
console.log("");
|
|
6406
6596
|
}
|
|
6407
6597
|
await runInteractiveProviderSetup();
|
|
6408
|
-
|
|
6409
|
-
|
|
6598
|
+
const updated = loadConfig();
|
|
6599
|
+
if (updated) trackConfigProviderSet(updated.provider);
|
|
6600
|
+
console.log(chalk15.green("\n\u2713 Configuration saved"));
|
|
6601
|
+
console.log(chalk15.dim(` ${getConfigFilePath()}
|
|
6410
6602
|
`));
|
|
6411
|
-
console.log(
|
|
6412
|
-
console.log(
|
|
6603
|
+
console.log(chalk15.dim(" You can also set environment variables instead:"));
|
|
6604
|
+
console.log(chalk15.dim(" ANTHROPIC_API_KEY, OPENAI_API_KEY, VERTEX_PROJECT_ID, CALIBER_USE_CURSOR_SEAT=1, or CALIBER_USE_CLAUDE_CLI=1\n"));
|
|
6413
6605
|
}
|
|
6414
6606
|
|
|
6415
6607
|
// src/commands/learn.ts
|
|
6416
|
-
import
|
|
6608
|
+
import chalk16 from "chalk";
|
|
6417
6609
|
|
|
6418
6610
|
// src/learner/stdin.ts
|
|
6419
6611
|
var STDIN_TIMEOUT_MS = 5e3;
|
|
@@ -6444,8 +6636,8 @@ function readStdin() {
|
|
|
6444
6636
|
|
|
6445
6637
|
// src/learner/storage.ts
|
|
6446
6638
|
init_constants();
|
|
6447
|
-
import
|
|
6448
|
-
import
|
|
6639
|
+
import fs26 from "fs";
|
|
6640
|
+
import path20 from "path";
|
|
6449
6641
|
var MAX_RESPONSE_LENGTH = 2e3;
|
|
6450
6642
|
var DEFAULT_STATE = {
|
|
6451
6643
|
sessionId: null,
|
|
@@ -6453,15 +6645,15 @@ var DEFAULT_STATE = {
|
|
|
6453
6645
|
lastAnalysisTimestamp: null
|
|
6454
6646
|
};
|
|
6455
6647
|
function ensureLearningDir() {
|
|
6456
|
-
if (!
|
|
6457
|
-
|
|
6648
|
+
if (!fs26.existsSync(LEARNING_DIR)) {
|
|
6649
|
+
fs26.mkdirSync(LEARNING_DIR, { recursive: true });
|
|
6458
6650
|
}
|
|
6459
6651
|
}
|
|
6460
6652
|
function sessionFilePath() {
|
|
6461
|
-
return
|
|
6653
|
+
return path20.join(LEARNING_DIR, LEARNING_SESSION_FILE);
|
|
6462
6654
|
}
|
|
6463
6655
|
function stateFilePath() {
|
|
6464
|
-
return
|
|
6656
|
+
return path20.join(LEARNING_DIR, LEARNING_STATE_FILE);
|
|
6465
6657
|
}
|
|
6466
6658
|
function truncateResponse(response) {
|
|
6467
6659
|
const str = JSON.stringify(response);
|
|
@@ -6472,50 +6664,50 @@ function appendEvent(event) {
|
|
|
6472
6664
|
ensureLearningDir();
|
|
6473
6665
|
const truncated = { ...event, tool_response: truncateResponse(event.tool_response) };
|
|
6474
6666
|
const filePath = sessionFilePath();
|
|
6475
|
-
|
|
6667
|
+
fs26.appendFileSync(filePath, JSON.stringify(truncated) + "\n");
|
|
6476
6668
|
const count = getEventCount();
|
|
6477
6669
|
if (count > LEARNING_MAX_EVENTS) {
|
|
6478
|
-
const lines =
|
|
6670
|
+
const lines = fs26.readFileSync(filePath, "utf-8").split("\n").filter(Boolean);
|
|
6479
6671
|
const kept = lines.slice(lines.length - LEARNING_MAX_EVENTS);
|
|
6480
|
-
|
|
6672
|
+
fs26.writeFileSync(filePath, kept.join("\n") + "\n");
|
|
6481
6673
|
}
|
|
6482
6674
|
}
|
|
6483
6675
|
function readAllEvents() {
|
|
6484
6676
|
const filePath = sessionFilePath();
|
|
6485
|
-
if (!
|
|
6486
|
-
const lines =
|
|
6677
|
+
if (!fs26.existsSync(filePath)) return [];
|
|
6678
|
+
const lines = fs26.readFileSync(filePath, "utf-8").split("\n").filter(Boolean);
|
|
6487
6679
|
return lines.map((line) => JSON.parse(line));
|
|
6488
6680
|
}
|
|
6489
6681
|
function getEventCount() {
|
|
6490
6682
|
const filePath = sessionFilePath();
|
|
6491
|
-
if (!
|
|
6492
|
-
const content =
|
|
6683
|
+
if (!fs26.existsSync(filePath)) return 0;
|
|
6684
|
+
const content = fs26.readFileSync(filePath, "utf-8");
|
|
6493
6685
|
return content.split("\n").filter(Boolean).length;
|
|
6494
6686
|
}
|
|
6495
6687
|
function clearSession() {
|
|
6496
6688
|
const filePath = sessionFilePath();
|
|
6497
|
-
if (
|
|
6689
|
+
if (fs26.existsSync(filePath)) fs26.unlinkSync(filePath);
|
|
6498
6690
|
}
|
|
6499
6691
|
function readState2() {
|
|
6500
6692
|
const filePath = stateFilePath();
|
|
6501
|
-
if (!
|
|
6693
|
+
if (!fs26.existsSync(filePath)) return { ...DEFAULT_STATE };
|
|
6502
6694
|
try {
|
|
6503
|
-
return JSON.parse(
|
|
6695
|
+
return JSON.parse(fs26.readFileSync(filePath, "utf-8"));
|
|
6504
6696
|
} catch {
|
|
6505
6697
|
return { ...DEFAULT_STATE };
|
|
6506
6698
|
}
|
|
6507
6699
|
}
|
|
6508
6700
|
function writeState2(state) {
|
|
6509
6701
|
ensureLearningDir();
|
|
6510
|
-
|
|
6702
|
+
fs26.writeFileSync(stateFilePath(), JSON.stringify(state, null, 2));
|
|
6511
6703
|
}
|
|
6512
6704
|
function resetState() {
|
|
6513
6705
|
writeState2({ ...DEFAULT_STATE });
|
|
6514
6706
|
}
|
|
6515
6707
|
|
|
6516
6708
|
// src/learner/writer.ts
|
|
6517
|
-
import
|
|
6518
|
-
import
|
|
6709
|
+
import fs27 from "fs";
|
|
6710
|
+
import path21 from "path";
|
|
6519
6711
|
var LEARNED_START = "<!-- caliber:learned -->";
|
|
6520
6712
|
var LEARNED_END = "<!-- /caliber:learned -->";
|
|
6521
6713
|
function writeLearnedContent(update) {
|
|
@@ -6535,8 +6727,8 @@ function writeLearnedContent(update) {
|
|
|
6535
6727
|
function writeLearnedSection(content) {
|
|
6536
6728
|
const claudeMdPath = "CLAUDE.md";
|
|
6537
6729
|
let existing = "";
|
|
6538
|
-
if (
|
|
6539
|
-
existing =
|
|
6730
|
+
if (fs27.existsSync(claudeMdPath)) {
|
|
6731
|
+
existing = fs27.readFileSync(claudeMdPath, "utf-8");
|
|
6540
6732
|
}
|
|
6541
6733
|
const section = `${LEARNED_START}
|
|
6542
6734
|
${content}
|
|
@@ -6550,15 +6742,15 @@ ${LEARNED_END}`;
|
|
|
6550
6742
|
const separator = existing.endsWith("\n") || existing === "" ? "" : "\n";
|
|
6551
6743
|
updated = existing + separator + "\n" + section + "\n";
|
|
6552
6744
|
}
|
|
6553
|
-
|
|
6745
|
+
fs27.writeFileSync(claudeMdPath, updated);
|
|
6554
6746
|
}
|
|
6555
6747
|
function writeLearnedSkill(skill) {
|
|
6556
|
-
const skillDir =
|
|
6557
|
-
if (!
|
|
6558
|
-
const skillPath =
|
|
6559
|
-
if (!skill.isNew &&
|
|
6560
|
-
const existing =
|
|
6561
|
-
|
|
6748
|
+
const skillDir = path21.join(".claude", "skills", skill.name);
|
|
6749
|
+
if (!fs27.existsSync(skillDir)) fs27.mkdirSync(skillDir, { recursive: true });
|
|
6750
|
+
const skillPath = path21.join(skillDir, "SKILL.md");
|
|
6751
|
+
if (!skill.isNew && fs27.existsSync(skillPath)) {
|
|
6752
|
+
const existing = fs27.readFileSync(skillPath, "utf-8");
|
|
6753
|
+
fs27.writeFileSync(skillPath, existing.trimEnd() + "\n\n" + skill.content);
|
|
6562
6754
|
} else {
|
|
6563
6755
|
const frontmatter = [
|
|
6564
6756
|
"---",
|
|
@@ -6567,14 +6759,14 @@ function writeLearnedSkill(skill) {
|
|
|
6567
6759
|
"---",
|
|
6568
6760
|
""
|
|
6569
6761
|
].join("\n");
|
|
6570
|
-
|
|
6762
|
+
fs27.writeFileSync(skillPath, frontmatter + skill.content);
|
|
6571
6763
|
}
|
|
6572
6764
|
return skillPath;
|
|
6573
6765
|
}
|
|
6574
6766
|
function readLearnedSection() {
|
|
6575
6767
|
const claudeMdPath = "CLAUDE.md";
|
|
6576
|
-
if (!
|
|
6577
|
-
const content =
|
|
6768
|
+
if (!fs27.existsSync(claudeMdPath)) return null;
|
|
6769
|
+
const content = fs27.readFileSync(claudeMdPath, "utf-8");
|
|
6578
6770
|
const startIdx = content.indexOf(LEARNED_START);
|
|
6579
6771
|
const endIdx = content.indexOf(LEARNED_END);
|
|
6580
6772
|
if (startIdx === -1 || endIdx === -1) return null;
|
|
@@ -6719,57 +6911,98 @@ async function learnFinalizeCommand() {
|
|
|
6719
6911
|
async function learnInstallCommand() {
|
|
6720
6912
|
const result = installLearningHooks();
|
|
6721
6913
|
if (result.alreadyInstalled) {
|
|
6722
|
-
console.log(
|
|
6914
|
+
console.log(chalk16.dim("Learning hooks already installed."));
|
|
6723
6915
|
return;
|
|
6724
6916
|
}
|
|
6725
|
-
console.log(
|
|
6726
|
-
console.log(
|
|
6727
|
-
console.log(
|
|
6917
|
+
console.log(chalk16.green("\u2713") + " Learning hooks installed in .claude/settings.json");
|
|
6918
|
+
console.log(chalk16.dim(" PostToolUse, PostToolUseFailure, and SessionEnd hooks active."));
|
|
6919
|
+
console.log(chalk16.dim(" Session learnings will be written to CLAUDE.md and skills."));
|
|
6728
6920
|
}
|
|
6729
6921
|
async function learnRemoveCommand() {
|
|
6730
6922
|
const result = removeLearningHooks();
|
|
6731
6923
|
if (result.notFound) {
|
|
6732
|
-
console.log(
|
|
6924
|
+
console.log(chalk16.dim("Learning hooks not found."));
|
|
6733
6925
|
return;
|
|
6734
6926
|
}
|
|
6735
|
-
console.log(
|
|
6927
|
+
console.log(chalk16.green("\u2713") + " Learning hooks removed from .claude/settings.json");
|
|
6736
6928
|
}
|
|
6737
6929
|
async function learnStatusCommand() {
|
|
6738
6930
|
const installed = areLearningHooksInstalled();
|
|
6739
6931
|
const state = readState2();
|
|
6740
6932
|
const eventCount = getEventCount();
|
|
6741
|
-
console.log(
|
|
6933
|
+
console.log(chalk16.bold("Session Learning Status"));
|
|
6742
6934
|
console.log();
|
|
6743
6935
|
if (installed) {
|
|
6744
|
-
console.log(
|
|
6936
|
+
console.log(chalk16.green("\u2713") + " Learning hooks are " + chalk16.green("installed"));
|
|
6745
6937
|
} else {
|
|
6746
|
-
console.log(
|
|
6747
|
-
console.log(
|
|
6938
|
+
console.log(chalk16.dim("\u2717") + " Learning hooks are " + chalk16.yellow("not installed"));
|
|
6939
|
+
console.log(chalk16.dim(" Run `caliber learn install` to enable session learning."));
|
|
6748
6940
|
}
|
|
6749
6941
|
console.log();
|
|
6750
|
-
console.log(`Events recorded: ${
|
|
6751
|
-
console.log(`Total this session: ${
|
|
6942
|
+
console.log(`Events recorded: ${chalk16.cyan(String(eventCount))}`);
|
|
6943
|
+
console.log(`Total this session: ${chalk16.cyan(String(state.eventCount))}`);
|
|
6752
6944
|
if (state.lastAnalysisTimestamp) {
|
|
6753
|
-
console.log(`Last analysis: ${
|
|
6945
|
+
console.log(`Last analysis: ${chalk16.cyan(state.lastAnalysisTimestamp)}`);
|
|
6754
6946
|
} else {
|
|
6755
|
-
console.log(`Last analysis: ${
|
|
6947
|
+
console.log(`Last analysis: ${chalk16.dim("none")}`);
|
|
6756
6948
|
}
|
|
6757
6949
|
const learnedSection = readLearnedSection();
|
|
6758
6950
|
if (learnedSection) {
|
|
6759
6951
|
const lineCount = learnedSection.split("\n").filter(Boolean).length;
|
|
6760
6952
|
console.log(`
|
|
6761
|
-
Learned items in CLAUDE.md: ${
|
|
6953
|
+
Learned items in CLAUDE.md: ${chalk16.cyan(String(lineCount))}`);
|
|
6762
6954
|
}
|
|
6763
6955
|
}
|
|
6764
6956
|
|
|
6765
6957
|
// src/cli.ts
|
|
6766
|
-
var __dirname =
|
|
6958
|
+
var __dirname = path22.dirname(fileURLToPath(import.meta.url));
|
|
6767
6959
|
var pkg = JSON.parse(
|
|
6768
|
-
|
|
6960
|
+
fs28.readFileSync(path22.resolve(__dirname, "..", "package.json"), "utf-8")
|
|
6769
6961
|
);
|
|
6770
6962
|
var program = new Command();
|
|
6771
6963
|
var displayVersion = process.env.CALIBER_LOCAL ? `${pkg.version}-local` : pkg.version;
|
|
6772
|
-
program.name(process.env.CALIBER_LOCAL ? "caloc" : "caliber").description("Configure your coding agent environment").version(displayVersion);
|
|
6964
|
+
program.name(process.env.CALIBER_LOCAL ? "caloc" : "caliber").description("Configure your coding agent environment").version(displayVersion).option("--no-traces", "Disable anonymous telemetry for this run");
|
|
6965
|
+
function tracked(commandName, handler) {
|
|
6966
|
+
const wrapper = async (...args) => {
|
|
6967
|
+
const start = Date.now();
|
|
6968
|
+
trackEvent("command_started", {
|
|
6969
|
+
command: commandName,
|
|
6970
|
+
cli_version: pkg.version
|
|
6971
|
+
});
|
|
6972
|
+
try {
|
|
6973
|
+
await handler(...args);
|
|
6974
|
+
trackEvent("command_completed", {
|
|
6975
|
+
command: commandName,
|
|
6976
|
+
duration_ms: Date.now() - start,
|
|
6977
|
+
success: true
|
|
6978
|
+
});
|
|
6979
|
+
} catch (err) {
|
|
6980
|
+
const errorMessage = err instanceof Error ? err.message : "Unknown error";
|
|
6981
|
+
const errorType = err instanceof Error ? err.constructor.name : typeof err;
|
|
6982
|
+
if (errorMessage !== "__exit__") {
|
|
6983
|
+
trackEvent("command_error", {
|
|
6984
|
+
command: commandName,
|
|
6985
|
+
error_type: errorType,
|
|
6986
|
+
error_message: errorMessage
|
|
6987
|
+
});
|
|
6988
|
+
}
|
|
6989
|
+
trackEvent("command_completed", {
|
|
6990
|
+
command: commandName,
|
|
6991
|
+
duration_ms: Date.now() - start,
|
|
6992
|
+
success: false
|
|
6993
|
+
});
|
|
6994
|
+
throw err;
|
|
6995
|
+
}
|
|
6996
|
+
};
|
|
6997
|
+
return wrapper;
|
|
6998
|
+
}
|
|
6999
|
+
program.hook("preAction", (thisCommand) => {
|
|
7000
|
+
const opts = thisCommand.optsWithGlobals();
|
|
7001
|
+
if (opts.traces === false) {
|
|
7002
|
+
setTelemetryDisabled(true);
|
|
7003
|
+
}
|
|
7004
|
+
initTelemetry();
|
|
7005
|
+
});
|
|
6773
7006
|
function parseAgentOption(value) {
|
|
6774
7007
|
if (value === "both") return ["claude", "cursor"];
|
|
6775
7008
|
if (value === "all") return ["claude", "cursor", "codex"];
|
|
@@ -6781,39 +7014,39 @@ function parseAgentOption(value) {
|
|
|
6781
7014
|
}
|
|
6782
7015
|
return agents;
|
|
6783
7016
|
}
|
|
6784
|
-
program.command("onboard").alias("init").description("Onboard your project for AI-assisted development").option("--agent <type>", "Target agents (comma-separated): claude, cursor, codex", parseAgentOption).option("--dry-run", "Preview changes without writing files").option("--force", "Overwrite existing setup without prompting").action(initCommand);
|
|
6785
|
-
program.command("undo").description("Revert all config changes made by Caliber").action(undoCommand);
|
|
6786
|
-
program.command("status").description("Show current Caliber setup status").option("--json", "Output as JSON").action(statusCommand);
|
|
6787
|
-
program.command("regenerate").alias("regen").alias("re").description("Re-analyze project and regenerate setup").option("--dry-run", "Preview changes without writing files").action(regenerateCommand);
|
|
6788
|
-
program.command("config").description("Configure LLM provider, API key, and model").action(configCommand);
|
|
6789
|
-
program.command("skills").description("Discover and install community skills for your project").action(recommendCommand);
|
|
6790
|
-
program.command("score").description("Score your current agent config setup (deterministic, no network)").option("--json", "Output as JSON").option("--quiet", "One-line output for scripts/hooks").option("--agent <type>", "Target agents (comma-separated): claude, cursor, codex", parseAgentOption).action(scoreCommand);
|
|
6791
|
-
program.command("refresh").description("Update docs based on recent code changes").option("--quiet", "Suppress output (for use in hooks)").option("--dry-run", "Preview changes without writing files").action(refreshCommand);
|
|
6792
|
-
program.command("hooks").description("Manage auto-refresh hooks (toggle interactively)").option("--install", "Enable all hooks non-interactively").option("--remove", "Disable all hooks non-interactively").action(hooksCommand);
|
|
7017
|
+
program.command("onboard").alias("init").description("Onboard your project for AI-assisted development").option("--agent <type>", "Target agents (comma-separated): claude, cursor, codex", parseAgentOption).option("--dry-run", "Preview changes without writing files").option("--force", "Overwrite existing setup without prompting").action(tracked("onboard", initCommand));
|
|
7018
|
+
program.command("undo").description("Revert all config changes made by Caliber").action(tracked("undo", undoCommand));
|
|
7019
|
+
program.command("status").description("Show current Caliber setup status").option("--json", "Output as JSON").action(tracked("status", statusCommand));
|
|
7020
|
+
program.command("regenerate").alias("regen").alias("re").description("Re-analyze project and regenerate setup").option("--dry-run", "Preview changes without writing files").action(tracked("regenerate", regenerateCommand));
|
|
7021
|
+
program.command("config").description("Configure LLM provider, API key, and model").action(tracked("config", configCommand));
|
|
7022
|
+
program.command("skills").description("Discover and install community skills for your project").action(tracked("skills", recommendCommand));
|
|
7023
|
+
program.command("score").description("Score your current agent config setup (deterministic, no network)").option("--json", "Output as JSON").option("--quiet", "One-line output for scripts/hooks").option("--agent <type>", "Target agents (comma-separated): claude, cursor, codex", parseAgentOption).action(tracked("score", scoreCommand));
|
|
7024
|
+
program.command("refresh").description("Update docs based on recent code changes").option("--quiet", "Suppress output (for use in hooks)").option("--dry-run", "Preview changes without writing files").action(tracked("refresh", refreshCommand));
|
|
7025
|
+
program.command("hooks").description("Manage auto-refresh hooks (toggle interactively)").option("--install", "Enable all hooks non-interactively").option("--remove", "Disable all hooks non-interactively").action(tracked("hooks", hooksCommand));
|
|
6793
7026
|
var learn = program.command("learn", { hidden: true }).description("[dev] Session learning \u2014 observe tool usage and extract reusable instructions");
|
|
6794
|
-
learn.command("observe").description("Record a tool event from stdin (called by hooks)").option("--failure", "Mark event as a tool failure").action(learnObserveCommand);
|
|
6795
|
-
learn.command("finalize").description("Analyze session events and update CLAUDE.md (called on SessionEnd)").action(learnFinalizeCommand);
|
|
6796
|
-
learn.command("install").description("Install learning hooks into .claude/settings.json").action(learnInstallCommand);
|
|
6797
|
-
learn.command("remove").description("Remove learning hooks from .claude/settings.json").action(learnRemoveCommand);
|
|
6798
|
-
learn.command("status").description("Show learning system status").action(learnStatusCommand);
|
|
7027
|
+
learn.command("observe").description("Record a tool event from stdin (called by hooks)").option("--failure", "Mark event as a tool failure").action(tracked("learn:observe", learnObserveCommand));
|
|
7028
|
+
learn.command("finalize").description("Analyze session events and update CLAUDE.md (called on SessionEnd)").action(tracked("learn:finalize", learnFinalizeCommand));
|
|
7029
|
+
learn.command("install").description("Install learning hooks into .claude/settings.json").action(tracked("learn:install", learnInstallCommand));
|
|
7030
|
+
learn.command("remove").description("Remove learning hooks from .claude/settings.json").action(tracked("learn:remove", learnRemoveCommand));
|
|
7031
|
+
learn.command("status").description("Show learning system status").action(tracked("learn:status", learnStatusCommand));
|
|
6799
7032
|
|
|
6800
7033
|
// src/utils/version-check.ts
|
|
6801
|
-
import
|
|
6802
|
-
import
|
|
7034
|
+
import fs29 from "fs";
|
|
7035
|
+
import path23 from "path";
|
|
6803
7036
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
6804
|
-
import { execSync as
|
|
6805
|
-
import
|
|
7037
|
+
import { execSync as execSync10 } from "child_process";
|
|
7038
|
+
import chalk17 from "chalk";
|
|
6806
7039
|
import ora6 from "ora";
|
|
6807
7040
|
import confirm from "@inquirer/confirm";
|
|
6808
|
-
var __dirname_vc =
|
|
7041
|
+
var __dirname_vc = path23.dirname(fileURLToPath2(import.meta.url));
|
|
6809
7042
|
var pkg2 = JSON.parse(
|
|
6810
|
-
|
|
7043
|
+
fs29.readFileSync(path23.resolve(__dirname_vc, "..", "package.json"), "utf-8")
|
|
6811
7044
|
);
|
|
6812
7045
|
function getInstalledVersion() {
|
|
6813
7046
|
try {
|
|
6814
|
-
const globalRoot =
|
|
6815
|
-
const pkgPath =
|
|
6816
|
-
return JSON.parse(
|
|
7047
|
+
const globalRoot = execSync10("npm root -g", { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
|
|
7048
|
+
const pkgPath = path23.join(globalRoot, "@rely-ai", "caliber", "package.json");
|
|
7049
|
+
return JSON.parse(fs29.readFileSync(pkgPath, "utf-8")).version;
|
|
6817
7050
|
} catch {
|
|
6818
7051
|
return null;
|
|
6819
7052
|
}
|
|
@@ -6836,17 +7069,17 @@ async function checkForUpdates() {
|
|
|
6836
7069
|
const isInteractive = process.stdin.isTTY === true;
|
|
6837
7070
|
if (!isInteractive) {
|
|
6838
7071
|
console.log(
|
|
6839
|
-
|
|
7072
|
+
chalk17.yellow(
|
|
6840
7073
|
`
|
|
6841
7074
|
Update available: ${current} -> ${latest}
|
|
6842
|
-
Run ${
|
|
7075
|
+
Run ${chalk17.bold("npm install -g @rely-ai/caliber")} to upgrade.
|
|
6843
7076
|
`
|
|
6844
7077
|
)
|
|
6845
7078
|
);
|
|
6846
7079
|
return;
|
|
6847
7080
|
}
|
|
6848
7081
|
console.log(
|
|
6849
|
-
|
|
7082
|
+
chalk17.yellow(`
|
|
6850
7083
|
Update available: ${current} -> ${latest}`)
|
|
6851
7084
|
);
|
|
6852
7085
|
const shouldUpdate = await confirm({ message: "Would you like to update now? (Y/n)", default: true });
|
|
@@ -6856,7 +7089,7 @@ Update available: ${current} -> ${latest}`)
|
|
|
6856
7089
|
}
|
|
6857
7090
|
const spinner = ora6("Updating caliber...").start();
|
|
6858
7091
|
try {
|
|
6859
|
-
|
|
7092
|
+
execSync10(`npm install -g @rely-ai/caliber@${latest}`, {
|
|
6860
7093
|
stdio: "pipe",
|
|
6861
7094
|
timeout: 12e4,
|
|
6862
7095
|
env: { ...process.env, npm_config_fund: "false", npm_config_audit: "false" }
|
|
@@ -6864,16 +7097,16 @@ Update available: ${current} -> ${latest}`)
|
|
|
6864
7097
|
const installed = getInstalledVersion();
|
|
6865
7098
|
if (installed !== latest) {
|
|
6866
7099
|
spinner.fail(`Update incomplete \u2014 got ${installed ?? "unknown"}, expected ${latest}`);
|
|
6867
|
-
console.log(
|
|
7100
|
+
console.log(chalk17.yellow(`Run ${chalk17.bold(`npm install -g @rely-ai/caliber@${latest}`)} manually.
|
|
6868
7101
|
`));
|
|
6869
7102
|
return;
|
|
6870
7103
|
}
|
|
6871
|
-
spinner.succeed(
|
|
7104
|
+
spinner.succeed(chalk17.green(`Updated to ${latest}`));
|
|
6872
7105
|
const args = process.argv.slice(2);
|
|
6873
|
-
console.log(
|
|
7106
|
+
console.log(chalk17.dim(`
|
|
6874
7107
|
Restarting: caliber ${args.join(" ")}
|
|
6875
7108
|
`));
|
|
6876
|
-
|
|
7109
|
+
execSync10(`caliber ${args.map((a) => JSON.stringify(a)).join(" ")}`, {
|
|
6877
7110
|
stdio: "inherit",
|
|
6878
7111
|
env: { ...process.env, CALIBER_SKIP_UPDATE_CHECK: "1" }
|
|
6879
7112
|
});
|
|
@@ -6883,11 +7116,11 @@ Restarting: caliber ${args.join(" ")}
|
|
|
6883
7116
|
if (err instanceof Error) {
|
|
6884
7117
|
const stderr = err.stderr;
|
|
6885
7118
|
const errMsg = stderr ? String(stderr).trim().split("\n").pop() : err.message.split("\n")[0];
|
|
6886
|
-
if (errMsg && !errMsg.includes("SIGTERM")) console.log(
|
|
7119
|
+
if (errMsg && !errMsg.includes("SIGTERM")) console.log(chalk17.dim(` ${errMsg}`));
|
|
6887
7120
|
}
|
|
6888
7121
|
console.log(
|
|
6889
|
-
|
|
6890
|
-
`Run ${
|
|
7122
|
+
chalk17.yellow(
|
|
7123
|
+
`Run ${chalk17.bold(`npm install -g @rely-ai/caliber@${latest}`)} manually to upgrade.
|
|
6891
7124
|
`
|
|
6892
7125
|
)
|
|
6893
7126
|
);
|
|
@@ -6907,5 +7140,8 @@ program.parseAsync().catch((err) => {
|
|
|
6907
7140
|
console.error(msg);
|
|
6908
7141
|
}
|
|
6909
7142
|
process.exitCode = 1;
|
|
6910
|
-
}).finally(() =>
|
|
7143
|
+
}).finally(async () => {
|
|
7144
|
+
await flushTelemetry();
|
|
7145
|
+
process.exit(Number(process.exitCode ?? 0));
|
|
7146
|
+
});
|
|
6911
7147
|
//# sourceMappingURL=bin.js.map
|