@rely-ai/caliber 1.44.2 → 1.45.1
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 +871 -598
- package/package.json +2 -1
package/dist/bin.js
CHANGED
|
@@ -84,6 +84,12 @@ function resolveFromEnv() {
|
|
|
84
84
|
model: process.env.CALIBER_MODEL || DEFAULT_MODELS["claude-cli"]
|
|
85
85
|
};
|
|
86
86
|
}
|
|
87
|
+
if (process.env.CALIBER_USE_OPENCODE === "1" || process.env.CALIBER_USE_OPENCODE === "true") {
|
|
88
|
+
return {
|
|
89
|
+
provider: "opencode",
|
|
90
|
+
model: process.env.CALIBER_MODEL || DEFAULT_MODELS.opencode
|
|
91
|
+
};
|
|
92
|
+
}
|
|
87
93
|
return null;
|
|
88
94
|
}
|
|
89
95
|
function readConfigFile() {
|
|
@@ -91,7 +97,7 @@ function readConfigFile() {
|
|
|
91
97
|
if (!fs4.existsSync(CONFIG_FILE)) return null;
|
|
92
98
|
const raw = fs4.readFileSync(CONFIG_FILE, "utf-8");
|
|
93
99
|
const parsed = JSON.parse(raw);
|
|
94
|
-
if (!parsed.provider || !["anthropic", "vertex", "openai", "minimax", "cursor", "claude-cli"].includes(
|
|
100
|
+
if (!parsed.provider || !["anthropic", "vertex", "openai", "minimax", "cursor", "claude-cli", "opencode"].includes(
|
|
95
101
|
parsed.provider
|
|
96
102
|
)) {
|
|
97
103
|
return null;
|
|
@@ -118,6 +124,9 @@ function getDisplayModel(config) {
|
|
|
118
124
|
if (config.model === "default" && config.provider === "claude-cli") {
|
|
119
125
|
return process.env.ANTHROPIC_MODEL || "default (inherited from Claude Code)";
|
|
120
126
|
}
|
|
127
|
+
if (config.model === "default" && config.provider === "opencode") {
|
|
128
|
+
return "default (inherited from OpenCode)";
|
|
129
|
+
}
|
|
121
130
|
return config.model;
|
|
122
131
|
}
|
|
123
132
|
function getFastModel() {
|
|
@@ -143,7 +152,8 @@ var init_config = __esm({
|
|
|
143
152
|
openai: "gpt-5.4-mini",
|
|
144
153
|
minimax: "MiniMax-M2.7",
|
|
145
154
|
cursor: "sonnet-4.6",
|
|
146
|
-
"claude-cli": "default"
|
|
155
|
+
"claude-cli": "default",
|
|
156
|
+
opencode: "default"
|
|
147
157
|
};
|
|
148
158
|
MODEL_CONTEXT_WINDOWS = {
|
|
149
159
|
"claude-sonnet-4-6": 2e5,
|
|
@@ -267,7 +277,11 @@ var SEAT_BASED_PROVIDERS;
|
|
|
267
277
|
var init_types = __esm({
|
|
268
278
|
"src/llm/types.ts"() {
|
|
269
279
|
"use strict";
|
|
270
|
-
SEAT_BASED_PROVIDERS = /* @__PURE__ */ new Set([
|
|
280
|
+
SEAT_BASED_PROVIDERS = /* @__PURE__ */ new Set([
|
|
281
|
+
"cursor",
|
|
282
|
+
"claude-cli",
|
|
283
|
+
"opencode"
|
|
284
|
+
]);
|
|
271
285
|
}
|
|
272
286
|
});
|
|
273
287
|
|
|
@@ -897,7 +911,7 @@ var init_builtin_skills = __esm({
|
|
|
897
911
|
});
|
|
898
912
|
|
|
899
913
|
// src/utils/editor.ts
|
|
900
|
-
import { execSync as
|
|
914
|
+
import { execSync as execSync16, spawn as spawn4 } from "child_process";
|
|
901
915
|
import fs29 from "fs";
|
|
902
916
|
import path25 from "path";
|
|
903
917
|
import os6 from "os";
|
|
@@ -910,7 +924,7 @@ function getEmptyFilePath(proposedPath) {
|
|
|
910
924
|
function commandExists(cmd) {
|
|
911
925
|
try {
|
|
912
926
|
const check = process.platform === "win32" ? `where ${cmd}` : `which ${cmd}`;
|
|
913
|
-
|
|
927
|
+
execSync16(check, { stdio: "ignore" });
|
|
914
928
|
return true;
|
|
915
929
|
} catch {
|
|
916
930
|
return false;
|
|
@@ -928,22 +942,22 @@ function openDiffsInEditor(editor, files) {
|
|
|
928
942
|
for (const file of files) {
|
|
929
943
|
try {
|
|
930
944
|
const leftPath = file.originalPath ?? getEmptyFilePath(file.proposedPath);
|
|
931
|
-
if (
|
|
945
|
+
if (IS_WINDOWS5) {
|
|
932
946
|
const quote = (s) => `"${s}"`;
|
|
933
|
-
|
|
947
|
+
spawn4([cmd, "--diff", quote(leftPath), quote(file.proposedPath)].join(" "), { shell: true, stdio: "ignore", detached: true }).unref();
|
|
934
948
|
} else {
|
|
935
|
-
|
|
949
|
+
spawn4(cmd, ["--diff", leftPath, file.proposedPath], { stdio: "ignore", detached: true }).unref();
|
|
936
950
|
}
|
|
937
951
|
} catch {
|
|
938
952
|
continue;
|
|
939
953
|
}
|
|
940
954
|
}
|
|
941
955
|
}
|
|
942
|
-
var
|
|
956
|
+
var IS_WINDOWS5, DIFF_TEMP_DIR;
|
|
943
957
|
var init_editor = __esm({
|
|
944
958
|
"src/utils/editor.ts"() {
|
|
945
959
|
"use strict";
|
|
946
|
-
|
|
960
|
+
IS_WINDOWS5 = process.platform === "win32";
|
|
947
961
|
DIFF_TEMP_DIR = path25.join(os6.tmpdir(), "caliber-diff");
|
|
948
962
|
}
|
|
949
963
|
});
|
|
@@ -955,7 +969,7 @@ __export(review_exports, {
|
|
|
955
969
|
promptReviewMethod: () => promptReviewMethod,
|
|
956
970
|
promptWantsReview: () => promptWantsReview
|
|
957
971
|
});
|
|
958
|
-
import
|
|
972
|
+
import chalk9 from "chalk";
|
|
959
973
|
import fs30 from "fs";
|
|
960
974
|
import select4 from "@inquirer/select";
|
|
961
975
|
import { createTwoFilesPatch } from "diff";
|
|
@@ -994,7 +1008,7 @@ async function openReview(method, stagedFiles) {
|
|
|
994
1008
|
proposedPath: f.proposedPath
|
|
995
1009
|
}))
|
|
996
1010
|
);
|
|
997
|
-
console.log(
|
|
1011
|
+
console.log(chalk9.dim(" Diffs opened in your editor.\n"));
|
|
998
1012
|
return;
|
|
999
1013
|
}
|
|
1000
1014
|
const fileInfos = stagedFiles.map((file) => {
|
|
@@ -1025,8 +1039,8 @@ async function openReview(method, stagedFiles) {
|
|
|
1025
1039
|
async function interactiveDiffExplorer(files) {
|
|
1026
1040
|
if (!process.stdin.isTTY) {
|
|
1027
1041
|
for (const f of files) {
|
|
1028
|
-
const icon = f.isNew ?
|
|
1029
|
-
const stats = f.isNew ?
|
|
1042
|
+
const icon = f.isNew ? chalk9.green("+") : chalk9.yellow("~");
|
|
1043
|
+
const stats = f.isNew ? chalk9.dim(`${f.lines} lines`) : `${chalk9.green(`+${f.added}`)} ${chalk9.red(`-${f.removed}`)}`;
|
|
1030
1044
|
console.log(` ${icon} ${f.relativePath} ${stats}`);
|
|
1031
1045
|
}
|
|
1032
1046
|
console.log("");
|
|
@@ -1042,47 +1056,47 @@ async function interactiveDiffExplorer(files) {
|
|
|
1042
1056
|
}
|
|
1043
1057
|
function renderFileList() {
|
|
1044
1058
|
const lines = [];
|
|
1045
|
-
lines.push(
|
|
1059
|
+
lines.push(chalk9.bold(" Review changes"));
|
|
1046
1060
|
lines.push("");
|
|
1047
1061
|
for (let i = 0; i < files.length; i++) {
|
|
1048
1062
|
const f = files[i];
|
|
1049
|
-
const ptr = i === cursor ?
|
|
1050
|
-
const icon = f.isNew ?
|
|
1051
|
-
const stats = f.isNew ?
|
|
1063
|
+
const ptr = i === cursor ? chalk9.cyan(">") : " ";
|
|
1064
|
+
const icon = f.isNew ? chalk9.green("+") : chalk9.yellow("~");
|
|
1065
|
+
const stats = f.isNew ? chalk9.dim(`${f.lines} lines`) : `${chalk9.green(`+${f.added}`)} ${chalk9.red(`-${f.removed}`)}`;
|
|
1052
1066
|
lines.push(` ${ptr} ${icon} ${f.relativePath} ${stats}`);
|
|
1053
1067
|
}
|
|
1054
1068
|
lines.push("");
|
|
1055
|
-
lines.push(
|
|
1069
|
+
lines.push(chalk9.dim(" \u2191\u2193 navigate \u23CE view diff q done"));
|
|
1056
1070
|
return lines.join("\n");
|
|
1057
1071
|
}
|
|
1058
1072
|
function renderDiff(index) {
|
|
1059
1073
|
const f = files[index];
|
|
1060
1074
|
const lines = [];
|
|
1061
|
-
const header = f.isNew ? ` ${
|
|
1075
|
+
const header = f.isNew ? ` ${chalk9.green("+")} ${f.relativePath} ${chalk9.dim("(new file)")}` : ` ${chalk9.yellow("~")} ${f.relativePath} ${chalk9.green(`+${f.added}`)} ${chalk9.red(`-${f.removed}`)}`;
|
|
1062
1076
|
lines.push(header);
|
|
1063
|
-
lines.push(
|
|
1077
|
+
lines.push(chalk9.dim(" " + "\u2500".repeat(60)));
|
|
1064
1078
|
const patchLines = f.patch.split("\n");
|
|
1065
1079
|
const bodyLines = patchLines.slice(4);
|
|
1066
1080
|
const maxVisible = getTermHeight() - 4;
|
|
1067
1081
|
const visibleLines = bodyLines.slice(scrollOffset, scrollOffset + maxVisible);
|
|
1068
1082
|
for (const line of visibleLines) {
|
|
1069
1083
|
if (line.startsWith("+")) {
|
|
1070
|
-
lines.push(
|
|
1084
|
+
lines.push(chalk9.green(" " + line));
|
|
1071
1085
|
} else if (line.startsWith("-")) {
|
|
1072
|
-
lines.push(
|
|
1086
|
+
lines.push(chalk9.red(" " + line));
|
|
1073
1087
|
} else if (line.startsWith("@@")) {
|
|
1074
|
-
lines.push(
|
|
1088
|
+
lines.push(chalk9.cyan(" " + line));
|
|
1075
1089
|
} else {
|
|
1076
|
-
lines.push(
|
|
1090
|
+
lines.push(chalk9.dim(" " + line));
|
|
1077
1091
|
}
|
|
1078
1092
|
}
|
|
1079
1093
|
const totalBody = bodyLines.length;
|
|
1080
1094
|
if (totalBody > maxVisible) {
|
|
1081
1095
|
const pct = Math.round((scrollOffset + maxVisible) / totalBody * 100);
|
|
1082
|
-
lines.push(
|
|
1096
|
+
lines.push(chalk9.dim(` \u2500\u2500 ${Math.min(pct, 100)}% \u2500\u2500`));
|
|
1083
1097
|
}
|
|
1084
1098
|
lines.push("");
|
|
1085
|
-
lines.push(
|
|
1099
|
+
lines.push(chalk9.dim(" \u2191\u2193 scroll \u23B5/esc back to file list"));
|
|
1086
1100
|
return lines.join("\n");
|
|
1087
1101
|
}
|
|
1088
1102
|
function draw(initial) {
|
|
@@ -1235,7 +1249,7 @@ import { fileURLToPath } from "url";
|
|
|
1235
1249
|
|
|
1236
1250
|
// src/commands/init.ts
|
|
1237
1251
|
import path28 from "path";
|
|
1238
|
-
import
|
|
1252
|
+
import chalk13 from "chalk";
|
|
1239
1253
|
import fs35 from "fs";
|
|
1240
1254
|
|
|
1241
1255
|
// src/fingerprint/index.ts
|
|
@@ -3132,6 +3146,215 @@ function isClaudeCliLoggedIn() {
|
|
|
3132
3146
|
return cachedLoggedIn;
|
|
3133
3147
|
}
|
|
3134
3148
|
|
|
3149
|
+
// src/llm/opencode.ts
|
|
3150
|
+
import { spawn as spawn3, execSync as execSync8 } from "child_process";
|
|
3151
|
+
var OPENCODE_BIN = "opencode";
|
|
3152
|
+
var DEFAULT_TIMEOUT_MS3 = 10 * 60 * 1e3;
|
|
3153
|
+
var IS_WINDOWS3 = process.platform === "win32";
|
|
3154
|
+
var cachedLoggedIn2 = null;
|
|
3155
|
+
function isOpenCodeAvailable() {
|
|
3156
|
+
try {
|
|
3157
|
+
const cmd = IS_WINDOWS3 ? `where ${OPENCODE_BIN}` : `which ${OPENCODE_BIN}`;
|
|
3158
|
+
execSync8(cmd, { stdio: "ignore" });
|
|
3159
|
+
return true;
|
|
3160
|
+
} catch {
|
|
3161
|
+
return false;
|
|
3162
|
+
}
|
|
3163
|
+
}
|
|
3164
|
+
function isOpenCodeLoggedIn() {
|
|
3165
|
+
if (cachedLoggedIn2 !== null) return cachedLoggedIn2;
|
|
3166
|
+
try {
|
|
3167
|
+
const result = execSync8("opencode auth status", {
|
|
3168
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
3169
|
+
timeout: 5e3
|
|
3170
|
+
});
|
|
3171
|
+
const output = result.toString().trim();
|
|
3172
|
+
try {
|
|
3173
|
+
const status = JSON.parse(output);
|
|
3174
|
+
cachedLoggedIn2 = status.loggedIn === true;
|
|
3175
|
+
} catch {
|
|
3176
|
+
cachedLoggedIn2 = !output.toLowerCase().includes("not logged in");
|
|
3177
|
+
}
|
|
3178
|
+
} catch {
|
|
3179
|
+
cachedLoggedIn2 = false;
|
|
3180
|
+
}
|
|
3181
|
+
return cachedLoggedIn2;
|
|
3182
|
+
}
|
|
3183
|
+
function spawnOpenCode(args) {
|
|
3184
|
+
const env = { ...process.env, OPENCODE_DISABLE_AUTOCOMPACT: "TRUE" };
|
|
3185
|
+
if (IS_WINDOWS3) {
|
|
3186
|
+
return spawn3([OPENCODE_BIN, ...args].join(" "), {
|
|
3187
|
+
cwd: process.cwd(),
|
|
3188
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
3189
|
+
env,
|
|
3190
|
+
shell: true
|
|
3191
|
+
});
|
|
3192
|
+
} else {
|
|
3193
|
+
return spawn3(OPENCODE_BIN, args, {
|
|
3194
|
+
cwd: process.cwd(),
|
|
3195
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
3196
|
+
env
|
|
3197
|
+
});
|
|
3198
|
+
}
|
|
3199
|
+
}
|
|
3200
|
+
function runCommand(args, input2, timeoutMs) {
|
|
3201
|
+
return new Promise((resolve3, reject) => {
|
|
3202
|
+
const child = spawnOpenCode(args);
|
|
3203
|
+
const stderrChunks = [];
|
|
3204
|
+
child.stdin.end(input2);
|
|
3205
|
+
let stdoutData = Buffer.alloc(0);
|
|
3206
|
+
child.stdout.on("data", (chunk) => {
|
|
3207
|
+
stdoutData = Buffer.concat([stdoutData, chunk]);
|
|
3208
|
+
});
|
|
3209
|
+
child.stderr.on("data", (chunk) => {
|
|
3210
|
+
stderrChunks.push(chunk);
|
|
3211
|
+
});
|
|
3212
|
+
const timer = setTimeout(() => {
|
|
3213
|
+
child.kill("SIGTERM");
|
|
3214
|
+
reject(
|
|
3215
|
+
new Error(
|
|
3216
|
+
`OpenCode timed out after ${timeoutMs / 1e3}s. Set CALIBER_OPENCODE_TIMEOUT_MS to increase.`
|
|
3217
|
+
)
|
|
3218
|
+
);
|
|
3219
|
+
}, timeoutMs);
|
|
3220
|
+
child.on("error", (err) => {
|
|
3221
|
+
clearTimeout(timer);
|
|
3222
|
+
reject(err);
|
|
3223
|
+
});
|
|
3224
|
+
child.on("close", (code, signal) => {
|
|
3225
|
+
clearTimeout(timer);
|
|
3226
|
+
const stderr = Buffer.concat(stderrChunks).toString("utf-8").trim();
|
|
3227
|
+
if (code === 0) {
|
|
3228
|
+
resolve3(stdoutData.toString("utf-8").trim());
|
|
3229
|
+
} else {
|
|
3230
|
+
const friendly = parseSeatBasedError(stderr, code);
|
|
3231
|
+
const base = signal ? `OpenCode killed (${signal})` : code != null ? `OpenCode exited with code ${code}` : "OpenCode exited";
|
|
3232
|
+
const detail = friendly || stderr;
|
|
3233
|
+
reject(new Error(detail ? `${base}. ${detail}` : base));
|
|
3234
|
+
}
|
|
3235
|
+
});
|
|
3236
|
+
});
|
|
3237
|
+
}
|
|
3238
|
+
function runCommandStream(args, input2, callbacks, timeoutMs) {
|
|
3239
|
+
return new Promise((resolve3, reject) => {
|
|
3240
|
+
const child = spawnOpenCode(args);
|
|
3241
|
+
const stderrChunks = [];
|
|
3242
|
+
let settled = false;
|
|
3243
|
+
let lineBuffer = "";
|
|
3244
|
+
child.stdin.end(input2);
|
|
3245
|
+
child.stdout.on("data", (chunk) => {
|
|
3246
|
+
const text = chunk.toString("utf-8");
|
|
3247
|
+
lineBuffer += text;
|
|
3248
|
+
const lines = lineBuffer.split("\n");
|
|
3249
|
+
lineBuffer = lines.pop() || "";
|
|
3250
|
+
for (const line of lines) {
|
|
3251
|
+
if (!line.trim()) continue;
|
|
3252
|
+
try {
|
|
3253
|
+
const event = JSON.parse(line);
|
|
3254
|
+
if (event.type === "text" && event.part?.text) {
|
|
3255
|
+
callbacks.onText(event.part.text);
|
|
3256
|
+
}
|
|
3257
|
+
} catch {
|
|
3258
|
+
}
|
|
3259
|
+
}
|
|
3260
|
+
});
|
|
3261
|
+
child.stderr.on("data", (chunk) => {
|
|
3262
|
+
stderrChunks.push(chunk);
|
|
3263
|
+
});
|
|
3264
|
+
const timer = setTimeout(() => {
|
|
3265
|
+
child.kill("SIGTERM");
|
|
3266
|
+
if (!settled) {
|
|
3267
|
+
settled = true;
|
|
3268
|
+
reject(
|
|
3269
|
+
new Error(
|
|
3270
|
+
`OpenCode timed out after ${timeoutMs / 1e3}s. Set CALIBER_OPENCODE_TIMEOUT_MS to increase.`
|
|
3271
|
+
)
|
|
3272
|
+
);
|
|
3273
|
+
}
|
|
3274
|
+
}, timeoutMs);
|
|
3275
|
+
child.on("error", (err) => {
|
|
3276
|
+
clearTimeout(timer);
|
|
3277
|
+
if (!settled) {
|
|
3278
|
+
settled = true;
|
|
3279
|
+
reject(err);
|
|
3280
|
+
}
|
|
3281
|
+
});
|
|
3282
|
+
child.on("close", (code, signal) => {
|
|
3283
|
+
clearTimeout(timer);
|
|
3284
|
+
if (settled) return;
|
|
3285
|
+
settled = true;
|
|
3286
|
+
if (code === 0) {
|
|
3287
|
+
if (lineBuffer.trim()) {
|
|
3288
|
+
try {
|
|
3289
|
+
const event = JSON.parse(lineBuffer);
|
|
3290
|
+
if (event.type === "text" && event.part?.text) {
|
|
3291
|
+
callbacks.onText(event.part.text);
|
|
3292
|
+
}
|
|
3293
|
+
} catch {
|
|
3294
|
+
}
|
|
3295
|
+
}
|
|
3296
|
+
callbacks.onEnd({ stopReason: "end_turn" });
|
|
3297
|
+
resolve3();
|
|
3298
|
+
} else {
|
|
3299
|
+
const stderr = Buffer.concat(stderrChunks).toString("utf-8").trim();
|
|
3300
|
+
const friendly = parseSeatBasedError(stderr, code);
|
|
3301
|
+
const base = signal ? `OpenCode killed (${signal})` : code != null ? `OpenCode exited with code ${code}` : "OpenCode exited";
|
|
3302
|
+
const detail = friendly || stderr;
|
|
3303
|
+
reject(new Error(detail ? `${base}. ${detail}` : base));
|
|
3304
|
+
}
|
|
3305
|
+
});
|
|
3306
|
+
});
|
|
3307
|
+
}
|
|
3308
|
+
var OpenCodeProvider = class {
|
|
3309
|
+
defaultModel;
|
|
3310
|
+
timeoutMs;
|
|
3311
|
+
constructor(config) {
|
|
3312
|
+
this.defaultModel = config.model || "default";
|
|
3313
|
+
const envTimeout = process.env.CALIBER_OPENCODE_TIMEOUT_MS;
|
|
3314
|
+
this.timeoutMs = envTimeout ? parseInt(envTimeout, 10) : DEFAULT_TIMEOUT_MS3;
|
|
3315
|
+
if (!Number.isFinite(this.timeoutMs) || this.timeoutMs < 1e3) {
|
|
3316
|
+
this.timeoutMs = DEFAULT_TIMEOUT_MS3;
|
|
3317
|
+
}
|
|
3318
|
+
}
|
|
3319
|
+
async call(options) {
|
|
3320
|
+
const system = options.system || "";
|
|
3321
|
+
const prompt = options.prompt || "";
|
|
3322
|
+
const combined = system + "\n\n" + prompt;
|
|
3323
|
+
const model = options.model || this.defaultModel;
|
|
3324
|
+
const args = ["run", "--format", "json", "--model", model, "--", "-"];
|
|
3325
|
+
const result = await runCommand(args, combined, this.timeoutMs);
|
|
3326
|
+
trackUsage(model, {
|
|
3327
|
+
inputTokens: estimateTokens(combined),
|
|
3328
|
+
outputTokens: estimateTokens(result)
|
|
3329
|
+
});
|
|
3330
|
+
return result;
|
|
3331
|
+
}
|
|
3332
|
+
async stream(options, callbacks) {
|
|
3333
|
+
const system = options.system || "";
|
|
3334
|
+
const prompt = options.prompt || "";
|
|
3335
|
+
const combined = system + "\n\n" + prompt;
|
|
3336
|
+
const model = options.model || this.defaultModel;
|
|
3337
|
+
const args = ["run", "--format", "json", "--model", model, "--", "-"];
|
|
3338
|
+
const inputEstimate = estimateTokens(combined);
|
|
3339
|
+
let outputChars = 0;
|
|
3340
|
+
const wrappedCallbacks = {
|
|
3341
|
+
onText: (text) => {
|
|
3342
|
+
outputChars += text.length;
|
|
3343
|
+
callbacks.onText(text);
|
|
3344
|
+
},
|
|
3345
|
+
onEnd: (meta) => {
|
|
3346
|
+
trackUsage(model, {
|
|
3347
|
+
inputTokens: inputEstimate,
|
|
3348
|
+
outputTokens: Math.ceil(outputChars / 4)
|
|
3349
|
+
});
|
|
3350
|
+
callbacks.onEnd(meta);
|
|
3351
|
+
},
|
|
3352
|
+
onError: (err) => callbacks.onError(err)
|
|
3353
|
+
};
|
|
3354
|
+
return runCommandStream(args, combined, wrappedCallbacks, this.timeoutMs);
|
|
3355
|
+
}
|
|
3356
|
+
};
|
|
3357
|
+
|
|
3135
3358
|
// src/llm/model-recovery.ts
|
|
3136
3359
|
init_config();
|
|
3137
3360
|
init_resolve_caliber();
|
|
@@ -3155,7 +3378,8 @@ var KNOWN_MODELS = {
|
|
|
3155
3378
|
openai: ["gpt-5.4-mini", "gpt-4o", "gpt-4o-mini", "o3-mini"],
|
|
3156
3379
|
minimax: ["MiniMax-M2.7", "MiniMax-M2.7-highspeed"],
|
|
3157
3380
|
cursor: ["auto", "composer-1.5"],
|
|
3158
|
-
"claude-cli": []
|
|
3381
|
+
"claude-cli": [],
|
|
3382
|
+
opencode: []
|
|
3159
3383
|
};
|
|
3160
3384
|
function isModelNotAvailableError(error) {
|
|
3161
3385
|
const msg = error.message.toLowerCase();
|
|
@@ -3285,6 +3509,19 @@ function createProvider(config) {
|
|
|
3285
3509
|
}
|
|
3286
3510
|
return new ClaudeCliProvider(config);
|
|
3287
3511
|
}
|
|
3512
|
+
case "opencode": {
|
|
3513
|
+
if (!isOpenCodeAvailable()) {
|
|
3514
|
+
throw new Error(
|
|
3515
|
+
"OpenCode provider requires the OpenCode CLI. Install it from https://opencode.ai then run `opencode auth login`. Alternatively set ANTHROPIC_API_KEY or choose another provider."
|
|
3516
|
+
);
|
|
3517
|
+
}
|
|
3518
|
+
if (!isOpenCodeLoggedIn()) {
|
|
3519
|
+
throw new Error(
|
|
3520
|
+
"OpenCode CLI is installed but not logged in. Run `opencode auth login` in your terminal to authenticate, then retry."
|
|
3521
|
+
);
|
|
3522
|
+
}
|
|
3523
|
+
return new OpenCodeProvider(config);
|
|
3524
|
+
}
|
|
3288
3525
|
default:
|
|
3289
3526
|
throw new Error(`Unknown provider: ${config.provider}`);
|
|
3290
3527
|
}
|
|
@@ -3294,7 +3531,7 @@ function getProvider() {
|
|
|
3294
3531
|
const config = loadConfig();
|
|
3295
3532
|
if (!config) {
|
|
3296
3533
|
throw new Error(
|
|
3297
|
-
`No LLM provider configured. Set ANTHROPIC_API_KEY, OPENAI_API_KEY, MINIMAX_API_KEY, or VERTEX_PROJECT_ID; or run \`${resolveCaliber()} config\` and choose Cursor
|
|
3534
|
+
`No LLM provider configured. Set ANTHROPIC_API_KEY, OPENAI_API_KEY, MINIMAX_API_KEY, or VERTEX_PROJECT_ID; or run \`${resolveCaliber()} config\` and choose Cursor, Claude Code, or OpenCode; or set CALIBER_USE_CURSOR_SEAT=1 / CALIBER_USE_CLAUDE_CLI=1 / CALIBER_USE_OPENCODE=1.`
|
|
3298
3535
|
);
|
|
3299
3536
|
}
|
|
3300
3537
|
cachedConfig = config;
|
|
@@ -3945,7 +4182,7 @@ init_config();
|
|
|
3945
4182
|
import fs8 from "fs";
|
|
3946
4183
|
import path7 from "path";
|
|
3947
4184
|
import crypto from "crypto";
|
|
3948
|
-
import { execSync as
|
|
4185
|
+
import { execSync as execSync9 } from "child_process";
|
|
3949
4186
|
var CACHE_VERSION = 1;
|
|
3950
4187
|
var CACHE_DIR = ".caliber/cache";
|
|
3951
4188
|
var CACHE_FILE = "fingerprint.json";
|
|
@@ -3954,7 +4191,7 @@ function getCachePath(dir) {
|
|
|
3954
4191
|
}
|
|
3955
4192
|
function getGitHead(dir) {
|
|
3956
4193
|
try {
|
|
3957
|
-
return
|
|
4194
|
+
return execSync9("git rev-parse HEAD", {
|
|
3958
4195
|
cwd: dir,
|
|
3959
4196
|
encoding: "utf-8",
|
|
3960
4197
|
stdio: ["pipe", "pipe", "pipe"],
|
|
@@ -3966,7 +4203,7 @@ function getGitHead(dir) {
|
|
|
3966
4203
|
}
|
|
3967
4204
|
function getDirtySignature(dir) {
|
|
3968
4205
|
try {
|
|
3969
|
-
const output =
|
|
4206
|
+
const output = execSync9("git diff --name-only HEAD", {
|
|
3970
4207
|
cwd: dir,
|
|
3971
4208
|
encoding: "utf-8",
|
|
3972
4209
|
stdio: ["pipe", "pipe", "pipe"],
|
|
@@ -4309,7 +4546,7 @@ function getCursorConfigDir() {
|
|
|
4309
4546
|
init_resolve_caliber();
|
|
4310
4547
|
import fs11 from "fs";
|
|
4311
4548
|
import path10 from "path";
|
|
4312
|
-
import { execSync as
|
|
4549
|
+
import { execSync as execSync10 } from "child_process";
|
|
4313
4550
|
var SETTINGS_PATH = path10.join(".claude", "settings.json");
|
|
4314
4551
|
var REFRESH_TAIL = "refresh --quiet";
|
|
4315
4552
|
var HOOK_DESCRIPTION = "Caliber: auto-refreshing docs based on code changes";
|
|
@@ -4514,7 +4751,7 @@ ${PRECOMMIT_END}`;
|
|
|
4514
4751
|
}
|
|
4515
4752
|
function getGitHooksDir() {
|
|
4516
4753
|
try {
|
|
4517
|
-
const gitDir =
|
|
4754
|
+
const gitDir = execSync10("git rev-parse --git-dir", {
|
|
4518
4755
|
encoding: "utf-8",
|
|
4519
4756
|
stdio: ["pipe", "pipe", "pipe"]
|
|
4520
4757
|
}).trim();
|
|
@@ -5278,16 +5515,20 @@ async function generateSetup(fingerprint, targetAgent, prompt, callbacks, failin
|
|
|
5278
5515
|
({ platform, topic }) => generateSkill(skillContext, topic, fastModel).then((skill) => ({ platform, skill }))
|
|
5279
5516
|
)
|
|
5280
5517
|
);
|
|
5281
|
-
const { succeeded, failed: failedCount } = mergeSkillResults(skillResults, setup);
|
|
5518
|
+
const { succeeded, failed: failedCount, failedNames } = mergeSkillResults(skillResults, setup);
|
|
5282
5519
|
if (failedCount > 0 && callbacks) {
|
|
5283
5520
|
const msg = succeeded === 0 ? `${failedCount} skill${failedCount === 1 ? "" : "s"} failed to generate \u2014 config saved without skills` : `Warning: ${failedCount} of ${failedCount + succeeded} skill${failedCount === 1 ? "" : "s"} failed to generate`;
|
|
5284
5521
|
callbacks.onStatus(msg);
|
|
5522
|
+
for (const name of failedNames) {
|
|
5523
|
+
callbacks.onStatus(` \u2192 ${name}`);
|
|
5524
|
+
}
|
|
5285
5525
|
}
|
|
5286
5526
|
return coreResult;
|
|
5287
5527
|
}
|
|
5288
5528
|
function mergeSkillResults(results, setup) {
|
|
5289
5529
|
let succeeded = 0;
|
|
5290
5530
|
let failed = 0;
|
|
5531
|
+
const failedNames = [];
|
|
5291
5532
|
for (const result of results) {
|
|
5292
5533
|
if (result.status === "fulfilled") {
|
|
5293
5534
|
const { platform, skill } = result.value;
|
|
@@ -5303,9 +5544,11 @@ function mergeSkillResults(results, setup) {
|
|
|
5303
5544
|
succeeded++;
|
|
5304
5545
|
} else {
|
|
5305
5546
|
failed++;
|
|
5547
|
+
const reason = result.reason instanceof Error ? result.reason.message : String(result.reason);
|
|
5548
|
+
failedNames.push(reason);
|
|
5306
5549
|
}
|
|
5307
5550
|
}
|
|
5308
|
-
return { succeeded, failed };
|
|
5551
|
+
return { succeeded, failed, failedNames };
|
|
5309
5552
|
}
|
|
5310
5553
|
var MAX_SKILL_TOPICS = 5;
|
|
5311
5554
|
function collectSkillTopics(setup, targetAgent, fingerprint) {
|
|
@@ -5630,8 +5873,14 @@ async function generateSkillsForSetup(setup, fingerprint, targetAgent, onStatus)
|
|
|
5630
5873
|
({ platform, topic }) => generateSkill(skillContext, topic, fastModel).then((skill) => ({ platform, skill }))
|
|
5631
5874
|
)
|
|
5632
5875
|
);
|
|
5633
|
-
const { succeeded, failed } = mergeSkillResults(skillResults, setup);
|
|
5634
|
-
if (failed > 0)
|
|
5876
|
+
const { succeeded, failed, failedNames } = mergeSkillResults(skillResults, setup);
|
|
5877
|
+
if (failed > 0) {
|
|
5878
|
+
const msg = failed === skillTopics.length ? `All ${failed} skills failed to generate` : `${failed}/${skillTopics.length} skills failed to generate`;
|
|
5879
|
+
onStatus?.(msg);
|
|
5880
|
+
for (const name of failedNames) {
|
|
5881
|
+
onStatus?.(` \u2192 ${name}`);
|
|
5882
|
+
}
|
|
5883
|
+
}
|
|
5635
5884
|
return succeeded;
|
|
5636
5885
|
}
|
|
5637
5886
|
var LIMITS = {
|
|
@@ -6622,7 +6871,7 @@ init_resolve_caliber();
|
|
|
6622
6871
|
// src/lib/state.ts
|
|
6623
6872
|
import fs25 from "fs";
|
|
6624
6873
|
import path21 from "path";
|
|
6625
|
-
import { execSync as
|
|
6874
|
+
import { execSync as execSync11 } from "child_process";
|
|
6626
6875
|
var STATE_FILE = path21.join(CALIBER_DIR, ".caliber-state.json");
|
|
6627
6876
|
function normalizeTargetAgent(value) {
|
|
6628
6877
|
if (Array.isArray(value)) return value;
|
|
@@ -6650,7 +6899,7 @@ function writeState(state) {
|
|
|
6650
6899
|
}
|
|
6651
6900
|
function getCurrentHeadSha() {
|
|
6652
6901
|
try {
|
|
6653
|
-
return
|
|
6902
|
+
return execSync11("git rev-parse HEAD", {
|
|
6654
6903
|
encoding: "utf-8",
|
|
6655
6904
|
stdio: ["pipe", "pipe", "pipe"]
|
|
6656
6905
|
}).trim();
|
|
@@ -6660,17 +6909,15 @@ function getCurrentHeadSha() {
|
|
|
6660
6909
|
}
|
|
6661
6910
|
|
|
6662
6911
|
// src/utils/prompt.ts
|
|
6663
|
-
import
|
|
6664
|
-
|
|
6665
|
-
|
|
6666
|
-
|
|
6667
|
-
|
|
6668
|
-
|
|
6669
|
-
|
|
6670
|
-
|
|
6671
|
-
|
|
6672
|
-
});
|
|
6673
|
-
});
|
|
6912
|
+
import input from "@inquirer/input";
|
|
6913
|
+
async function promptInput(question) {
|
|
6914
|
+
if (!process.stdin.isTTY) return "";
|
|
6915
|
+
try {
|
|
6916
|
+
const answer = await input({ message: question });
|
|
6917
|
+
return answer.trim();
|
|
6918
|
+
} catch {
|
|
6919
|
+
return "";
|
|
6920
|
+
}
|
|
6674
6921
|
}
|
|
6675
6922
|
|
|
6676
6923
|
// src/commands/init.ts
|
|
@@ -6678,12 +6925,13 @@ init_config();
|
|
|
6678
6925
|
|
|
6679
6926
|
// src/commands/interactive-provider-setup.ts
|
|
6680
6927
|
init_config();
|
|
6681
|
-
import
|
|
6928
|
+
import chalk2 from "chalk";
|
|
6682
6929
|
import select2 from "@inquirer/select";
|
|
6683
6930
|
import confirm from "@inquirer/confirm";
|
|
6684
|
-
var
|
|
6931
|
+
var IS_WINDOWS4 = process.platform === "win32";
|
|
6685
6932
|
var PROVIDER_CHOICES = [
|
|
6686
6933
|
{ name: "Claude Code \u2014 use your existing subscription (no API key)", value: "claude-cli" },
|
|
6934
|
+
{ name: "OpenCode \u2014 use your existing subscription (no API key)", value: "opencode" },
|
|
6687
6935
|
{ name: "Cursor \u2014 use your existing subscription (no API key)", value: "cursor" },
|
|
6688
6936
|
{ name: "Anthropic \u2014 API key from console.anthropic.com", value: "anthropic" },
|
|
6689
6937
|
{ name: "Google Vertex AI \u2014 Claude models via GCP", value: "vertex" },
|
|
@@ -6701,55 +6949,68 @@ async function runInteractiveProviderSetup(options) {
|
|
|
6701
6949
|
case "claude-cli": {
|
|
6702
6950
|
config.model = "default";
|
|
6703
6951
|
if (!isClaudeCliAvailable()) {
|
|
6704
|
-
console.log(
|
|
6952
|
+
console.log(chalk2.yellow("\n Claude Code CLI not found."));
|
|
6705
6953
|
console.log(
|
|
6706
|
-
|
|
6954
|
+
chalk2.dim(" Install it: ") + chalk2.hex("#83D1EB")("npm install -g @anthropic-ai/claude-code")
|
|
6707
6955
|
);
|
|
6708
6956
|
console.log(
|
|
6709
|
-
|
|
6957
|
+
chalk2.dim(" Then run ") + chalk2.hex("#83D1EB")("claude") + chalk2.dim(" once to log in.\n")
|
|
6710
6958
|
);
|
|
6711
6959
|
const proceed = await confirm({ message: "Continue anyway?" });
|
|
6712
6960
|
if (!proceed) throw new Error("__exit__");
|
|
6713
6961
|
} else if (!isClaudeCliLoggedIn()) {
|
|
6714
|
-
console.log(
|
|
6962
|
+
console.log(chalk2.yellow("\n Claude Code CLI found but not logged in."));
|
|
6715
6963
|
console.log(
|
|
6716
|
-
|
|
6964
|
+
chalk2.dim(" Run ") + chalk2.hex("#83D1EB")("claude") + chalk2.dim(" once to log in.\n")
|
|
6717
6965
|
);
|
|
6718
6966
|
const proceed = await confirm({ message: "Continue anyway?" });
|
|
6719
6967
|
if (!proceed) throw new Error("__exit__");
|
|
6720
6968
|
} else {
|
|
6721
6969
|
console.log(
|
|
6722
|
-
|
|
6970
|
+
chalk2.dim(
|
|
6723
6971
|
" Run `claude` once and log in with your Pro/Max/Team account if you haven't."
|
|
6724
6972
|
)
|
|
6725
6973
|
);
|
|
6726
6974
|
}
|
|
6727
6975
|
break;
|
|
6728
6976
|
}
|
|
6977
|
+
case "opencode": {
|
|
6978
|
+
if (!isOpenCodeAvailable()) {
|
|
6979
|
+
console.log(chalk2.yellow("\n OpenCode CLI not found."));
|
|
6980
|
+
console.log(chalk2.dim(" Install it from: ") + chalk2.hex("#83D1EB")("https://opencode.ai"));
|
|
6981
|
+
console.log(
|
|
6982
|
+
chalk2.dim(" Then run ") + chalk2.hex("#83D1EB")("opencode auth login") + chalk2.dim(" to authenticate.\n")
|
|
6983
|
+
);
|
|
6984
|
+
const proceed = await confirm({ message: "Continue anyway?" });
|
|
6985
|
+
if (!proceed) throw new Error("__exit__");
|
|
6986
|
+
}
|
|
6987
|
+
config.model = await promptInput(`Model (default: ${DEFAULT_MODELS.opencode}):`) || DEFAULT_MODELS.opencode;
|
|
6988
|
+
break;
|
|
6989
|
+
}
|
|
6729
6990
|
case "cursor": {
|
|
6730
6991
|
if (!isCursorAgentAvailable()) {
|
|
6731
|
-
console.log(
|
|
6732
|
-
if (
|
|
6992
|
+
console.log(chalk2.yellow("\n Cursor Agent CLI not found."));
|
|
6993
|
+
if (IS_WINDOWS4) {
|
|
6733
6994
|
console.log(
|
|
6734
|
-
|
|
6995
|
+
chalk2.dim(" Install it from: ") + chalk2.hex("#83D1EB")("https://www.cursor.com/downloads")
|
|
6735
6996
|
);
|
|
6736
6997
|
console.log(
|
|
6737
|
-
|
|
6998
|
+
chalk2.dim(" Then run ") + chalk2.hex("#83D1EB")("agent login") + chalk2.dim(" in PowerShell to authenticate.\n")
|
|
6738
6999
|
);
|
|
6739
7000
|
} else {
|
|
6740
7001
|
console.log(
|
|
6741
|
-
|
|
7002
|
+
chalk2.dim(" Install it: ") + chalk2.hex("#83D1EB")("curl https://cursor.com/install -fsS | bash")
|
|
6742
7003
|
);
|
|
6743
7004
|
console.log(
|
|
6744
|
-
|
|
7005
|
+
chalk2.dim(" Then run ") + chalk2.hex("#83D1EB")("agent login") + chalk2.dim(" to authenticate.\n")
|
|
6745
7006
|
);
|
|
6746
7007
|
}
|
|
6747
7008
|
const proceed = await confirm({ message: "Continue anyway?" });
|
|
6748
7009
|
if (!proceed) throw new Error("__exit__");
|
|
6749
7010
|
} else if (!isCursorLoggedIn()) {
|
|
6750
|
-
console.log(
|
|
7011
|
+
console.log(chalk2.yellow("\n Cursor Agent CLI found but not logged in."));
|
|
6751
7012
|
console.log(
|
|
6752
|
-
|
|
7013
|
+
chalk2.dim(" Run ") + chalk2.hex("#83D1EB")("agent login") + chalk2.dim(" to authenticate.\n")
|
|
6753
7014
|
);
|
|
6754
7015
|
const proceed = await confirm({ message: "Continue anyway?" });
|
|
6755
7016
|
if (!proceed) throw new Error("__exit__");
|
|
@@ -6759,13 +7020,13 @@ async function runInteractiveProviderSetup(options) {
|
|
|
6759
7020
|
}
|
|
6760
7021
|
case "anthropic": {
|
|
6761
7022
|
console.log(
|
|
6762
|
-
|
|
7023
|
+
chalk2.dim(
|
|
6763
7024
|
" Get a key at https://console.anthropic.com (same account as Claude Pro/Team/Max)."
|
|
6764
7025
|
)
|
|
6765
7026
|
);
|
|
6766
7027
|
config.apiKey = await promptInput("Anthropic API key:");
|
|
6767
7028
|
if (!config.apiKey) {
|
|
6768
|
-
console.log(
|
|
7029
|
+
console.log(chalk2.red("API key is required."));
|
|
6769
7030
|
throw new Error("__exit__");
|
|
6770
7031
|
}
|
|
6771
7032
|
config.model = await promptInput(`Model (default: ${DEFAULT_MODELS.anthropic}):`) || DEFAULT_MODELS.anthropic;
|
|
@@ -6774,7 +7035,7 @@ async function runInteractiveProviderSetup(options) {
|
|
|
6774
7035
|
case "vertex": {
|
|
6775
7036
|
config.vertexProjectId = await promptInput("GCP Project ID:");
|
|
6776
7037
|
if (!config.vertexProjectId) {
|
|
6777
|
-
console.log(
|
|
7038
|
+
console.log(chalk2.red("Project ID is required."));
|
|
6778
7039
|
throw new Error("__exit__");
|
|
6779
7040
|
}
|
|
6780
7041
|
config.vertexRegion = await promptInput("Region (default: us-east5):") || "us-east5";
|
|
@@ -6785,7 +7046,7 @@ async function runInteractiveProviderSetup(options) {
|
|
|
6785
7046
|
case "openai": {
|
|
6786
7047
|
config.apiKey = await promptInput("API key:");
|
|
6787
7048
|
if (!config.apiKey) {
|
|
6788
|
-
console.log(
|
|
7049
|
+
console.log(chalk2.red("API key is required."));
|
|
6789
7050
|
throw new Error("__exit__");
|
|
6790
7051
|
}
|
|
6791
7052
|
config.baseUrl = await promptInput("Base URL (leave empty for OpenAI, or enter custom endpoint):") || void 0;
|
|
@@ -6793,10 +7054,10 @@ async function runInteractiveProviderSetup(options) {
|
|
|
6793
7054
|
break;
|
|
6794
7055
|
}
|
|
6795
7056
|
case "minimax": {
|
|
6796
|
-
console.log(
|
|
7057
|
+
console.log(chalk2.dim(" Get a key at https://platform.minimax.io"));
|
|
6797
7058
|
config.apiKey = await promptInput("MiniMax API key:");
|
|
6798
7059
|
if (!config.apiKey) {
|
|
6799
|
-
console.log(
|
|
7060
|
+
console.log(chalk2.red("API key is required."));
|
|
6800
7061
|
throw new Error("__exit__");
|
|
6801
7062
|
}
|
|
6802
7063
|
config.model = await promptInput(`Model (default: ${DEFAULT_MODELS.minimax}):`) || DEFAULT_MODELS.minimax;
|
|
@@ -7336,7 +7597,7 @@ function checkGrounding(dir) {
|
|
|
7336
7597
|
|
|
7337
7598
|
// src/scoring/checks/accuracy.ts
|
|
7338
7599
|
import { existsSync as existsSync4, statSync } from "fs";
|
|
7339
|
-
import { execSync as
|
|
7600
|
+
import { execSync as execSync12 } from "child_process";
|
|
7340
7601
|
import { join as join5 } from "path";
|
|
7341
7602
|
init_resolve_caliber();
|
|
7342
7603
|
function validateReferences(dir) {
|
|
@@ -7346,13 +7607,13 @@ function validateReferences(dir) {
|
|
|
7346
7607
|
}
|
|
7347
7608
|
function detectGitDrift(dir) {
|
|
7348
7609
|
try {
|
|
7349
|
-
|
|
7610
|
+
execSync12("git rev-parse --git-dir", { cwd: dir, stdio: ["pipe", "pipe", "pipe"] });
|
|
7350
7611
|
} catch {
|
|
7351
7612
|
return { commitsSinceConfigUpdate: 0, lastConfigCommit: null, isGitRepo: false };
|
|
7352
7613
|
}
|
|
7353
7614
|
const configFiles = ["CLAUDE.md", "AGENTS.md", ".cursorrules", ".cursor/rules"];
|
|
7354
7615
|
try {
|
|
7355
|
-
const headTimestamp =
|
|
7616
|
+
const headTimestamp = execSync12(
|
|
7356
7617
|
"git log -1 --format=%ct HEAD",
|
|
7357
7618
|
{ cwd: dir, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
7358
7619
|
).trim();
|
|
@@ -7373,7 +7634,7 @@ function detectGitDrift(dir) {
|
|
|
7373
7634
|
let latestConfigCommitHash = null;
|
|
7374
7635
|
for (const file of configFiles) {
|
|
7375
7636
|
try {
|
|
7376
|
-
const hash =
|
|
7637
|
+
const hash = execSync12(
|
|
7377
7638
|
`git log -1 --format=%H -- "${file}"`,
|
|
7378
7639
|
{ cwd: dir, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
7379
7640
|
).trim();
|
|
@@ -7382,7 +7643,7 @@ function detectGitDrift(dir) {
|
|
|
7382
7643
|
latestConfigCommitHash = hash;
|
|
7383
7644
|
} else {
|
|
7384
7645
|
try {
|
|
7385
|
-
|
|
7646
|
+
execSync12(
|
|
7386
7647
|
`git merge-base --is-ancestor ${latestConfigCommitHash} ${hash}`,
|
|
7387
7648
|
{ cwd: dir, stdio: ["pipe", "pipe", "pipe"] }
|
|
7388
7649
|
);
|
|
@@ -7397,12 +7658,12 @@ function detectGitDrift(dir) {
|
|
|
7397
7658
|
return { commitsSinceConfigUpdate: 0, lastConfigCommit: null, isGitRepo: true };
|
|
7398
7659
|
}
|
|
7399
7660
|
try {
|
|
7400
|
-
const countStr =
|
|
7661
|
+
const countStr = execSync12(
|
|
7401
7662
|
`git rev-list --count ${latestConfigCommitHash}..HEAD`,
|
|
7402
7663
|
{ cwd: dir, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
7403
7664
|
).trim();
|
|
7404
7665
|
const commitsSince = parseInt(countStr, 10) || 0;
|
|
7405
|
-
const lastDate =
|
|
7666
|
+
const lastDate = execSync12(
|
|
7406
7667
|
`git log -1 --format=%ci ${latestConfigCommitHash}`,
|
|
7407
7668
|
{ cwd: dir, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
7408
7669
|
).trim();
|
|
@@ -7475,12 +7736,12 @@ function checkAccuracy(dir) {
|
|
|
7475
7736
|
// src/scoring/checks/freshness.ts
|
|
7476
7737
|
init_resolve_caliber();
|
|
7477
7738
|
import { existsSync as existsSync5, statSync as statSync2 } from "fs";
|
|
7478
|
-
import { execSync as
|
|
7739
|
+
import { execSync as execSync13 } from "child_process";
|
|
7479
7740
|
import { join as join6 } from "path";
|
|
7480
7741
|
function getCommitsSinceConfigUpdate(dir) {
|
|
7481
7742
|
const configFiles = ["CLAUDE.md", "AGENTS.md", ".cursorrules"];
|
|
7482
7743
|
try {
|
|
7483
|
-
const headTimestamp =
|
|
7744
|
+
const headTimestamp = execSync13(
|
|
7484
7745
|
"git log -1 --format=%ct HEAD",
|
|
7485
7746
|
{ cwd: dir, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
7486
7747
|
).trim();
|
|
@@ -7500,12 +7761,12 @@ function getCommitsSinceConfigUpdate(dir) {
|
|
|
7500
7761
|
}
|
|
7501
7762
|
for (const file of configFiles) {
|
|
7502
7763
|
try {
|
|
7503
|
-
const hash =
|
|
7764
|
+
const hash = execSync13(
|
|
7504
7765
|
`git log -1 --format=%H -- "${file}"`,
|
|
7505
7766
|
{ cwd: dir, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
7506
7767
|
).trim();
|
|
7507
7768
|
if (hash) {
|
|
7508
|
-
const countStr =
|
|
7769
|
+
const countStr = execSync13(
|
|
7509
7770
|
`git rev-list --count ${hash}..HEAD`,
|
|
7510
7771
|
{ cwd: dir, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
7511
7772
|
).trim();
|
|
@@ -7623,7 +7884,7 @@ function checkFreshness(dir) {
|
|
|
7623
7884
|
|
|
7624
7885
|
// src/scoring/checks/bonus.ts
|
|
7625
7886
|
import { existsSync as existsSync6, readdirSync as readdirSync3 } from "fs";
|
|
7626
|
-
import { execSync as
|
|
7887
|
+
import { execSync as execSync14 } from "child_process";
|
|
7627
7888
|
import { join as join7 } from "path";
|
|
7628
7889
|
init_resolve_caliber();
|
|
7629
7890
|
init_pre_commit_block();
|
|
@@ -7642,7 +7903,7 @@ function configContentSuggestsPinnedModel(lower) {
|
|
|
7642
7903
|
// src/scoring/checks/bonus.ts
|
|
7643
7904
|
function hasPreCommitHook(dir) {
|
|
7644
7905
|
try {
|
|
7645
|
-
const gitDir =
|
|
7906
|
+
const gitDir = execSync14("git rev-parse --git-dir", {
|
|
7646
7907
|
cwd: dir,
|
|
7647
7908
|
encoding: "utf-8",
|
|
7648
7909
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -7920,7 +8181,7 @@ function computeLocalScore(dir, targetAgent) {
|
|
|
7920
8181
|
|
|
7921
8182
|
// src/scoring/display.ts
|
|
7922
8183
|
init_resolve_caliber();
|
|
7923
|
-
import
|
|
8184
|
+
import chalk3 from "chalk";
|
|
7924
8185
|
var AGENT_DISPLAY_NAMES = {
|
|
7925
8186
|
claude: "Claude Code",
|
|
7926
8187
|
cursor: "Cursor",
|
|
@@ -7938,17 +8199,17 @@ var CATEGORY_ORDER = ["existence", "quality", "grounding", "accuracy", "freshnes
|
|
|
7938
8199
|
function gradeColor(grade) {
|
|
7939
8200
|
switch (grade) {
|
|
7940
8201
|
case "A":
|
|
7941
|
-
return
|
|
8202
|
+
return chalk3.green;
|
|
7942
8203
|
case "B":
|
|
7943
|
-
return
|
|
8204
|
+
return chalk3.greenBright;
|
|
7944
8205
|
case "C":
|
|
7945
|
-
return
|
|
8206
|
+
return chalk3.yellow;
|
|
7946
8207
|
case "D":
|
|
7947
|
-
return
|
|
8208
|
+
return chalk3.hex("#f97316");
|
|
7948
8209
|
case "F":
|
|
7949
|
-
return
|
|
8210
|
+
return chalk3.red;
|
|
7950
8211
|
default:
|
|
7951
|
-
return
|
|
8212
|
+
return chalk3.white;
|
|
7952
8213
|
}
|
|
7953
8214
|
}
|
|
7954
8215
|
var GRADIENT_COLORS = ["#ef4444", "#f97316", "#eab308", "#22c55e"];
|
|
@@ -7962,37 +8223,37 @@ function progressBar(score, max, width = 40) {
|
|
|
7962
8223
|
GRADIENT_COLORS.length - 1,
|
|
7963
8224
|
Math.floor(position * GRADIENT_COLORS.length)
|
|
7964
8225
|
);
|
|
7965
|
-
bar +=
|
|
8226
|
+
bar += chalk3.hex(GRADIENT_COLORS[colorIndex])("\u2593");
|
|
7966
8227
|
}
|
|
7967
|
-
bar +=
|
|
8228
|
+
bar += chalk3.gray("\u2591".repeat(empty));
|
|
7968
8229
|
return bar;
|
|
7969
8230
|
}
|
|
7970
8231
|
function formatCheck(check) {
|
|
7971
8232
|
const isPartial = !check.passed && check.earnedPoints > 0;
|
|
7972
8233
|
const isNegative = check.earnedPoints < 0;
|
|
7973
8234
|
const lostPoints = check.maxPoints - check.earnedPoints;
|
|
7974
|
-
const icon = check.passed ?
|
|
8235
|
+
const icon = check.passed ? chalk3.green("\u2713") : isPartial ? chalk3.yellow("~") : isNegative ? chalk3.red("\u2717") : chalk3.gray("\u2717");
|
|
7975
8236
|
let points;
|
|
7976
8237
|
if (check.passed) {
|
|
7977
|
-
points =
|
|
8238
|
+
points = chalk3.green(`+${check.earnedPoints}`.padStart(4));
|
|
7978
8239
|
} else if (isNegative) {
|
|
7979
|
-
points =
|
|
8240
|
+
points = chalk3.red(`${check.earnedPoints}`.padStart(4));
|
|
7980
8241
|
} else if (isPartial) {
|
|
7981
|
-
points =
|
|
8242
|
+
points = chalk3.yellow(`${check.earnedPoints}/${check.maxPoints}`.padStart(5));
|
|
7982
8243
|
} else {
|
|
7983
|
-
points =
|
|
8244
|
+
points = chalk3.gray(`0/${check.maxPoints}`.padStart(5));
|
|
7984
8245
|
}
|
|
7985
|
-
const name = check.passed ?
|
|
7986
|
-
const detail = check.detail ?
|
|
8246
|
+
const name = check.passed ? chalk3.white(check.name) : isNegative ? chalk3.red(check.name) : isPartial ? chalk3.white(check.name) : chalk3.gray(check.name);
|
|
8247
|
+
const detail = check.detail ? chalk3.gray(` (${check.detail})`) : "";
|
|
7987
8248
|
let suggestion = "";
|
|
7988
8249
|
if (!check.passed && check.suggestion) {
|
|
7989
|
-
const suggColor = isNegative ?
|
|
8250
|
+
const suggColor = isNegative ? chalk3.red : chalk3.yellow;
|
|
7990
8251
|
suggestion = suggColor(`
|
|
7991
8252
|
\u2192 ${check.suggestion}`);
|
|
7992
8253
|
}
|
|
7993
8254
|
let recovery = "";
|
|
7994
8255
|
if (isPartial && lostPoints > 0) {
|
|
7995
|
-
recovery =
|
|
8256
|
+
recovery = chalk3.yellow(`
|
|
7996
8257
|
\u2191 Fix this for +${lostPoints} more points`);
|
|
7997
8258
|
}
|
|
7998
8259
|
return ` ${icon} ${name.padEnd(38)}${points}${detail}${suggestion}${recovery}`;
|
|
@@ -8001,22 +8262,22 @@ function displayScore(result) {
|
|
|
8001
8262
|
const gc = gradeColor(result.grade);
|
|
8002
8263
|
const agentLabel = result.targetAgent.map((a) => AGENT_DISPLAY_NAMES[a] || a).join(" + ");
|
|
8003
8264
|
console.log("");
|
|
8004
|
-
console.log(
|
|
8265
|
+
console.log(chalk3.gray(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
8005
8266
|
console.log("");
|
|
8006
|
-
console.log(` ${
|
|
8267
|
+
console.log(` ${chalk3.bold("Agent Config Score")} ${gc(chalk3.bold(`${result.score} / ${result.maxScore}`))} Grade ${gc(chalk3.bold(result.grade))}`);
|
|
8007
8268
|
console.log(` ${progressBar(result.score, result.maxScore)}`);
|
|
8008
|
-
console.log(
|
|
8269
|
+
console.log(chalk3.dim(` Target: ${agentLabel}`));
|
|
8009
8270
|
console.log("");
|
|
8010
|
-
console.log(
|
|
8271
|
+
console.log(chalk3.gray(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
8011
8272
|
console.log("");
|
|
8012
8273
|
for (const category of CATEGORY_ORDER) {
|
|
8013
8274
|
const summary = result.categories[category];
|
|
8014
8275
|
const categoryChecks = result.checks.filter((c) => c.category === category);
|
|
8015
8276
|
const { icon, label } = CATEGORY_LABELS[category];
|
|
8016
8277
|
const gap = summary.max - summary.earned;
|
|
8017
|
-
const gapLabel = gap > 0 ?
|
|
8278
|
+
const gapLabel = gap > 0 ? chalk3.yellow(` (-${gap} available)`) : "";
|
|
8018
8279
|
console.log(
|
|
8019
|
-
|
|
8280
|
+
chalk3.gray(` ${icon} ${label}`) + chalk3.gray(" ".repeat(Math.max(1, 43 - label.length))) + chalk3.white(`${summary.earned}`) + chalk3.gray(` / ${summary.max}`) + gapLabel
|
|
8020
8281
|
);
|
|
8021
8282
|
for (const check of categoryChecks) {
|
|
8022
8283
|
console.log(formatCheck(check));
|
|
@@ -8028,16 +8289,16 @@ function displayScore(result) {
|
|
|
8028
8289
|
function formatTopImprovements(checks) {
|
|
8029
8290
|
const improvable = checks.filter((c) => c.earnedPoints < c.maxPoints).map((c) => ({ name: c.name, potential: c.maxPoints - c.earnedPoints, suggestion: c.suggestion })).sort((a, b) => b.potential - a.potential).slice(0, 5);
|
|
8030
8291
|
if (improvable.length === 0) return;
|
|
8031
|
-
console.log(
|
|
8292
|
+
console.log(chalk3.gray(" \u2500 TOP IMPROVEMENTS \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
8032
8293
|
console.log("");
|
|
8033
8294
|
for (let i = 0; i < improvable.length; i++) {
|
|
8034
8295
|
const item = improvable[i];
|
|
8035
|
-
const num =
|
|
8036
|
-
const label =
|
|
8037
|
-
const pts =
|
|
8296
|
+
const num = chalk3.gray(`${i + 1}.`);
|
|
8297
|
+
const label = chalk3.white(item.name.padEnd(42));
|
|
8298
|
+
const pts = chalk3.yellow(`+${item.potential} pts`);
|
|
8038
8299
|
console.log(` ${num} ${label}${pts}`);
|
|
8039
8300
|
if (item.suggestion) {
|
|
8040
|
-
console.log(
|
|
8301
|
+
console.log(chalk3.gray(` ${item.suggestion}`));
|
|
8041
8302
|
}
|
|
8042
8303
|
}
|
|
8043
8304
|
console.log("");
|
|
@@ -8047,48 +8308,48 @@ function displayScoreSummary(result) {
|
|
|
8047
8308
|
const agentLabel = result.targetAgent.map((a) => AGENT_DISPLAY_NAMES[a] || a).join(" + ");
|
|
8048
8309
|
console.log("");
|
|
8049
8310
|
console.log(
|
|
8050
|
-
|
|
8311
|
+
chalk3.gray(" ") + gc(`${result.score}/${result.maxScore}`) + chalk3.gray(` (Grade ${result.grade})`) + chalk3.gray(` \xB7 ${agentLabel}`) + chalk3.gray(` \xB7 ${progressBar(result.score, result.maxScore, 20)}`)
|
|
8051
8312
|
);
|
|
8052
8313
|
const failing = result.checks.filter((c) => !c.passed);
|
|
8053
8314
|
if (failing.length > 0) {
|
|
8054
8315
|
const shown = failing.slice(0, 5);
|
|
8055
8316
|
for (const check of shown) {
|
|
8056
|
-
console.log(
|
|
8317
|
+
console.log(chalk3.gray(` \u2717 ${check.name}`));
|
|
8057
8318
|
}
|
|
8058
8319
|
const remaining = failing.length - shown.length;
|
|
8059
8320
|
const moreText = remaining > 0 ? ` (+${remaining} more)` : "";
|
|
8060
|
-
console.log(
|
|
8061
|
-
Run ${
|
|
8321
|
+
console.log(chalk3.dim(`
|
|
8322
|
+
Run ${chalk3.hex("#83D1EB")(`${resolveCaliber()} score`)} for details.${moreText}`));
|
|
8062
8323
|
}
|
|
8063
8324
|
console.log("");
|
|
8064
8325
|
}
|
|
8065
8326
|
function displayScoreDelta(before, after) {
|
|
8066
8327
|
const delta = after.score - before.score;
|
|
8067
8328
|
const deltaStr = delta >= 0 ? `+${delta}` : `${delta}`;
|
|
8068
|
-
const deltaColor = delta >= 0 ?
|
|
8329
|
+
const deltaColor = delta >= 0 ? chalk3.green : chalk3.red;
|
|
8069
8330
|
const beforeGc = gradeColor(before.grade);
|
|
8070
8331
|
const afterGc = gradeColor(after.grade);
|
|
8071
8332
|
console.log("");
|
|
8072
|
-
console.log(
|
|
8333
|
+
console.log(chalk3.gray(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
8073
8334
|
console.log("");
|
|
8074
8335
|
console.log(
|
|
8075
|
-
` Score: ${beforeGc(`${before.score}`)} ${
|
|
8336
|
+
` Score: ${beforeGc(`${before.score}`)} ${chalk3.gray("\u2192")} ${afterGc(`${after.score}`)} ${deltaColor(deltaStr + " pts")} ${beforeGc(before.grade)} ${chalk3.gray("\u2192")} ${afterGc(after.grade)}`
|
|
8076
8337
|
);
|
|
8077
|
-
console.log(` ${progressBar(before.score, before.maxScore, 19)} ${
|
|
8338
|
+
console.log(` ${progressBar(before.score, before.maxScore, 19)} ${chalk3.gray("\u2192")} ${progressBar(after.score, after.maxScore, 19)}`);
|
|
8078
8339
|
console.log("");
|
|
8079
|
-
console.log(
|
|
8340
|
+
console.log(chalk3.gray(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
8080
8341
|
console.log("");
|
|
8081
8342
|
const improved = after.checks.filter((ac) => {
|
|
8082
8343
|
const bc = before.checks.find((b) => b.id === ac.id);
|
|
8083
8344
|
return bc && ac.earnedPoints > bc.earnedPoints;
|
|
8084
8345
|
});
|
|
8085
8346
|
if (improved.length > 0) {
|
|
8086
|
-
console.log(
|
|
8347
|
+
console.log(chalk3.gray(" What improved:"));
|
|
8087
8348
|
for (const check of improved) {
|
|
8088
8349
|
const bc = before.checks.find((b) => b.id === check.id);
|
|
8089
8350
|
const gain = check.earnedPoints - bc.earnedPoints;
|
|
8090
8351
|
console.log(
|
|
8091
|
-
|
|
8352
|
+
chalk3.green(" +") + chalk3.white(` ${check.name.padEnd(50)}`) + chalk3.green(`+${gain}`)
|
|
8092
8353
|
);
|
|
8093
8354
|
}
|
|
8094
8355
|
console.log("");
|
|
@@ -8096,7 +8357,7 @@ function displayScoreDelta(before, after) {
|
|
|
8096
8357
|
}
|
|
8097
8358
|
|
|
8098
8359
|
// src/commands/recommend.ts
|
|
8099
|
-
import
|
|
8360
|
+
import chalk5 from "chalk";
|
|
8100
8361
|
import ora from "ora";
|
|
8101
8362
|
import select3 from "@inquirer/select";
|
|
8102
8363
|
import { mkdirSync, readFileSync as readFileSync4, readdirSync as readdirSync4, existsSync as existsSync8, writeFileSync } from "fs";
|
|
@@ -8105,14 +8366,14 @@ init_config();
|
|
|
8105
8366
|
|
|
8106
8367
|
// src/telemetry/index.ts
|
|
8107
8368
|
import { PostHog } from "posthog-node";
|
|
8108
|
-
import
|
|
8369
|
+
import chalk4 from "chalk";
|
|
8109
8370
|
|
|
8110
8371
|
// src/telemetry/config.ts
|
|
8111
8372
|
import fs27 from "fs";
|
|
8112
8373
|
import path23 from "path";
|
|
8113
8374
|
import os5 from "os";
|
|
8114
8375
|
import crypto4 from "crypto";
|
|
8115
|
-
import { execSync as
|
|
8376
|
+
import { execSync as execSync15 } from "child_process";
|
|
8116
8377
|
var CONFIG_DIR2 = path23.join(os5.homedir(), ".caliber");
|
|
8117
8378
|
var CONFIG_FILE2 = path23.join(CONFIG_DIR2, "config.json");
|
|
8118
8379
|
var runtimeDisabled = false;
|
|
@@ -8164,7 +8425,7 @@ var PERSONAL_DOMAINS = /* @__PURE__ */ new Set([
|
|
|
8164
8425
|
]);
|
|
8165
8426
|
function getGitEmail() {
|
|
8166
8427
|
try {
|
|
8167
|
-
const email =
|
|
8428
|
+
const email = execSync15("git config user.email", { encoding: "utf-8" }).trim();
|
|
8168
8429
|
return email || void 0;
|
|
8169
8430
|
} catch {
|
|
8170
8431
|
return void 0;
|
|
@@ -8183,7 +8444,7 @@ function getGitEmailInfo() {
|
|
|
8183
8444
|
}
|
|
8184
8445
|
function getRepoHash() {
|
|
8185
8446
|
try {
|
|
8186
|
-
const remote =
|
|
8447
|
+
const remote = execSync15("git remote get-url origin || git rev-parse --show-toplevel", {
|
|
8187
8448
|
encoding: "utf-8",
|
|
8188
8449
|
stdio: ["pipe", "pipe", "pipe"]
|
|
8189
8450
|
}).trim();
|
|
@@ -8225,7 +8486,7 @@ function initTelemetry() {
|
|
|
8225
8486
|
});
|
|
8226
8487
|
if (!wasNoticeShown()) {
|
|
8227
8488
|
console.log(
|
|
8228
|
-
|
|
8489
|
+
chalk4.dim(" Caliber collects anonymous usage data to improve the product.") + "\n" + chalk4.dim(" Disable with --no-traces or CALIBER_TELEMETRY_DISABLED=1\n")
|
|
8229
8490
|
);
|
|
8230
8491
|
markNoticeShown();
|
|
8231
8492
|
}
|
|
@@ -8693,7 +8954,7 @@ async function searchSkills(fingerprint, targetPlatforms, onStatus) {
|
|
|
8693
8954
|
async function querySkills(query) {
|
|
8694
8955
|
const terms = query.split(/[\s,]+/).filter(Boolean);
|
|
8695
8956
|
if (terms.length === 0) {
|
|
8696
|
-
console.log(
|
|
8957
|
+
console.log(chalk5.yellow("Please provide search terms."));
|
|
8697
8958
|
throw new Error("__exit__");
|
|
8698
8959
|
}
|
|
8699
8960
|
const platforms = detectLocalPlatforms();
|
|
@@ -8741,7 +9002,7 @@ async function querySkills(query) {
|
|
|
8741
9002
|
const available = top.filter((r) => contentMap.has(r.slug));
|
|
8742
9003
|
fetchSpinner.succeed(`${available.length} available`);
|
|
8743
9004
|
if (!available.length) {
|
|
8744
|
-
console.log(
|
|
9005
|
+
console.log(chalk5.dim(" No installable skills found.\n"));
|
|
8745
9006
|
return;
|
|
8746
9007
|
}
|
|
8747
9008
|
console.log("");
|
|
@@ -8753,7 +9014,7 @@ async function querySkills(query) {
|
|
|
8753
9014
|
}
|
|
8754
9015
|
console.log("");
|
|
8755
9016
|
console.log(
|
|
8756
|
-
|
|
9017
|
+
chalk5.dim(
|
|
8757
9018
|
` Install with: ${resolveCaliber()} skills --install ${available.map((r) => r.slug).join(",")}`
|
|
8758
9019
|
)
|
|
8759
9020
|
);
|
|
@@ -8762,7 +9023,7 @@ async function querySkills(query) {
|
|
|
8762
9023
|
async function installBySlug(slugStr) {
|
|
8763
9024
|
const slugs = slugStr.split(",").map((s) => s.trim()).filter(Boolean);
|
|
8764
9025
|
if (slugs.length === 0) {
|
|
8765
|
-
console.log(
|
|
9026
|
+
console.log(chalk5.yellow("Please provide skill slugs to install."));
|
|
8766
9027
|
throw new Error("__exit__");
|
|
8767
9028
|
}
|
|
8768
9029
|
const platforms = detectLocalPlatforms();
|
|
@@ -8802,7 +9063,7 @@ async function recommendCommand(options) {
|
|
|
8802
9063
|
return;
|
|
8803
9064
|
}
|
|
8804
9065
|
if (!process.stdin.isTTY) {
|
|
8805
|
-
console.log(
|
|
9066
|
+
console.log(chalk5.dim(" Skills search requires an interactive terminal."));
|
|
8806
9067
|
return;
|
|
8807
9068
|
}
|
|
8808
9069
|
const proceed = await select3({
|
|
@@ -8813,7 +9074,7 @@ async function recommendCommand(options) {
|
|
|
8813
9074
|
]
|
|
8814
9075
|
});
|
|
8815
9076
|
if (!proceed) {
|
|
8816
|
-
console.log(
|
|
9077
|
+
console.log(chalk5.dim(" Cancelled.\n"));
|
|
8817
9078
|
return;
|
|
8818
9079
|
}
|
|
8819
9080
|
const state = readState();
|
|
@@ -8831,7 +9092,7 @@ async function searchAndInstallSkills(targetPlatforms) {
|
|
|
8831
9092
|
];
|
|
8832
9093
|
if (technologies.length === 0) {
|
|
8833
9094
|
console.log(
|
|
8834
|
-
|
|
9095
|
+
chalk5.yellow(
|
|
8835
9096
|
"Could not detect any languages or dependencies. Try running from a project root."
|
|
8836
9097
|
)
|
|
8837
9098
|
);
|
|
@@ -8851,7 +9112,7 @@ async function searchAndInstallSkills(targetPlatforms) {
|
|
|
8851
9112
|
return;
|
|
8852
9113
|
}
|
|
8853
9114
|
searchSpinner.succeed(
|
|
8854
|
-
`Found ${allCandidates.length} skills` + (filteredCount > 0 ?
|
|
9115
|
+
`Found ${allCandidates.length} skills` + (filteredCount > 0 ? chalk5.dim(` (${filteredCount} already installed)`) : "")
|
|
8855
9116
|
);
|
|
8856
9117
|
let results;
|
|
8857
9118
|
const config = loadConfig();
|
|
@@ -8889,7 +9150,7 @@ async function searchAndInstallSkills(targetPlatforms) {
|
|
|
8889
9150
|
}
|
|
8890
9151
|
const unavailableCount = results.length - available.length;
|
|
8891
9152
|
fetchSpinner.succeed(
|
|
8892
|
-
`${available.length} installable skill${available.length > 1 ? "s" : ""}` + (unavailableCount > 0 ?
|
|
9153
|
+
`${available.length} installable skill${available.length > 1 ? "s" : ""}` + (unavailableCount > 0 ? chalk5.dim(` (${unavailableCount} unavailable)`) : "")
|
|
8893
9154
|
);
|
|
8894
9155
|
const selected = await interactiveSelect(available);
|
|
8895
9156
|
if (selected?.length) {
|
|
@@ -8912,34 +9173,34 @@ async function interactiveSelect(recs) {
|
|
|
8912
9173
|
const nameWidth = Math.max(...recs.map((r) => r.name.length), 4) + 2;
|
|
8913
9174
|
const prefixWidth = 8;
|
|
8914
9175
|
const scoreWidth = 6;
|
|
8915
|
-
lines.push(
|
|
9176
|
+
lines.push(chalk5.bold(" Skills"));
|
|
8916
9177
|
lines.push("");
|
|
8917
9178
|
if (hasScores) {
|
|
8918
|
-
const header = " ".repeat(prefixWidth) +
|
|
9179
|
+
const header = " ".repeat(prefixWidth) + chalk5.dim("Score".padEnd(scoreWidth)) + chalk5.dim("Name".padEnd(nameWidth)) + chalk5.dim("Why");
|
|
8919
9180
|
lines.push(header);
|
|
8920
9181
|
} else {
|
|
8921
|
-
const header = " ".repeat(prefixWidth) +
|
|
9182
|
+
const header = " ".repeat(prefixWidth) + chalk5.dim("Name".padEnd(nameWidth)) + chalk5.dim("Technology".padEnd(18)) + chalk5.dim("Source");
|
|
8922
9183
|
lines.push(header);
|
|
8923
9184
|
}
|
|
8924
|
-
lines.push(
|
|
9185
|
+
lines.push(chalk5.dim(" " + "\u2500".repeat(Math.min(cols - 4, 90))));
|
|
8925
9186
|
for (let i = 0; i < recs.length; i++) {
|
|
8926
9187
|
const rec = recs[i];
|
|
8927
|
-
const check = selected.has(i) ?
|
|
8928
|
-
const ptr = i === cursor ?
|
|
9188
|
+
const check = selected.has(i) ? chalk5.green("[x]") : "[ ]";
|
|
9189
|
+
const ptr = i === cursor ? chalk5.cyan(">") : " ";
|
|
8929
9190
|
if (hasScores) {
|
|
8930
|
-
const scoreColor = rec.score >= 90 ?
|
|
9191
|
+
const scoreColor = rec.score >= 90 ? chalk5.green : rec.score >= 70 ? chalk5.yellow : chalk5.dim;
|
|
8931
9192
|
const reasonMax = Math.max(cols - prefixWidth - scoreWidth - nameWidth - 2, 20);
|
|
8932
9193
|
lines.push(
|
|
8933
|
-
` ${ptr} ${check} ${scoreColor(String(rec.score).padStart(3))} ${rec.name.padEnd(nameWidth)}${
|
|
9194
|
+
` ${ptr} ${check} ${scoreColor(String(rec.score).padStart(3))} ${rec.name.padEnd(nameWidth)}${chalk5.dim(rec.reason.slice(0, reasonMax))}`
|
|
8934
9195
|
);
|
|
8935
9196
|
} else {
|
|
8936
9197
|
lines.push(
|
|
8937
|
-
` ${ptr} ${check} ${rec.name.padEnd(nameWidth)}${rec.detected_technology.padEnd(16)} ${
|
|
9198
|
+
` ${ptr} ${check} ${rec.name.padEnd(nameWidth)}${rec.detected_technology.padEnd(16)} ${chalk5.dim(rec.source_url || "")}`
|
|
8938
9199
|
);
|
|
8939
9200
|
}
|
|
8940
9201
|
}
|
|
8941
9202
|
lines.push("");
|
|
8942
|
-
lines.push(
|
|
9203
|
+
lines.push(chalk5.dim(" \u2191\u2193 navigate \u23B5 toggle a all n none \u23CE install q cancel"));
|
|
8943
9204
|
return lines.join("\n");
|
|
8944
9205
|
}
|
|
8945
9206
|
function draw(initial) {
|
|
@@ -8988,7 +9249,7 @@ async function interactiveSelect(recs) {
|
|
|
8988
9249
|
case "\n":
|
|
8989
9250
|
cleanup();
|
|
8990
9251
|
if (selected.size === 0) {
|
|
8991
|
-
console.log(
|
|
9252
|
+
console.log(chalk5.dim("\n No skills selected.\n"));
|
|
8992
9253
|
resolve3(null);
|
|
8993
9254
|
} else {
|
|
8994
9255
|
resolve3(
|
|
@@ -9000,7 +9261,7 @@ async function interactiveSelect(recs) {
|
|
|
9000
9261
|
case "\x1B":
|
|
9001
9262
|
case "":
|
|
9002
9263
|
cleanup();
|
|
9003
|
-
console.log(
|
|
9264
|
+
console.log(chalk5.dim("\n Cancelled.\n"));
|
|
9004
9265
|
resolve3(null);
|
|
9005
9266
|
break;
|
|
9006
9267
|
}
|
|
@@ -9047,7 +9308,7 @@ async function installSkills(recs, platforms, contentMap) {
|
|
|
9047
9308
|
trackSkillsInstalled(installed.length);
|
|
9048
9309
|
spinner.succeed(`Installed ${installed.length} file${installed.length > 1 ? "s" : ""}`);
|
|
9049
9310
|
for (const p of installed) {
|
|
9050
|
-
console.log(
|
|
9311
|
+
console.log(chalk5.green(` \u2713 ${p}`));
|
|
9051
9312
|
}
|
|
9052
9313
|
} else {
|
|
9053
9314
|
spinner.fail("No skills were installed");
|
|
@@ -9060,26 +9321,26 @@ function printSkills(recs) {
|
|
|
9060
9321
|
const nameWidth = Math.max(...recs.map((r) => r.name.length), 4) + 2;
|
|
9061
9322
|
const scoreWidth = 6;
|
|
9062
9323
|
const prefixWidth = 2;
|
|
9063
|
-
console.log(
|
|
9324
|
+
console.log(chalk5.bold("\n Skills\n"));
|
|
9064
9325
|
if (hasScores) {
|
|
9065
9326
|
console.log(
|
|
9066
|
-
" ".repeat(prefixWidth) +
|
|
9327
|
+
" ".repeat(prefixWidth) + chalk5.dim("Score".padEnd(scoreWidth)) + chalk5.dim("Name".padEnd(nameWidth)) + chalk5.dim("Why")
|
|
9067
9328
|
);
|
|
9068
9329
|
} else {
|
|
9069
9330
|
console.log(
|
|
9070
|
-
" ".repeat(prefixWidth) +
|
|
9331
|
+
" ".repeat(prefixWidth) + chalk5.dim("Name".padEnd(nameWidth)) + chalk5.dim("Technology".padEnd(18)) + chalk5.dim("Source")
|
|
9071
9332
|
);
|
|
9072
9333
|
}
|
|
9073
|
-
console.log(
|
|
9334
|
+
console.log(chalk5.dim(" " + "\u2500".repeat(Math.min(cols - 4, 90))));
|
|
9074
9335
|
for (const rec of recs) {
|
|
9075
9336
|
if (hasScores) {
|
|
9076
9337
|
const reasonMax = Math.max(cols - prefixWidth - scoreWidth - nameWidth - 2, 20);
|
|
9077
9338
|
console.log(
|
|
9078
|
-
` ${String(rec.score).padStart(3)} ${rec.name.padEnd(nameWidth)}${
|
|
9339
|
+
` ${String(rec.score).padStart(3)} ${rec.name.padEnd(nameWidth)}${chalk5.dim(rec.reason.slice(0, reasonMax))}`
|
|
9079
9340
|
);
|
|
9080
9341
|
} else {
|
|
9081
9342
|
console.log(
|
|
9082
|
-
` ${rec.name.padEnd(nameWidth)}${rec.detected_technology.padEnd(16)} ${
|
|
9343
|
+
` ${rec.name.padEnd(nameWidth)}${rec.detected_technology.padEnd(16)} ${chalk5.dim(rec.source_url || "")}`
|
|
9083
9344
|
);
|
|
9084
9345
|
}
|
|
9085
9346
|
}
|
|
@@ -9559,10 +9820,10 @@ function formatMs(ms) {
|
|
|
9559
9820
|
}
|
|
9560
9821
|
|
|
9561
9822
|
// src/utils/parallel-tasks.ts
|
|
9562
|
-
import
|
|
9823
|
+
import chalk7 from "chalk";
|
|
9563
9824
|
|
|
9564
9825
|
// src/utils/waiting-content.ts
|
|
9565
|
-
import
|
|
9826
|
+
import chalk6 from "chalk";
|
|
9566
9827
|
|
|
9567
9828
|
// src/utils/waiting-cards.json
|
|
9568
9829
|
var waiting_cards_default = [
|
|
@@ -9650,8 +9911,8 @@ var waiting_cards_default = [
|
|
|
9650
9911
|
];
|
|
9651
9912
|
|
|
9652
9913
|
// src/utils/waiting-content.ts
|
|
9653
|
-
var ACCENT =
|
|
9654
|
-
var BRAND =
|
|
9914
|
+
var ACCENT = chalk6.hex("#83D1EB");
|
|
9915
|
+
var BRAND = chalk6.hex("#EB9D83");
|
|
9655
9916
|
var WAITING_CARDS = waiting_cards_default;
|
|
9656
9917
|
function highlightCommands(text) {
|
|
9657
9918
|
return text.replace(/`([^`]+)`/g, (_, cmd) => ACCENT(cmd));
|
|
@@ -9660,20 +9921,20 @@ function renderCard(card, index, total, cols) {
|
|
|
9660
9921
|
const prefix = " ";
|
|
9661
9922
|
const maxWidth = Math.min(cols - 8, 65);
|
|
9662
9923
|
const lines = [];
|
|
9663
|
-
lines.push(
|
|
9924
|
+
lines.push(chalk6.dim(`${prefix}${"\u2500".repeat(maxWidth)}`));
|
|
9664
9925
|
lines.push("");
|
|
9665
9926
|
const dots = Array.from(
|
|
9666
9927
|
{ length: total },
|
|
9667
|
-
(_, i) => i === index ? ACCENT("\u25CF") :
|
|
9928
|
+
(_, i) => i === index ? ACCENT("\u25CF") : chalk6.dim("\u25CB")
|
|
9668
9929
|
).join(" ");
|
|
9669
|
-
lines.push(`${prefix}${
|
|
9930
|
+
lines.push(`${prefix}${chalk6.dim("While you wait...")} ${dots}`);
|
|
9670
9931
|
lines.push("");
|
|
9671
|
-
lines.push(`${prefix}${BRAND(card.icon)} ${
|
|
9932
|
+
lines.push(`${prefix}${BRAND(card.icon)} ${chalk6.bold(card.title)}`);
|
|
9672
9933
|
for (const line of card.lines) {
|
|
9673
|
-
lines.push(`${prefix} ${
|
|
9934
|
+
lines.push(`${prefix} ${chalk6.dim(highlightCommands(line))}`);
|
|
9674
9935
|
}
|
|
9675
9936
|
lines.push("");
|
|
9676
|
-
lines.push(`${prefix}${
|
|
9937
|
+
lines.push(`${prefix}${chalk6.dim("\u2190 \u2192 navigate auto-advances every 15s")}`);
|
|
9677
9938
|
return lines;
|
|
9678
9939
|
}
|
|
9679
9940
|
|
|
@@ -9824,15 +10085,15 @@ var ParallelTaskDisplay = class {
|
|
|
9824
10085
|
statusIcon(task) {
|
|
9825
10086
|
switch (task.status) {
|
|
9826
10087
|
case "pending":
|
|
9827
|
-
return { char: "\u25CB", styled:
|
|
10088
|
+
return { char: "\u25CB", styled: chalk7.dim("\u25CB") };
|
|
9828
10089
|
case "running": {
|
|
9829
10090
|
const frame = SPINNER_FRAMES[this.spinnerFrame];
|
|
9830
|
-
return { char: frame, styled:
|
|
10091
|
+
return { char: frame, styled: chalk7.cyan(frame) };
|
|
9831
10092
|
}
|
|
9832
10093
|
case "done":
|
|
9833
|
-
return { char: "\u2713", styled:
|
|
10094
|
+
return { char: "\u2713", styled: chalk7.green("\u2713") };
|
|
9834
10095
|
case "failed":
|
|
9835
|
-
return { char: "\u2717", styled:
|
|
10096
|
+
return { char: "\u2717", styled: chalk7.red("\u2717") };
|
|
9836
10097
|
}
|
|
9837
10098
|
}
|
|
9838
10099
|
renderPipelineHeader() {
|
|
@@ -9840,14 +10101,14 @@ var ParallelTaskDisplay = class {
|
|
|
9840
10101
|
const branchTasks = this.tasks.filter((t) => t.pipelineLabel && t.pipelineRow === 1);
|
|
9841
10102
|
if (mainTasks.length === 0) return [];
|
|
9842
10103
|
const arrow = " \u2192 ";
|
|
9843
|
-
const styledArrow =
|
|
10104
|
+
const styledArrow = chalk7.dim(arrow);
|
|
9844
10105
|
const renderNode = (t) => {
|
|
9845
10106
|
const { char, styled: icon } = this.statusIcon(t);
|
|
9846
10107
|
const label = t.pipelineLabel;
|
|
9847
|
-
const styledLabel = t.status === "pending" ?
|
|
10108
|
+
const styledLabel = t.status === "pending" ? chalk7.dim(label) : label;
|
|
9848
10109
|
return {
|
|
9849
10110
|
plain: `[${char} ${label}]`,
|
|
9850
|
-
styled:
|
|
10111
|
+
styled: chalk7.dim("[") + icon + " " + styledLabel + chalk7.dim("]")
|
|
9851
10112
|
};
|
|
9852
10113
|
};
|
|
9853
10114
|
const mainNodes = mainTasks.map(renderNode);
|
|
@@ -9857,7 +10118,7 @@ var ParallelTaskDisplay = class {
|
|
|
9857
10118
|
const firstNodePlainWidth = mainNodes[0].plain.length;
|
|
9858
10119
|
const indent = " ".repeat(PREFIX.length + firstNodePlainWidth + arrow.length);
|
|
9859
10120
|
const branchNodes = branchTasks.map(renderNode);
|
|
9860
|
-
const branchLine = indent +
|
|
10121
|
+
const branchLine = indent + chalk7.dim("\u2198 ") + branchNodes.map((n) => n.styled).join(styledArrow) + chalk7.dim(" \u2197");
|
|
9861
10122
|
lines.push(branchLine);
|
|
9862
10123
|
}
|
|
9863
10124
|
return lines;
|
|
@@ -9884,16 +10145,16 @@ var ParallelTaskDisplay = class {
|
|
|
9884
10145
|
renderLine(task, index) {
|
|
9885
10146
|
const cols = process.stdout.columns || 80;
|
|
9886
10147
|
const elapsed = task.startTime ? this.formatTime((task.endTime ?? Date.now()) - task.startTime) : "";
|
|
9887
|
-
const timeStr = elapsed ? ` ${
|
|
10148
|
+
const timeStr = elapsed ? ` ${chalk7.dim(elapsed)}` : "";
|
|
9888
10149
|
const timePlain = elapsed ? ` ${elapsed}` : "";
|
|
9889
10150
|
const { styled: icon } = this.statusIcon(task);
|
|
9890
|
-
const nameStyle = task.status === "pending" ?
|
|
9891
|
-
const msgStyle = task.status === "failed" ?
|
|
10151
|
+
const nameStyle = task.status === "pending" ? chalk7.dim : chalk7.white;
|
|
10152
|
+
const msgStyle = task.status === "failed" ? chalk7.red : chalk7.dim;
|
|
9892
10153
|
if (!this.cachedConnectors) {
|
|
9893
10154
|
this.cachedConnectors = this.tasks.map((_, i) => this.getTreeConnector(i));
|
|
9894
10155
|
}
|
|
9895
10156
|
const connector = this.cachedConnectors[index];
|
|
9896
|
-
const connectorStyled = connector ?
|
|
10157
|
+
const connectorStyled = connector ? chalk7.dim(connector) : "";
|
|
9897
10158
|
const paddedName = task.name.padEnd(Math.max(0, NAME_COL_WIDTH - connector.length));
|
|
9898
10159
|
const usedByFixed = PREFIX.length + connector.length + 2 + NAME_COL_WIDTH + timePlain.length;
|
|
9899
10160
|
const msgMax = Math.max(cols - usedByFixed - 2, 10);
|
|
@@ -9912,7 +10173,7 @@ var ParallelTaskDisplay = class {
|
|
|
9912
10173
|
if (pipelineHeader.length > 0) {
|
|
9913
10174
|
lines.push(...pipelineHeader);
|
|
9914
10175
|
const cols = stdout.columns || 80;
|
|
9915
|
-
lines.push(PREFIX +
|
|
10176
|
+
lines.push(PREFIX + chalk7.dim("\u2500".repeat(Math.min(cols - PREFIX.length * 2, 55))));
|
|
9916
10177
|
}
|
|
9917
10178
|
lines.push(...taskLines);
|
|
9918
10179
|
const PREVIEW_STALE_MS = 3e3;
|
|
@@ -9921,7 +10182,7 @@ var ParallelTaskDisplay = class {
|
|
|
9921
10182
|
const cols = stdout.columns || 80;
|
|
9922
10183
|
const maxHeight = Math.min(Math.floor((stdout.rows || 24) / 3), 10);
|
|
9923
10184
|
const visibleLines = this.previewLines.slice(-maxHeight);
|
|
9924
|
-
lines.push(PREFIX +
|
|
10185
|
+
lines.push(PREFIX + chalk7.dim("\u2500".repeat(Math.min(cols - PREFIX.length * 2, 55))));
|
|
9925
10186
|
for (const line of visibleLines) {
|
|
9926
10187
|
lines.push(PREFIX + line.slice(0, cols - PREFIX.length));
|
|
9927
10188
|
}
|
|
@@ -9943,7 +10204,7 @@ var ParallelTaskDisplay = class {
|
|
|
9943
10204
|
};
|
|
9944
10205
|
|
|
9945
10206
|
// src/commands/init-prompts.ts
|
|
9946
|
-
import
|
|
10207
|
+
import chalk10 from "chalk";
|
|
9947
10208
|
import ora3 from "ora";
|
|
9948
10209
|
import select5 from "@inquirer/select";
|
|
9949
10210
|
import checkbox from "@inquirer/checkbox";
|
|
@@ -10032,7 +10293,7 @@ Return the complete updated AgentSetup JSON incorporating the user's changes. Re
|
|
|
10032
10293
|
}
|
|
10033
10294
|
|
|
10034
10295
|
// src/utils/spinner-messages.ts
|
|
10035
|
-
import
|
|
10296
|
+
import chalk8 from "chalk";
|
|
10036
10297
|
var GENERATION_MESSAGES = [
|
|
10037
10298
|
"Analyzing your project structure and dependencies...",
|
|
10038
10299
|
"Mapping out build commands and test workflows...",
|
|
@@ -10082,9 +10343,9 @@ var SpinnerMessages = class {
|
|
|
10082
10343
|
this.currentBaseMessage = this.messages[0];
|
|
10083
10344
|
this.updateSpinnerText();
|
|
10084
10345
|
if (this.showElapsedTime) {
|
|
10085
|
-
this.spinner.suffixText =
|
|
10346
|
+
this.spinner.suffixText = chalk8.dim(`(${this.formatElapsed()})`);
|
|
10086
10347
|
this.elapsedTimer = setInterval(() => {
|
|
10087
|
-
this.spinner.suffixText =
|
|
10348
|
+
this.spinner.suffixText = chalk8.dim(`(${this.formatElapsed()})`);
|
|
10088
10349
|
}, 1e3);
|
|
10089
10350
|
}
|
|
10090
10351
|
this.timer = setInterval(() => {
|
|
@@ -10202,9 +10463,9 @@ async function refineLoop(currentSetup, sessionHistory, summarizeSetup2, printSu
|
|
|
10202
10463
|
}
|
|
10203
10464
|
const isValid = await classifyRefineIntent(message);
|
|
10204
10465
|
if (!isValid) {
|
|
10205
|
-
console.log(
|
|
10206
|
-
console.log(
|
|
10207
|
-
console.log(
|
|
10466
|
+
console.log(chalk10.dim(" This doesn't look like a config change request."));
|
|
10467
|
+
console.log(chalk10.dim(" Describe what to add, remove, or modify in your configs."));
|
|
10468
|
+
console.log(chalk10.dim(' Type "done" to accept the current config.\n'));
|
|
10208
10469
|
continue;
|
|
10209
10470
|
}
|
|
10210
10471
|
const refineSpinner = ora3("Refining config...").start();
|
|
@@ -10221,16 +10482,16 @@ async function refineLoop(currentSetup, sessionHistory, summarizeSetup2, printSu
|
|
|
10221
10482
|
});
|
|
10222
10483
|
refineSpinner.succeed("Config updated");
|
|
10223
10484
|
printSummary(refined);
|
|
10224
|
-
console.log(
|
|
10485
|
+
console.log(chalk10.dim('Type "done" to accept, or describe more changes.'));
|
|
10225
10486
|
} else {
|
|
10226
10487
|
refineSpinner.fail("Refinement failed \u2014 could not parse AI response.");
|
|
10227
|
-
console.log(
|
|
10488
|
+
console.log(chalk10.dim('Try rephrasing your request, or type "done" to keep the current config.'));
|
|
10228
10489
|
}
|
|
10229
10490
|
}
|
|
10230
10491
|
}
|
|
10231
10492
|
|
|
10232
10493
|
// src/commands/init-display.ts
|
|
10233
|
-
import
|
|
10494
|
+
import chalk11 from "chalk";
|
|
10234
10495
|
import fs32 from "fs";
|
|
10235
10496
|
init_types();
|
|
10236
10497
|
function formatWhatChanged(setup) {
|
|
@@ -10282,26 +10543,26 @@ function printSetupSummary(setup) {
|
|
|
10282
10543
|
const fileDescriptions = setup.fileDescriptions;
|
|
10283
10544
|
const deletions = setup.deletions;
|
|
10284
10545
|
console.log("");
|
|
10285
|
-
console.log(
|
|
10546
|
+
console.log(chalk11.bold(" Your tailored config:\n"));
|
|
10286
10547
|
const getDescription = (filePath) => {
|
|
10287
10548
|
return fileDescriptions?.[filePath];
|
|
10288
10549
|
};
|
|
10289
10550
|
if (claude) {
|
|
10290
10551
|
if (claude.claudeMd) {
|
|
10291
|
-
const icon = fs32.existsSync("CLAUDE.md") ?
|
|
10552
|
+
const icon = fs32.existsSync("CLAUDE.md") ? chalk11.yellow("~") : chalk11.green("+");
|
|
10292
10553
|
const desc = getDescription("CLAUDE.md");
|
|
10293
|
-
console.log(` ${icon} ${
|
|
10294
|
-
if (desc) console.log(
|
|
10554
|
+
console.log(` ${icon} ${chalk11.bold("CLAUDE.md")}`);
|
|
10555
|
+
if (desc) console.log(chalk11.dim(` ${desc}`));
|
|
10295
10556
|
console.log("");
|
|
10296
10557
|
}
|
|
10297
10558
|
const skills = claude.skills;
|
|
10298
10559
|
if (Array.isArray(skills) && skills.length > 0) {
|
|
10299
10560
|
for (const skill of skills) {
|
|
10300
10561
|
const skillPath = `.claude/skills/${skill.name}/SKILL.md`;
|
|
10301
|
-
const icon = fs32.existsSync(skillPath) ?
|
|
10562
|
+
const icon = fs32.existsSync(skillPath) ? chalk11.yellow("~") : chalk11.green("+");
|
|
10302
10563
|
const desc = getDescription(skillPath);
|
|
10303
|
-
console.log(` ${icon} ${
|
|
10304
|
-
console.log(
|
|
10564
|
+
console.log(` ${icon} ${chalk11.bold(skillPath)}`);
|
|
10565
|
+
console.log(chalk11.dim(` ${desc || skill.description || skill.name}`));
|
|
10305
10566
|
console.log("");
|
|
10306
10567
|
}
|
|
10307
10568
|
}
|
|
@@ -10309,20 +10570,20 @@ function printSetupSummary(setup) {
|
|
|
10309
10570
|
const codex = setup.codex;
|
|
10310
10571
|
if (codex) {
|
|
10311
10572
|
if (codex.agentsMd) {
|
|
10312
|
-
const icon = fs32.existsSync("AGENTS.md") ?
|
|
10573
|
+
const icon = fs32.existsSync("AGENTS.md") ? chalk11.yellow("~") : chalk11.green("+");
|
|
10313
10574
|
const desc = getDescription("AGENTS.md");
|
|
10314
|
-
console.log(` ${icon} ${
|
|
10315
|
-
if (desc) console.log(
|
|
10575
|
+
console.log(` ${icon} ${chalk11.bold("AGENTS.md")}`);
|
|
10576
|
+
if (desc) console.log(chalk11.dim(` ${desc}`));
|
|
10316
10577
|
console.log("");
|
|
10317
10578
|
}
|
|
10318
10579
|
const codexSkills = codex.skills;
|
|
10319
10580
|
if (Array.isArray(codexSkills) && codexSkills.length > 0) {
|
|
10320
10581
|
for (const skill of codexSkills) {
|
|
10321
10582
|
const skillPath = `.agents/skills/${skill.name}/SKILL.md`;
|
|
10322
|
-
const icon = fs32.existsSync(skillPath) ?
|
|
10583
|
+
const icon = fs32.existsSync(skillPath) ? chalk11.yellow("~") : chalk11.green("+");
|
|
10323
10584
|
const desc = getDescription(skillPath);
|
|
10324
|
-
console.log(` ${icon} ${
|
|
10325
|
-
console.log(
|
|
10585
|
+
console.log(` ${icon} ${chalk11.bold(skillPath)}`);
|
|
10586
|
+
console.log(chalk11.dim(` ${desc || skill.description || skill.name}`));
|
|
10326
10587
|
console.log("");
|
|
10327
10588
|
}
|
|
10328
10589
|
}
|
|
@@ -10330,40 +10591,40 @@ function printSetupSummary(setup) {
|
|
|
10330
10591
|
const opencode = setup.opencode;
|
|
10331
10592
|
if (opencode) {
|
|
10332
10593
|
if (opencode.agentsMd && !codex?.agentsMd) {
|
|
10333
|
-
const icon = fs32.existsSync("AGENTS.md") ?
|
|
10594
|
+
const icon = fs32.existsSync("AGENTS.md") ? chalk11.yellow("~") : chalk11.green("+");
|
|
10334
10595
|
const desc = getDescription("AGENTS.md");
|
|
10335
|
-
console.log(` ${icon} ${
|
|
10336
|
-
if (desc) console.log(
|
|
10596
|
+
console.log(` ${icon} ${chalk11.bold("AGENTS.md")} ${chalk11.dim("(OpenCode)")}`);
|
|
10597
|
+
if (desc) console.log(chalk11.dim(` ${desc}`));
|
|
10337
10598
|
console.log("");
|
|
10338
10599
|
}
|
|
10339
10600
|
const opencodeSkills = opencode.skills;
|
|
10340
10601
|
if (Array.isArray(opencodeSkills) && opencodeSkills.length > 0) {
|
|
10341
10602
|
for (const skill of opencodeSkills) {
|
|
10342
10603
|
const skillPath = `.opencode/skills/${skill.name}/SKILL.md`;
|
|
10343
|
-
const icon = fs32.existsSync(skillPath) ?
|
|
10604
|
+
const icon = fs32.existsSync(skillPath) ? chalk11.yellow("~") : chalk11.green("+");
|
|
10344
10605
|
const desc = getDescription(skillPath);
|
|
10345
|
-
console.log(` ${icon} ${
|
|
10346
|
-
console.log(
|
|
10606
|
+
console.log(` ${icon} ${chalk11.bold(skillPath)}`);
|
|
10607
|
+
console.log(chalk11.dim(` ${desc || skill.description || skill.name}`));
|
|
10347
10608
|
console.log("");
|
|
10348
10609
|
}
|
|
10349
10610
|
}
|
|
10350
10611
|
}
|
|
10351
10612
|
if (cursor) {
|
|
10352
10613
|
if (cursor.cursorrules) {
|
|
10353
|
-
const icon = fs32.existsSync(".cursorrules") ?
|
|
10614
|
+
const icon = fs32.existsSync(".cursorrules") ? chalk11.yellow("~") : chalk11.green("+");
|
|
10354
10615
|
const desc = getDescription(".cursorrules");
|
|
10355
|
-
console.log(` ${icon} ${
|
|
10356
|
-
if (desc) console.log(
|
|
10616
|
+
console.log(` ${icon} ${chalk11.bold(".cursorrules")}`);
|
|
10617
|
+
if (desc) console.log(chalk11.dim(` ${desc}`));
|
|
10357
10618
|
console.log("");
|
|
10358
10619
|
}
|
|
10359
10620
|
const cursorSkills = cursor.skills;
|
|
10360
10621
|
if (Array.isArray(cursorSkills) && cursorSkills.length > 0) {
|
|
10361
10622
|
for (const skill of cursorSkills) {
|
|
10362
10623
|
const skillPath = `.cursor/skills/${skill.name}/SKILL.md`;
|
|
10363
|
-
const icon = fs32.existsSync(skillPath) ?
|
|
10624
|
+
const icon = fs32.existsSync(skillPath) ? chalk11.yellow("~") : chalk11.green("+");
|
|
10364
10625
|
const desc = getDescription(skillPath);
|
|
10365
|
-
console.log(` ${icon} ${
|
|
10366
|
-
console.log(
|
|
10626
|
+
console.log(` ${icon} ${chalk11.bold(skillPath)}`);
|
|
10627
|
+
console.log(chalk11.dim(` ${desc || skill.description || skill.name}`));
|
|
10367
10628
|
console.log("");
|
|
10368
10629
|
}
|
|
10369
10630
|
}
|
|
@@ -10371,14 +10632,14 @@ function printSetupSummary(setup) {
|
|
|
10371
10632
|
if (Array.isArray(rulesArr) && rulesArr.length > 0) {
|
|
10372
10633
|
for (const rule of rulesArr) {
|
|
10373
10634
|
const rulePath = `.cursor/rules/${rule.filename}`;
|
|
10374
|
-
const icon = fs32.existsSync(rulePath) ?
|
|
10635
|
+
const icon = fs32.existsSync(rulePath) ? chalk11.yellow("~") : chalk11.green("+");
|
|
10375
10636
|
const desc = getDescription(rulePath);
|
|
10376
|
-
console.log(` ${icon} ${
|
|
10637
|
+
console.log(` ${icon} ${chalk11.bold(rulePath)}`);
|
|
10377
10638
|
if (desc) {
|
|
10378
|
-
console.log(
|
|
10639
|
+
console.log(chalk11.dim(` ${desc}`));
|
|
10379
10640
|
} else {
|
|
10380
10641
|
const firstLine = rule.content.split("\n").filter((l) => l.trim() && !l.trim().startsWith("#"))[0];
|
|
10381
|
-
if (firstLine) console.log(
|
|
10642
|
+
if (firstLine) console.log(chalk11.dim(` ${firstLine.trim().slice(0, 80)}`));
|
|
10382
10643
|
}
|
|
10383
10644
|
console.log("");
|
|
10384
10645
|
}
|
|
@@ -10386,53 +10647,53 @@ function printSetupSummary(setup) {
|
|
|
10386
10647
|
}
|
|
10387
10648
|
if (Array.isArray(deletions) && deletions.length > 0) {
|
|
10388
10649
|
for (const del of deletions) {
|
|
10389
|
-
console.log(` ${
|
|
10390
|
-
console.log(
|
|
10650
|
+
console.log(` ${chalk11.red("-")} ${chalk11.bold(del.filePath)}`);
|
|
10651
|
+
console.log(chalk11.dim(` ${del.reason}`));
|
|
10391
10652
|
console.log("");
|
|
10392
10653
|
}
|
|
10393
10654
|
}
|
|
10394
10655
|
console.log(
|
|
10395
|
-
` ${
|
|
10656
|
+
` ${chalk11.green("+")} ${chalk11.dim("new")} ${chalk11.yellow("~")} ${chalk11.dim("modified")} ${chalk11.red("-")} ${chalk11.dim("removed")}`
|
|
10396
10657
|
);
|
|
10397
10658
|
console.log("");
|
|
10398
10659
|
}
|
|
10399
10660
|
function displayTokenUsage() {
|
|
10400
10661
|
const summary = getUsageSummary();
|
|
10401
10662
|
if (summary.length === 0) {
|
|
10402
|
-
console.log(
|
|
10663
|
+
console.log(chalk11.dim(" Token tracking not available for this provider.\n"));
|
|
10403
10664
|
return;
|
|
10404
10665
|
}
|
|
10405
10666
|
const config = loadConfig();
|
|
10406
10667
|
const isEstimated = config != null && isSeatBased(config.provider);
|
|
10407
10668
|
const label = isEstimated ? "Estimated token usage:" : "Token usage:";
|
|
10408
|
-
console.log(
|
|
10669
|
+
console.log(chalk11.bold(` ${label}
|
|
10409
10670
|
`));
|
|
10410
10671
|
let totalIn = 0;
|
|
10411
10672
|
let totalOut = 0;
|
|
10412
10673
|
for (const m of summary) {
|
|
10413
10674
|
totalIn += m.inputTokens;
|
|
10414
10675
|
totalOut += m.outputTokens;
|
|
10415
|
-
const cacheInfo = m.cacheReadTokens > 0 || m.cacheWriteTokens > 0 ?
|
|
10676
|
+
const cacheInfo = m.cacheReadTokens > 0 || m.cacheWriteTokens > 0 ? chalk11.dim(
|
|
10416
10677
|
` (cache: ${m.cacheReadTokens.toLocaleString()} read, ${m.cacheWriteTokens.toLocaleString()} write)`
|
|
10417
10678
|
) : "";
|
|
10418
10679
|
console.log(
|
|
10419
|
-
` ${
|
|
10680
|
+
` ${chalk11.dim(m.model)}: ${m.inputTokens.toLocaleString()} in / ${m.outputTokens.toLocaleString()} out (${m.calls} call${m.calls === 1 ? "" : "s"})${cacheInfo}`
|
|
10420
10681
|
);
|
|
10421
10682
|
}
|
|
10422
10683
|
if (summary.length > 1) {
|
|
10423
10684
|
console.log(
|
|
10424
|
-
` ${
|
|
10685
|
+
` ${chalk11.dim("Total")}: ${totalIn.toLocaleString()} in / ${totalOut.toLocaleString()} out`
|
|
10425
10686
|
);
|
|
10426
10687
|
}
|
|
10427
10688
|
if (isEstimated) {
|
|
10428
|
-
console.log(
|
|
10689
|
+
console.log(chalk11.dim(" (Estimated from character count)"));
|
|
10429
10690
|
}
|
|
10430
10691
|
console.log("");
|
|
10431
10692
|
}
|
|
10432
10693
|
|
|
10433
10694
|
// src/commands/init-helpers.ts
|
|
10434
10695
|
init_config();
|
|
10435
|
-
import
|
|
10696
|
+
import chalk12 from "chalk";
|
|
10436
10697
|
import fs33 from "fs";
|
|
10437
10698
|
import path26 from "path";
|
|
10438
10699
|
function isFirstRun(dir) {
|
|
@@ -10533,7 +10794,7 @@ function writeErrorLog(config, rawOutput, error, stopReason) {
|
|
|
10533
10794
|
}
|
|
10534
10795
|
fs33.mkdirSync(path26.join(process.cwd(), ".caliber"), { recursive: true });
|
|
10535
10796
|
fs33.writeFileSync(logPath, lines.join("\n"));
|
|
10536
|
-
console.log(
|
|
10797
|
+
console.log(chalk12.dim(`
|
|
10537
10798
|
Error log written to .caliber/error-log.md`));
|
|
10538
10799
|
} catch {
|
|
10539
10800
|
}
|
|
@@ -10647,13 +10908,13 @@ function getScoreTrend(entries) {
|
|
|
10647
10908
|
}
|
|
10648
10909
|
|
|
10649
10910
|
// src/commands/init.ts
|
|
10650
|
-
var
|
|
10911
|
+
var IS_WINDOWS6 = process.platform === "win32";
|
|
10651
10912
|
function log(verbose, ...args) {
|
|
10652
|
-
if (verbose) console.log(
|
|
10913
|
+
if (verbose) console.log(chalk13.dim(` [verbose] ${args.map(String).join(" ")}`));
|
|
10653
10914
|
}
|
|
10654
10915
|
async function initCommand(options) {
|
|
10655
|
-
const brand =
|
|
10656
|
-
const title =
|
|
10916
|
+
const brand = chalk13.hex("#EB9D83");
|
|
10917
|
+
const title = chalk13.hex("#83D1EB");
|
|
10657
10918
|
const bin = resolveCaliber();
|
|
10658
10919
|
const firstRun = isFirstRun(process.cwd());
|
|
10659
10920
|
if (firstRun) {
|
|
@@ -10667,23 +10928,23 @@ async function initCommand(options) {
|
|
|
10667
10928
|
\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
|
|
10668
10929
|
`)
|
|
10669
10930
|
);
|
|
10670
|
-
console.log(
|
|
10671
|
-
console.log(
|
|
10931
|
+
console.log(chalk13.dim(" Keep your AI agent configs in sync \u2014 automatically."));
|
|
10932
|
+
console.log(chalk13.dim(" Works across Claude Code, Cursor, Codex, and GitHub Copilot.\n"));
|
|
10672
10933
|
console.log(title.bold(" How it works:\n"));
|
|
10673
|
-
console.log(
|
|
10674
|
-
console.log(
|
|
10675
|
-
console.log(
|
|
10676
|
-
console.log(
|
|
10934
|
+
console.log(chalk13.dim(" 1. Connect Link your LLM provider and select your agents"));
|
|
10935
|
+
console.log(chalk13.dim(" 2. Setup Detect stack, install sync hooks & skills"));
|
|
10936
|
+
console.log(chalk13.dim(" 3. Generate Audit existing config or generate from scratch"));
|
|
10937
|
+
console.log(chalk13.dim(" 4. Finalize Review changes and score your setup\n"));
|
|
10677
10938
|
} else {
|
|
10678
|
-
console.log(brand.bold("\n CALIBER") +
|
|
10939
|
+
console.log(brand.bold("\n CALIBER") + chalk13.dim(" \u2014 setting up continuous sync\n"));
|
|
10679
10940
|
}
|
|
10680
10941
|
const platforms = detectPlatforms();
|
|
10681
10942
|
if (!platforms.claude && !platforms.cursor && !platforms.codex && !platforms.opencode) {
|
|
10682
10943
|
console.log(
|
|
10683
|
-
|
|
10944
|
+
chalk13.yellow(" \u26A0 No supported AI platforms detected (Claude, Cursor, Codex, OpenCode).")
|
|
10684
10945
|
);
|
|
10685
10946
|
console.log(
|
|
10686
|
-
|
|
10947
|
+
chalk13.yellow(
|
|
10687
10948
|
" Caliber will still generate config files, but they won't be auto-installed.\n"
|
|
10688
10949
|
)
|
|
10689
10950
|
);
|
|
@@ -10691,9 +10952,17 @@ async function initCommand(options) {
|
|
|
10691
10952
|
const report = options.debugReport ? new DebugReport() : null;
|
|
10692
10953
|
console.log(title.bold(" Step 1/3 \u2014 Connect\n"));
|
|
10693
10954
|
let config = loadConfig();
|
|
10955
|
+
if (!config && options.agent?.includes("opencode")) {
|
|
10956
|
+
if (isOpenCodeAvailable()) {
|
|
10957
|
+
console.log(chalk13.dim(" Detected: OpenCode (uses your existing subscription)\n"));
|
|
10958
|
+
const autoConfig = { provider: "opencode", model: DEFAULT_MODELS.opencode };
|
|
10959
|
+
writeConfigFile(autoConfig);
|
|
10960
|
+
config = autoConfig;
|
|
10961
|
+
}
|
|
10962
|
+
}
|
|
10694
10963
|
if (!config && !options.autoApprove) {
|
|
10695
10964
|
if (isClaudeCliAvailable() && isClaudeCliLoggedIn()) {
|
|
10696
|
-
console.log(
|
|
10965
|
+
console.log(chalk13.dim(" Detected: Claude Code CLI (uses your Pro/Max/Team subscription)\n"));
|
|
10697
10966
|
const useIt = await confirm2({ message: "Use Claude Code as your LLM provider?" });
|
|
10698
10967
|
if (useIt) {
|
|
10699
10968
|
const autoConfig = { provider: "claude-cli", model: "default" };
|
|
@@ -10701,7 +10970,7 @@ async function initCommand(options) {
|
|
|
10701
10970
|
config = autoConfig;
|
|
10702
10971
|
}
|
|
10703
10972
|
} else if (isCursorAgentAvailable() && isCursorLoggedIn()) {
|
|
10704
|
-
console.log(
|
|
10973
|
+
console.log(chalk13.dim(" Detected: Cursor (uses your existing subscription)\n"));
|
|
10705
10974
|
const useIt = await confirm2({ message: "Use Cursor as your LLM provider?" });
|
|
10706
10975
|
if (useIt) {
|
|
10707
10976
|
const autoConfig = { provider: "cursor", model: "sonnet-4.6" };
|
|
@@ -10720,16 +10989,20 @@ async function initCommand(options) {
|
|
|
10720
10989
|
const autoConfig = { provider: "cursor", model: "sonnet-4.6" };
|
|
10721
10990
|
writeConfigFile(autoConfig);
|
|
10722
10991
|
config = autoConfig;
|
|
10992
|
+
} else if (isOpenCodeAvailable()) {
|
|
10993
|
+
const autoConfig = { provider: "opencode", model: DEFAULT_MODELS.opencode };
|
|
10994
|
+
writeConfigFile(autoConfig);
|
|
10995
|
+
config = autoConfig;
|
|
10723
10996
|
}
|
|
10724
10997
|
}
|
|
10725
10998
|
if (!config) {
|
|
10726
|
-
console.log(
|
|
10999
|
+
console.log(chalk13.dim(" No LLM provider detected.\n"));
|
|
10727
11000
|
await runInteractiveProviderSetup({
|
|
10728
11001
|
selectMessage: "How do you want to use Caliber? (choose LLM provider)"
|
|
10729
11002
|
});
|
|
10730
11003
|
config = loadConfig();
|
|
10731
11004
|
if (!config) {
|
|
10732
|
-
console.log(
|
|
11005
|
+
console.log(chalk13.red(" Configuration cancelled or failed.\n"));
|
|
10733
11006
|
throw new Error("__exit__");
|
|
10734
11007
|
}
|
|
10735
11008
|
}
|
|
@@ -10738,7 +11011,7 @@ async function initCommand(options) {
|
|
|
10738
11011
|
const displayModel = getDisplayModel(config);
|
|
10739
11012
|
const fastModel = getFastModel();
|
|
10740
11013
|
const modelLine = fastModel ? ` Provider: ${config.provider} | Model: ${displayModel} | Scan: ${fastModel}` : ` Provider: ${config.provider} | Model: ${displayModel}`;
|
|
10741
|
-
console.log(
|
|
11014
|
+
console.log(chalk13.dim(modelLine + "\n"));
|
|
10742
11015
|
if (report) {
|
|
10743
11016
|
report.markStep("Provider connection");
|
|
10744
11017
|
report.addSection(
|
|
@@ -10757,10 +11030,10 @@ async function initCommand(options) {
|
|
|
10757
11030
|
const detected = detectAgents(process.cwd());
|
|
10758
11031
|
if (detected.length > 0 && (options.autoApprove || firstRun)) {
|
|
10759
11032
|
targetAgent = detected;
|
|
10760
|
-
console.log(
|
|
11033
|
+
console.log(chalk13.dim(` Coding agents in this repo: ${detected.join(", ")}
|
|
10761
11034
|
`));
|
|
10762
11035
|
} else if (detected.length > 0) {
|
|
10763
|
-
console.log(
|
|
11036
|
+
console.log(chalk13.dim(` Coding agents in this repo: ${detected.join(", ")}
|
|
10764
11037
|
`));
|
|
10765
11038
|
const useDetected = await confirm2({ message: "Generate configs for these agents?" });
|
|
10766
11039
|
targetAgent = useDetected ? detected : await promptAgent();
|
|
@@ -10768,29 +11041,29 @@ async function initCommand(options) {
|
|
|
10768
11041
|
targetAgent = options.autoApprove ? ["claude"] : await promptAgent();
|
|
10769
11042
|
}
|
|
10770
11043
|
}
|
|
10771
|
-
console.log(
|
|
11044
|
+
console.log(chalk13.dim(` Target: ${targetAgent.join(", ")}
|
|
10772
11045
|
`));
|
|
10773
11046
|
trackInitAgentSelected(targetAgent, agentAutoDetected);
|
|
10774
11047
|
console.log(title.bold(" Step 2/4 \u2014 Setup\n"));
|
|
10775
|
-
console.log(
|
|
11048
|
+
console.log(chalk13.dim(" Installing sync infrastructure...\n"));
|
|
10776
11049
|
const hookResult = installPreCommitHook();
|
|
10777
11050
|
if (hookResult.installed) {
|
|
10778
|
-
console.log(` ${
|
|
11051
|
+
console.log(` ${chalk13.green("\u2713")} Pre-commit hook installed \u2014 configs sync on every commit`);
|
|
10779
11052
|
} else if (hookResult.alreadyInstalled) {
|
|
10780
|
-
console.log(` ${
|
|
11053
|
+
console.log(` ${chalk13.green("\u2713")} Pre-commit hook \u2014 active`);
|
|
10781
11054
|
}
|
|
10782
11055
|
installStopHook();
|
|
10783
|
-
console.log(` ${
|
|
11056
|
+
console.log(` ${chalk13.green("\u2713")} Onboarding hook \u2014 nudges new team members to set up`);
|
|
10784
11057
|
installSessionStartHook();
|
|
10785
|
-
console.log(` ${
|
|
10786
|
-
if (
|
|
11058
|
+
console.log(` ${chalk13.green("\u2713")} Freshness hook \u2014 warns when configs are stale`);
|
|
11059
|
+
if (IS_WINDOWS6) {
|
|
10787
11060
|
console.log(
|
|
10788
|
-
|
|
11061
|
+
chalk13.yellow(
|
|
10789
11062
|
"\n Note: hooks use shell syntax and require Git Bash (included with Git for Windows)."
|
|
10790
11063
|
)
|
|
10791
11064
|
);
|
|
10792
11065
|
console.log(
|
|
10793
|
-
|
|
11066
|
+
chalk13.dim(
|
|
10794
11067
|
" If hooks don't run, ensure Git for Windows is installed and git is using its bundled sh."
|
|
10795
11068
|
)
|
|
10796
11069
|
);
|
|
@@ -10807,23 +11080,23 @@ async function initCommand(options) {
|
|
|
10807
11080
|
const skillsWritten = ensureBuiltinSkills2();
|
|
10808
11081
|
if (skillsWritten.length > 0) {
|
|
10809
11082
|
console.log(
|
|
10810
|
-
` ${
|
|
11083
|
+
` ${chalk13.green("\u2713")} Agent skills installed \u2014 /setup-caliber, /find-skills, /save-learning`
|
|
10811
11084
|
);
|
|
10812
11085
|
} else {
|
|
10813
|
-
console.log(` ${
|
|
11086
|
+
console.log(` ${chalk13.green("\u2713")} Agent skills \u2014 already installed`);
|
|
10814
11087
|
}
|
|
10815
11088
|
const hasLearnableAgent = targetAgent.includes("claude") || targetAgent.includes("cursor");
|
|
10816
11089
|
if (hasLearnableAgent) {
|
|
10817
11090
|
if (targetAgent.includes("claude")) installLearningHooks();
|
|
10818
11091
|
if (targetAgent.includes("cursor")) installCursorLearningHooks();
|
|
10819
|
-
console.log(` ${
|
|
11092
|
+
console.log(` ${chalk13.green("\u2713")} Session learning enabled`);
|
|
10820
11093
|
trackInitLearnEnabled(true);
|
|
10821
11094
|
}
|
|
10822
11095
|
console.log("");
|
|
10823
|
-
console.log(
|
|
10824
|
-
console.log(
|
|
11096
|
+
console.log(chalk13.dim(" New team members can run /setup-caliber inside their coding agent"));
|
|
11097
|
+
console.log(chalk13.dim(" (Claude Code or Cursor) to get set up automatically.\n"));
|
|
10825
11098
|
const baselineScore = computeLocalScore(process.cwd(), targetAgent);
|
|
10826
|
-
console.log(
|
|
11099
|
+
console.log(chalk13.dim(" Current config score:"));
|
|
10827
11100
|
displayScoreSummary(baselineScore);
|
|
10828
11101
|
if (options.verbose) {
|
|
10829
11102
|
for (const c of baselineScore.checks) {
|
|
@@ -10861,20 +11134,20 @@ async function initCommand(options) {
|
|
|
10861
11134
|
let skipGeneration = false;
|
|
10862
11135
|
if (hasExistingConfig && baselineScore.score === 100) {
|
|
10863
11136
|
trackInitScoreComputed(baselineScore.score, passingCount, failingCount, true);
|
|
10864
|
-
console.log(
|
|
11137
|
+
console.log(chalk13.bold.green("\n Your config is already optimal.\n"));
|
|
10865
11138
|
skipGeneration = !options.force;
|
|
10866
11139
|
} else if (hasExistingConfig && !options.force && !options.autoApprove) {
|
|
10867
11140
|
trackInitScoreComputed(baselineScore.score, passingCount, failingCount, false);
|
|
10868
11141
|
console.log(
|
|
10869
|
-
|
|
11142
|
+
chalk13.dim("\n Sync infrastructure is ready. Caliber can also audit your existing")
|
|
10870
11143
|
);
|
|
10871
|
-
console.log(
|
|
11144
|
+
console.log(chalk13.dim(" configs and improve them using AI.\n"));
|
|
10872
11145
|
const auditAnswer = await promptInput(" Audit and improve your existing config? (Y/n) ");
|
|
10873
11146
|
skipGeneration = auditAnswer.toLowerCase() === "n";
|
|
10874
11147
|
} else if (!hasExistingConfig && !options.force && !options.autoApprove) {
|
|
10875
11148
|
trackInitScoreComputed(baselineScore.score, passingCount, failingCount, false);
|
|
10876
|
-
console.log(
|
|
10877
|
-
console.log(
|
|
11149
|
+
console.log(chalk13.dim("\n Sync infrastructure is ready. Caliber can also generate tailored"));
|
|
11150
|
+
console.log(chalk13.dim(" CLAUDE.md, Cursor rules, and Codex configs for your project.\n"));
|
|
10878
11151
|
const generateAnswer = await promptInput(" Generate agent configs? (Y/n) ");
|
|
10879
11152
|
skipGeneration = generateAnswer.toLowerCase() === "n";
|
|
10880
11153
|
} else {
|
|
@@ -10901,7 +11174,7 @@ async function initCommand(options) {
|
|
|
10901
11174
|
const updatedClaude = appendManagedBlocks2(claudeContent, "claude");
|
|
10902
11175
|
if (updatedClaude !== claudeContent || !fs35.existsSync(claudeMdPath)) {
|
|
10903
11176
|
fs35.writeFileSync(claudeMdPath, updatedClaude);
|
|
10904
|
-
console.log(` ${
|
|
11177
|
+
console.log(` ${chalk13.green("\u2713")} CLAUDE.md \u2014 added Caliber sync instructions`);
|
|
10905
11178
|
}
|
|
10906
11179
|
if (targetAgent.includes("cursor")) {
|
|
10907
11180
|
const rulesDir = path28.join(".cursor", "rules");
|
|
@@ -10914,7 +11187,7 @@ async function initCommand(options) {
|
|
|
10914
11187
|
]) {
|
|
10915
11188
|
fs35.writeFileSync(path28.join(rulesDir, rule.filename), rule.content);
|
|
10916
11189
|
}
|
|
10917
|
-
console.log(` ${
|
|
11190
|
+
console.log(` ${chalk13.green("\u2713")} Cursor rules \u2014 added Caliber sync rules`);
|
|
10918
11191
|
}
|
|
10919
11192
|
if (targetAgent.includes("github-copilot")) {
|
|
10920
11193
|
const copilotPath = path28.join(".github", "copilot-instructions.md");
|
|
@@ -10931,7 +11204,7 @@ async function initCommand(options) {
|
|
|
10931
11204
|
const updatedCopilot = appendManagedBlocks2(copilotContent, "copilot");
|
|
10932
11205
|
if (updatedCopilot !== copilotContent) {
|
|
10933
11206
|
fs35.writeFileSync(copilotPath, updatedCopilot);
|
|
10934
|
-
console.log(` ${
|
|
11207
|
+
console.log(` ${chalk13.green("\u2713")} Copilot instructions \u2014 added Caliber sync instructions`);
|
|
10935
11208
|
}
|
|
10936
11209
|
}
|
|
10937
11210
|
const sha2 = getCurrentHeadSha();
|
|
@@ -10941,16 +11214,16 @@ async function initCommand(options) {
|
|
|
10941
11214
|
targetAgent
|
|
10942
11215
|
});
|
|
10943
11216
|
trackInitCompleted("sync-only", baselineScore.score);
|
|
10944
|
-
console.log(
|
|
10945
|
-
console.log(
|
|
11217
|
+
console.log(chalk13.bold.green("\n Caliber sync is set up!\n"));
|
|
11218
|
+
console.log(chalk13.dim(" Your agent configs will sync automatically on every commit."));
|
|
10946
11219
|
console.log(
|
|
10947
|
-
|
|
11220
|
+
chalk13.dim(" Run ") + title(`${bin} init --force`) + chalk13.dim(" anytime to generate or improve configs.\n")
|
|
10948
11221
|
);
|
|
10949
11222
|
return;
|
|
10950
11223
|
}
|
|
10951
11224
|
console.log(title.bold("\n Step 3/4 \u2014 Generate\n"));
|
|
10952
11225
|
const genModelInfo = fastModel ? ` Using ${displayModel} for docs, ${fastModel} for skills` : ` Using ${displayModel}`;
|
|
10953
|
-
console.log(
|
|
11226
|
+
console.log(chalk13.dim(genModelInfo + "\n"));
|
|
10954
11227
|
if (report) report.markStep("Generation");
|
|
10955
11228
|
trackInitGenerationStarted(false);
|
|
10956
11229
|
const genStartTime = Date.now();
|
|
@@ -11079,7 +11352,7 @@ async function initCommand(options) {
|
|
|
11079
11352
|
onContent: (text) => {
|
|
11080
11353
|
const lines = text.split("\n").filter((l) => l.trim()).slice(-8);
|
|
11081
11354
|
if (lines.length > 0) {
|
|
11082
|
-
display.setPreviewContent(lines.map((l) => ` ${
|
|
11355
|
+
display.setPreviewContent(lines.map((l) => ` ${chalk13.dim(l.slice(0, 80))}`));
|
|
11083
11356
|
}
|
|
11084
11357
|
}
|
|
11085
11358
|
},
|
|
@@ -11162,7 +11435,7 @@ async function initCommand(options) {
|
|
|
11162
11435
|
} catch (err) {
|
|
11163
11436
|
display.stop();
|
|
11164
11437
|
const msg = err instanceof Error ? err.message : "Unknown error";
|
|
11165
|
-
console.log(
|
|
11438
|
+
console.log(chalk13.red(`
|
|
11166
11439
|
Engine failed: ${msg}
|
|
11167
11440
|
`));
|
|
11168
11441
|
writeErrorLog(config, void 0, msg, "exception");
|
|
@@ -11174,15 +11447,15 @@ async function initCommand(options) {
|
|
|
11174
11447
|
const mins = Math.floor(elapsedMs / 6e4);
|
|
11175
11448
|
const secs = Math.floor(elapsedMs % 6e4 / 1e3);
|
|
11176
11449
|
const timeStr = mins > 0 ? `${mins}m ${secs}s` : `${secs}s`;
|
|
11177
|
-
console.log(
|
|
11450
|
+
console.log(chalk13.dim(`
|
|
11178
11451
|
Done in ${timeStr}
|
|
11179
11452
|
`));
|
|
11180
11453
|
if (!generatedSetup) {
|
|
11181
|
-
console.log(
|
|
11454
|
+
console.log(chalk13.red(" Failed to generate config."));
|
|
11182
11455
|
writeErrorLog(config, rawOutput, void 0, genStopReason);
|
|
11183
11456
|
if (rawOutput) {
|
|
11184
|
-
console.log(
|
|
11185
|
-
console.log(
|
|
11457
|
+
console.log(chalk13.dim("\nRaw LLM output (JSON parse failed):"));
|
|
11458
|
+
console.log(chalk13.dim(rawOutput.slice(0, 500)));
|
|
11186
11459
|
}
|
|
11187
11460
|
throw new Error("__exit__");
|
|
11188
11461
|
}
|
|
@@ -11201,19 +11474,19 @@ async function initCommand(options) {
|
|
|
11201
11474
|
const changes = formatWhatChanged(generatedSetup);
|
|
11202
11475
|
if (changes.length > 0) {
|
|
11203
11476
|
for (const line of changes) {
|
|
11204
|
-
console.log(` ${
|
|
11477
|
+
console.log(` ${chalk13.dim("\u2022")} ${line}`);
|
|
11205
11478
|
}
|
|
11206
11479
|
console.log("");
|
|
11207
11480
|
}
|
|
11208
11481
|
console.log(
|
|
11209
|
-
|
|
11210
|
-
` ${
|
|
11482
|
+
chalk13.dim(
|
|
11483
|
+
` ${chalk13.green(`${staged.newFiles} new`)} / ${chalk13.yellow(`${staged.modifiedFiles} modified`)} file${totalChanges !== 1 ? "s" : ""}`
|
|
11211
11484
|
)
|
|
11212
11485
|
);
|
|
11213
11486
|
if (skillSearchResult.results.length > 0) {
|
|
11214
11487
|
console.log(
|
|
11215
|
-
|
|
11216
|
-
` ${
|
|
11488
|
+
chalk13.dim(
|
|
11489
|
+
` ${chalk13.cyan(`${skillSearchResult.results.length}`)} community skills available to install
|
|
11217
11490
|
`
|
|
11218
11491
|
)
|
|
11219
11492
|
);
|
|
@@ -11223,7 +11496,7 @@ async function initCommand(options) {
|
|
|
11223
11496
|
const hasSkillResults = skillSearchResult.results.length > 0;
|
|
11224
11497
|
let action;
|
|
11225
11498
|
if (totalChanges === 0 && !hasSkillResults) {
|
|
11226
|
-
console.log(
|
|
11499
|
+
console.log(chalk13.dim(" No changes needed \u2014 your configs are already up to date.\n"));
|
|
11227
11500
|
cleanupStaging();
|
|
11228
11501
|
action = "accept";
|
|
11229
11502
|
} else if (options.autoApprove) {
|
|
@@ -11247,14 +11520,14 @@ async function initCommand(options) {
|
|
|
11247
11520
|
trackInitRefinementRound(refinementRound, !!generatedSetup);
|
|
11248
11521
|
if (!generatedSetup) {
|
|
11249
11522
|
cleanupStaging();
|
|
11250
|
-
console.log(
|
|
11523
|
+
console.log(chalk13.dim("Refinement cancelled. No files were modified."));
|
|
11251
11524
|
return;
|
|
11252
11525
|
}
|
|
11253
11526
|
const updatedFiles = collectSetupFiles(generatedSetup, targetAgent);
|
|
11254
11527
|
const restaged = stageFiles(updatedFiles, process.cwd());
|
|
11255
11528
|
console.log(
|
|
11256
|
-
|
|
11257
|
-
` ${
|
|
11529
|
+
chalk13.dim(
|
|
11530
|
+
` ${chalk13.green(`${restaged.newFiles} new`)} / ${chalk13.yellow(`${restaged.modifiedFiles} modified`)} file${restaged.newFiles + restaged.modifiedFiles !== 1 ? "s" : ""}
|
|
11258
11531
|
`
|
|
11259
11532
|
)
|
|
11260
11533
|
);
|
|
@@ -11266,11 +11539,11 @@ async function initCommand(options) {
|
|
|
11266
11539
|
}
|
|
11267
11540
|
cleanupStaging();
|
|
11268
11541
|
if (action === "decline") {
|
|
11269
|
-
console.log(
|
|
11542
|
+
console.log(chalk13.dim("Declined. No files were modified."));
|
|
11270
11543
|
return;
|
|
11271
11544
|
}
|
|
11272
11545
|
if (options.dryRun) {
|
|
11273
|
-
console.log(
|
|
11546
|
+
console.log(chalk13.yellow("\n[Dry run] Would write the following files:"));
|
|
11274
11547
|
console.log(JSON.stringify(generatedSetup, null, 2));
|
|
11275
11548
|
return;
|
|
11276
11549
|
}
|
|
@@ -11301,23 +11574,23 @@ ${agentRefs.join(" ")}
|
|
|
11301
11574
|
0,
|
|
11302
11575
|
result.deleted.length
|
|
11303
11576
|
);
|
|
11304
|
-
console.log(
|
|
11577
|
+
console.log(chalk13.bold("\nFiles created/updated:"));
|
|
11305
11578
|
for (const file of result.written) {
|
|
11306
|
-
console.log(` ${
|
|
11579
|
+
console.log(` ${chalk13.green("\u2713")} ${file}`);
|
|
11307
11580
|
}
|
|
11308
11581
|
if (result.deleted.length > 0) {
|
|
11309
|
-
console.log(
|
|
11582
|
+
console.log(chalk13.bold("\nFiles removed:"));
|
|
11310
11583
|
for (const file of result.deleted) {
|
|
11311
|
-
console.log(` ${
|
|
11584
|
+
console.log(` ${chalk13.red("\u2717")} ${file}`);
|
|
11312
11585
|
}
|
|
11313
11586
|
}
|
|
11314
11587
|
if (result.backupDir) {
|
|
11315
|
-
console.log(
|
|
11588
|
+
console.log(chalk13.dim(`
|
|
11316
11589
|
Backups saved to ${result.backupDir}`));
|
|
11317
11590
|
}
|
|
11318
11591
|
} catch (err) {
|
|
11319
11592
|
writeSpinner.fail("Failed to write files");
|
|
11320
|
-
console.error(
|
|
11593
|
+
console.error(chalk13.red(err instanceof Error ? err.message : "Unknown error"));
|
|
11321
11594
|
throw new Error("__exit__");
|
|
11322
11595
|
}
|
|
11323
11596
|
if (fingerprint) ensurePermissions(fingerprint);
|
|
@@ -11332,7 +11605,7 @@ ${agentRefs.join(" ")}
|
|
|
11332
11605
|
trackInitScoreRegression(baselineScore.score, afterScore.score);
|
|
11333
11606
|
console.log("");
|
|
11334
11607
|
console.log(
|
|
11335
|
-
|
|
11608
|
+
chalk13.yellow(
|
|
11336
11609
|
` Score would drop from ${baselineScore.score} to ${afterScore.score} \u2014 reverting changes.`
|
|
11337
11610
|
)
|
|
11338
11611
|
);
|
|
@@ -11340,7 +11613,7 @@ ${agentRefs.join(" ")}
|
|
|
11340
11613
|
const { restored, removed } = undoSetup();
|
|
11341
11614
|
if (restored.length > 0 || removed.length > 0) {
|
|
11342
11615
|
console.log(
|
|
11343
|
-
|
|
11616
|
+
chalk13.dim(
|
|
11344
11617
|
` Reverted ${restored.length + removed.length} file${restored.length + removed.length === 1 ? "" : "s"} from backup.`
|
|
11345
11618
|
)
|
|
11346
11619
|
);
|
|
@@ -11348,7 +11621,7 @@ ${agentRefs.join(" ")}
|
|
|
11348
11621
|
} catch {
|
|
11349
11622
|
}
|
|
11350
11623
|
console.log(
|
|
11351
|
-
|
|
11624
|
+
chalk13.dim(" Run ") + chalk13.hex("#83D1EB")(`${bin} init --force`) + chalk13.dim(" to override.\n")
|
|
11352
11625
|
);
|
|
11353
11626
|
return;
|
|
11354
11627
|
}
|
|
@@ -11379,7 +11652,7 @@ ${agentRefs.join(" ")}
|
|
|
11379
11652
|
}
|
|
11380
11653
|
let communitySkillsInstalled = 0;
|
|
11381
11654
|
if (skillSearchResult.results.length > 0 && !options.autoApprove) {
|
|
11382
|
-
console.log(
|
|
11655
|
+
console.log(chalk13.dim(" Community skills matched to your project:\n"));
|
|
11383
11656
|
const selected = await interactiveSelect(skillSearchResult.results);
|
|
11384
11657
|
if (selected?.length) {
|
|
11385
11658
|
await installSkills(selected, targetAgent, skillSearchResult.contentMap);
|
|
@@ -11388,32 +11661,32 @@ ${agentRefs.join(" ")}
|
|
|
11388
11661
|
}
|
|
11389
11662
|
}
|
|
11390
11663
|
trackInitHookSelected("config-instructions");
|
|
11391
|
-
const done =
|
|
11392
|
-
console.log(
|
|
11393
|
-
console.log(
|
|
11664
|
+
const done = chalk13.green("\u2713");
|
|
11665
|
+
console.log(chalk13.bold.green("\n Caliber is set up!\n"));
|
|
11666
|
+
console.log(chalk13.bold(" What's configured:\n"));
|
|
11394
11667
|
console.log(
|
|
11395
|
-
` ${done} Continuous sync ${
|
|
11668
|
+
` ${done} Continuous sync ${chalk13.dim("pre-commit hook keeps all agent configs in sync")}`
|
|
11396
11669
|
);
|
|
11397
11670
|
console.log(
|
|
11398
|
-
` ${done} Config generated ${title(`${bin} score`)} ${
|
|
11671
|
+
` ${done} Config generated ${title(`${bin} score`)} ${chalk13.dim("for full breakdown")}`
|
|
11399
11672
|
);
|
|
11400
11673
|
console.log(
|
|
11401
|
-
` ${done} Agent skills ${
|
|
11674
|
+
` ${done} Agent skills ${chalk13.dim("/setup-caliber for new team members")}`
|
|
11402
11675
|
);
|
|
11403
11676
|
if (hasLearnableAgent) {
|
|
11404
11677
|
console.log(
|
|
11405
|
-
` ${done} Session learning ${
|
|
11678
|
+
` ${done} Session learning ${chalk13.dim("agent learns from your feedback")}`
|
|
11406
11679
|
);
|
|
11407
11680
|
}
|
|
11408
11681
|
if (communitySkillsInstalled > 0) {
|
|
11409
11682
|
console.log(
|
|
11410
|
-
` ${done} Community skills ${
|
|
11683
|
+
` ${done} Community skills ${chalk13.dim(`${communitySkillsInstalled} skill${communitySkillsInstalled > 1 ? "s" : ""} installed for your stack`)}`
|
|
11411
11684
|
);
|
|
11412
11685
|
}
|
|
11413
|
-
console.log(
|
|
11414
|
-
console.log(
|
|
11415
|
-
console.log(
|
|
11416
|
-
console.log(
|
|
11686
|
+
console.log(chalk13.bold("\n What happens next:\n"));
|
|
11687
|
+
console.log(chalk13.dim(" Every commit will automatically sync your agent configs."));
|
|
11688
|
+
console.log(chalk13.dim(" New team members can run /setup-caliber to get set up instantly.\n"));
|
|
11689
|
+
console.log(chalk13.bold(" Explore:\n"));
|
|
11417
11690
|
console.log(` ${title(`${bin} score`)} Full scoring breakdown with improvement tips`);
|
|
11418
11691
|
console.log(` ${title(`${bin} skills`)} Find community skills for your stack`);
|
|
11419
11692
|
console.log(` ${title(`${bin} undo`)} Revert all changes from this run`);
|
|
@@ -11427,14 +11700,14 @@ ${agentRefs.join(" ")}
|
|
|
11427
11700
|
const reportPath = path28.join(process.cwd(), ".caliber", "debug-report.md");
|
|
11428
11701
|
report.write(reportPath);
|
|
11429
11702
|
console.log(
|
|
11430
|
-
|
|
11703
|
+
chalk13.dim(` Debug report written to ${path28.relative(process.cwd(), reportPath)}
|
|
11431
11704
|
`)
|
|
11432
11705
|
);
|
|
11433
11706
|
}
|
|
11434
11707
|
}
|
|
11435
11708
|
|
|
11436
11709
|
// src/commands/undo.ts
|
|
11437
|
-
import
|
|
11710
|
+
import chalk14 from "chalk";
|
|
11438
11711
|
import ora4 from "ora";
|
|
11439
11712
|
function undoCommand() {
|
|
11440
11713
|
const spinner = ora4("Reverting config changes...").start();
|
|
@@ -11447,26 +11720,26 @@ function undoCommand() {
|
|
|
11447
11720
|
trackUndoExecuted();
|
|
11448
11721
|
spinner.succeed("Config reverted successfully.\n");
|
|
11449
11722
|
if (restored.length > 0) {
|
|
11450
|
-
console.log(
|
|
11723
|
+
console.log(chalk14.cyan(" Restored from backup:"));
|
|
11451
11724
|
for (const file of restored) {
|
|
11452
|
-
console.log(` ${
|
|
11725
|
+
console.log(` ${chalk14.green("\u21A9")} ${file}`);
|
|
11453
11726
|
}
|
|
11454
11727
|
}
|
|
11455
11728
|
if (removed.length > 0) {
|
|
11456
|
-
console.log(
|
|
11729
|
+
console.log(chalk14.cyan(" Removed:"));
|
|
11457
11730
|
for (const file of removed) {
|
|
11458
|
-
console.log(` ${
|
|
11731
|
+
console.log(` ${chalk14.red("\u2717")} ${file}`);
|
|
11459
11732
|
}
|
|
11460
11733
|
}
|
|
11461
11734
|
console.log("");
|
|
11462
11735
|
} catch (err) {
|
|
11463
|
-
spinner.fail(
|
|
11736
|
+
spinner.fail(chalk14.red(err instanceof Error ? err.message : "Undo failed"));
|
|
11464
11737
|
throw new Error("__exit__");
|
|
11465
11738
|
}
|
|
11466
11739
|
}
|
|
11467
11740
|
|
|
11468
11741
|
// src/commands/status.ts
|
|
11469
|
-
import
|
|
11742
|
+
import chalk15 from "chalk";
|
|
11470
11743
|
import fs36 from "fs";
|
|
11471
11744
|
init_config();
|
|
11472
11745
|
init_resolve_caliber();
|
|
@@ -11482,29 +11755,29 @@ async function statusCommand(options) {
|
|
|
11482
11755
|
}, null, 2));
|
|
11483
11756
|
return;
|
|
11484
11757
|
}
|
|
11485
|
-
console.log(
|
|
11758
|
+
console.log(chalk15.bold("\nCaliber Status\n"));
|
|
11486
11759
|
if (config) {
|
|
11487
|
-
console.log(` LLM: ${
|
|
11760
|
+
console.log(` LLM: ${chalk15.green(config.provider)} (${config.model})`);
|
|
11488
11761
|
} else {
|
|
11489
11762
|
const bin = resolveCaliber();
|
|
11490
|
-
console.log(` LLM: ${
|
|
11763
|
+
console.log(` LLM: ${chalk15.yellow("Not configured")} \u2014 run ${chalk15.hex("#83D1EB")(`${bin} config`)}`);
|
|
11491
11764
|
}
|
|
11492
11765
|
if (!manifest) {
|
|
11493
|
-
console.log(` Config: ${
|
|
11494
|
-
console.log(
|
|
11766
|
+
console.log(` Config: ${chalk15.dim("No config applied")}`);
|
|
11767
|
+
console.log(chalk15.dim("\n Run ") + chalk15.hex("#83D1EB")(`${resolveCaliber()} init`) + chalk15.dim(" to get started.\n"));
|
|
11495
11768
|
return;
|
|
11496
11769
|
}
|
|
11497
|
-
console.log(` Files managed: ${
|
|
11770
|
+
console.log(` Files managed: ${chalk15.cyan(manifest.entries.length.toString())}`);
|
|
11498
11771
|
for (const entry of manifest.entries) {
|
|
11499
11772
|
const exists = fs36.existsSync(entry.path);
|
|
11500
|
-
const icon = exists ?
|
|
11773
|
+
const icon = exists ? chalk15.green("\u2713") : chalk15.red("\u2717");
|
|
11501
11774
|
console.log(` ${icon} ${entry.path} (${entry.action})`);
|
|
11502
11775
|
}
|
|
11503
11776
|
console.log("");
|
|
11504
11777
|
}
|
|
11505
11778
|
|
|
11506
11779
|
// src/commands/regenerate.ts
|
|
11507
|
-
import
|
|
11780
|
+
import chalk16 from "chalk";
|
|
11508
11781
|
import ora5 from "ora";
|
|
11509
11782
|
import select6 from "@inquirer/select";
|
|
11510
11783
|
init_review();
|
|
@@ -11514,12 +11787,12 @@ async function regenerateCommand(options) {
|
|
|
11514
11787
|
const bin = resolveCaliber();
|
|
11515
11788
|
const config = loadConfig();
|
|
11516
11789
|
if (!config) {
|
|
11517
|
-
console.log(
|
|
11790
|
+
console.log(chalk16.red("No LLM provider configured. Run ") + chalk16.hex("#83D1EB")(`${bin} config`) + chalk16.red(" first."));
|
|
11518
11791
|
throw new Error("__exit__");
|
|
11519
11792
|
}
|
|
11520
11793
|
const manifest = readManifest();
|
|
11521
11794
|
if (!manifest) {
|
|
11522
|
-
console.log(
|
|
11795
|
+
console.log(chalk16.yellow("No existing config found. Run ") + chalk16.hex("#83D1EB")(`${bin} init`) + chalk16.yellow(" first."));
|
|
11523
11796
|
throw new Error("__exit__");
|
|
11524
11797
|
}
|
|
11525
11798
|
const targetAgent = readState()?.targetAgent ?? ["claude", "cursor"];
|
|
@@ -11530,7 +11803,7 @@ async function regenerateCommand(options) {
|
|
|
11530
11803
|
const baselineScore = computeLocalScore(process.cwd(), targetAgent);
|
|
11531
11804
|
displayScoreSummary(baselineScore);
|
|
11532
11805
|
if (baselineScore.score === 100) {
|
|
11533
|
-
console.log(
|
|
11806
|
+
console.log(chalk16.green(" Your config is already at 100/100 \u2014 nothing to regenerate.\n"));
|
|
11534
11807
|
return;
|
|
11535
11808
|
}
|
|
11536
11809
|
const genSpinner = ora5("Regenerating config...").start();
|
|
@@ -11572,18 +11845,18 @@ async function regenerateCommand(options) {
|
|
|
11572
11845
|
const setupFiles = collectSetupFiles(generatedSetup, targetAgent);
|
|
11573
11846
|
const staged = stageFiles(setupFiles, process.cwd());
|
|
11574
11847
|
const totalChanges = staged.newFiles + staged.modifiedFiles;
|
|
11575
|
-
console.log(
|
|
11576
|
-
${
|
|
11848
|
+
console.log(chalk16.dim(`
|
|
11849
|
+
${chalk16.green(`${staged.newFiles} new`)} / ${chalk16.yellow(`${staged.modifiedFiles} modified`)} file${totalChanges !== 1 ? "s" : ""}
|
|
11577
11850
|
`));
|
|
11578
11851
|
if (totalChanges === 0) {
|
|
11579
|
-
console.log(
|
|
11852
|
+
console.log(chalk16.dim(" No changes needed \u2014 your configs are already up to date.\n"));
|
|
11580
11853
|
cleanupStaging();
|
|
11581
11854
|
return;
|
|
11582
11855
|
}
|
|
11583
11856
|
if (options.dryRun) {
|
|
11584
|
-
console.log(
|
|
11857
|
+
console.log(chalk16.yellow("[Dry run] Would write:"));
|
|
11585
11858
|
for (const f of staged.stagedFiles) {
|
|
11586
|
-
console.log(` ${f.isNew ?
|
|
11859
|
+
console.log(` ${f.isNew ? chalk16.green("+") : chalk16.yellow("~")} ${f.relativePath}`);
|
|
11587
11860
|
}
|
|
11588
11861
|
cleanupStaging();
|
|
11589
11862
|
return;
|
|
@@ -11602,7 +11875,7 @@ async function regenerateCommand(options) {
|
|
|
11602
11875
|
});
|
|
11603
11876
|
cleanupStaging();
|
|
11604
11877
|
if (action === "decline") {
|
|
11605
|
-
console.log(
|
|
11878
|
+
console.log(chalk16.dim("Regeneration cancelled. No files were modified."));
|
|
11606
11879
|
return;
|
|
11607
11880
|
}
|
|
11608
11881
|
const writeSpinner = ora5("Writing config files...").start();
|
|
@@ -11610,20 +11883,20 @@ async function regenerateCommand(options) {
|
|
|
11610
11883
|
const result = writeSetup(generatedSetup);
|
|
11611
11884
|
writeSpinner.succeed("Config files written");
|
|
11612
11885
|
for (const file of result.written) {
|
|
11613
|
-
console.log(` ${
|
|
11886
|
+
console.log(` ${chalk16.green("\u2713")} ${file}`);
|
|
11614
11887
|
}
|
|
11615
11888
|
if (result.deleted.length > 0) {
|
|
11616
11889
|
for (const file of result.deleted) {
|
|
11617
|
-
console.log(` ${
|
|
11890
|
+
console.log(` ${chalk16.red("\u2717")} ${file}`);
|
|
11618
11891
|
}
|
|
11619
11892
|
}
|
|
11620
11893
|
if (result.backupDir) {
|
|
11621
|
-
console.log(
|
|
11894
|
+
console.log(chalk16.dim(`
|
|
11622
11895
|
Backups saved to ${result.backupDir}`));
|
|
11623
11896
|
}
|
|
11624
11897
|
} catch (err) {
|
|
11625
11898
|
writeSpinner.fail("Failed to write files");
|
|
11626
|
-
console.error(
|
|
11899
|
+
console.error(chalk16.red(err instanceof Error ? err.message : "Unknown error"));
|
|
11627
11900
|
throw new Error("__exit__");
|
|
11628
11901
|
}
|
|
11629
11902
|
const sha = getCurrentHeadSha();
|
|
@@ -11635,21 +11908,21 @@ async function regenerateCommand(options) {
|
|
|
11635
11908
|
const afterScore = computeLocalScore(process.cwd(), targetAgent);
|
|
11636
11909
|
if (afterScore.score < baselineScore.score) {
|
|
11637
11910
|
console.log("");
|
|
11638
|
-
console.log(
|
|
11911
|
+
console.log(chalk16.yellow(` Score would drop from ${baselineScore.score} to ${afterScore.score} \u2014 reverting changes.`));
|
|
11639
11912
|
try {
|
|
11640
11913
|
const { restored, removed } = undoSetup();
|
|
11641
11914
|
if (restored.length > 0 || removed.length > 0) {
|
|
11642
|
-
console.log(
|
|
11915
|
+
console.log(chalk16.dim(` Reverted ${restored.length + removed.length} file${restored.length + removed.length === 1 ? "" : "s"} from backup.`));
|
|
11643
11916
|
}
|
|
11644
11917
|
} catch {
|
|
11645
11918
|
}
|
|
11646
|
-
console.log(
|
|
11919
|
+
console.log(chalk16.dim(" Run ") + chalk16.hex("#83D1EB")(`${bin} init --force`) + chalk16.dim(" to override.\n"));
|
|
11647
11920
|
return;
|
|
11648
11921
|
}
|
|
11649
11922
|
displayScoreDelta(baselineScore, afterScore);
|
|
11650
11923
|
trackRegenerateCompleted(action, Date.now());
|
|
11651
|
-
console.log(
|
|
11652
|
-
console.log(
|
|
11924
|
+
console.log(chalk16.bold.green(" Regeneration complete!"));
|
|
11925
|
+
console.log(chalk16.dim(" Run ") + chalk16.hex("#83D1EB")(`${bin} undo`) + chalk16.dim(" to revert changes.\n"));
|
|
11653
11926
|
}
|
|
11654
11927
|
|
|
11655
11928
|
// src/commands/score.ts
|
|
@@ -11657,7 +11930,7 @@ import fs37 from "fs";
|
|
|
11657
11930
|
import os7 from "os";
|
|
11658
11931
|
import path29 from "path";
|
|
11659
11932
|
import { execFileSync as execFileSync4 } from "child_process";
|
|
11660
|
-
import
|
|
11933
|
+
import chalk17 from "chalk";
|
|
11661
11934
|
init_resolve_caliber();
|
|
11662
11935
|
var CONFIG_FILES = ["CLAUDE.md", "AGENTS.md", ".cursorrules", "CALIBER_LEARNINGS.md"];
|
|
11663
11936
|
var CONFIG_DIRS = [".claude", ".cursor"];
|
|
@@ -11711,7 +11984,7 @@ async function scoreCommand(options) {
|
|
|
11711
11984
|
const baseResult = scoreBaseRef(options.compare, target);
|
|
11712
11985
|
if (!baseResult) {
|
|
11713
11986
|
console.error(
|
|
11714
|
-
|
|
11987
|
+
chalk17.red(`Could not score ref "${options.compare}" \u2014 branch or ref not found.`)
|
|
11715
11988
|
);
|
|
11716
11989
|
process.exitCode = 1;
|
|
11717
11990
|
return;
|
|
@@ -11737,18 +12010,18 @@ async function scoreCommand(options) {
|
|
|
11737
12010
|
return;
|
|
11738
12011
|
}
|
|
11739
12012
|
displayScore(result);
|
|
11740
|
-
const separator2 =
|
|
12013
|
+
const separator2 = chalk17.gray(" " + "\u2500".repeat(53));
|
|
11741
12014
|
console.log(separator2);
|
|
11742
12015
|
if (delta > 0) {
|
|
11743
12016
|
console.log(
|
|
11744
|
-
|
|
12017
|
+
chalk17.green(` +${delta}`) + chalk17.gray(` from ${options.compare} (${baseResult.score}/100)`)
|
|
11745
12018
|
);
|
|
11746
12019
|
} else if (delta < 0) {
|
|
11747
12020
|
console.log(
|
|
11748
|
-
|
|
12021
|
+
chalk17.red(` ${delta}`) + chalk17.gray(` from ${options.compare} (${baseResult.score}/100)`)
|
|
11749
12022
|
);
|
|
11750
12023
|
} else {
|
|
11751
|
-
console.log(
|
|
12024
|
+
console.log(chalk17.gray(` No change from ${options.compare} (${baseResult.score}/100)`));
|
|
11752
12025
|
}
|
|
11753
12026
|
console.log("");
|
|
11754
12027
|
return;
|
|
@@ -11762,7 +12035,7 @@ async function scoreCommand(options) {
|
|
|
11762
12035
|
return;
|
|
11763
12036
|
}
|
|
11764
12037
|
displayScore(result);
|
|
11765
|
-
const separator =
|
|
12038
|
+
const separator = chalk17.gray(" " + "\u2500".repeat(53));
|
|
11766
12039
|
console.log(separator);
|
|
11767
12040
|
const bin = resolveCaliber();
|
|
11768
12041
|
const failing = result.checks.filter((c) => !c.passed && c.maxPoints > 0).sort((a, b) => b.maxPoints - b.earnedPoints - (a.maxPoints - a.earnedPoints));
|
|
@@ -11770,22 +12043,22 @@ async function scoreCommand(options) {
|
|
|
11770
12043
|
const topFix = failing[0];
|
|
11771
12044
|
const pts = topFix.maxPoints - topFix.earnedPoints;
|
|
11772
12045
|
console.log(
|
|
11773
|
-
|
|
12046
|
+
chalk17.gray(" Biggest gain: ") + chalk17.yellow(`+${pts} pts`) + chalk17.gray(` from "${topFix.name}"`) + (topFix.suggestion ? chalk17.gray(` \u2014 ${topFix.suggestion}`) : "")
|
|
11774
12047
|
);
|
|
11775
12048
|
console.log(
|
|
11776
|
-
|
|
12049
|
+
chalk17.gray(" Run ") + chalk17.hex("#83D1EB")(`${bin} init`) + chalk17.gray(" to generate or update your agent config files.")
|
|
11777
12050
|
);
|
|
11778
12051
|
} else if (failing.length > 0) {
|
|
11779
12052
|
console.log(
|
|
11780
|
-
|
|
12053
|
+
chalk17.green(" Looking good!") + chalk17.gray(
|
|
11781
12054
|
` ${failing.length} optional improvement${failing.length === 1 ? "" : "s"} available.`
|
|
11782
12055
|
)
|
|
11783
12056
|
);
|
|
11784
12057
|
console.log(
|
|
11785
|
-
|
|
12058
|
+
chalk17.gray(" Run ") + chalk17.hex("#83D1EB")(`${bin} init`) + chalk17.gray(" to improve, or ") + chalk17.hex("#83D1EB")(`${bin} regenerate`) + chalk17.gray(" to rebuild from scratch.")
|
|
11786
12059
|
);
|
|
11787
12060
|
} else {
|
|
11788
|
-
console.log(
|
|
12061
|
+
console.log(chalk17.green(" Perfect score! Your agent configs are fully optimized."));
|
|
11789
12062
|
}
|
|
11790
12063
|
console.log("");
|
|
11791
12064
|
}
|
|
@@ -11793,12 +12066,12 @@ async function scoreCommand(options) {
|
|
|
11793
12066
|
// src/commands/refresh.ts
|
|
11794
12067
|
import fs42 from "fs";
|
|
11795
12068
|
import path34 from "path";
|
|
11796
|
-
import
|
|
12069
|
+
import chalk18 from "chalk";
|
|
11797
12070
|
import ora6 from "ora";
|
|
11798
12071
|
import pLimit from "p-limit";
|
|
11799
12072
|
|
|
11800
12073
|
// src/lib/git-diff.ts
|
|
11801
|
-
import { execSync as
|
|
12074
|
+
import { execSync as execSync17 } from "child_process";
|
|
11802
12075
|
var MAX_DIFF_BYTES = 1e5;
|
|
11803
12076
|
var DOC_PATTERNS = [
|
|
11804
12077
|
"CLAUDE.md",
|
|
@@ -11824,7 +12097,7 @@ function excludeArgs() {
|
|
|
11824
12097
|
}
|
|
11825
12098
|
function safeExec(cmd) {
|
|
11826
12099
|
try {
|
|
11827
|
-
return
|
|
12100
|
+
return execSync17(cmd, {
|
|
11828
12101
|
encoding: "utf-8",
|
|
11829
12102
|
stdio: ["pipe", "pipe", "pipe"],
|
|
11830
12103
|
maxBuffer: 10 * 1024 * 1024
|
|
@@ -12454,7 +12727,7 @@ async function refreshDir(repoDir, dir, diff, options) {
|
|
|
12454
12727
|
const quiet = !!options.quiet;
|
|
12455
12728
|
const suppress = !!options.suppressSpinner;
|
|
12456
12729
|
const effectiveQuiet = quiet || suppress;
|
|
12457
|
-
const prefix = options.label ? `${
|
|
12730
|
+
const prefix = options.label ? `${chalk18.bold(options.label)} ` : "";
|
|
12458
12731
|
const absDir = dir === "." ? repoDir : path34.resolve(repoDir, dir);
|
|
12459
12732
|
const scope = dir === "." ? void 0 : dir;
|
|
12460
12733
|
const spinner = effectiveQuiet ? null : ora6(`${prefix}Analyzing changes...`).start();
|
|
@@ -12511,10 +12784,10 @@ async function refreshDir(repoDir, dir, diff, options) {
|
|
|
12511
12784
|
if (options.dryRun) {
|
|
12512
12785
|
spinner?.info(`${prefix}Dry run \u2014 would update:`);
|
|
12513
12786
|
for (const doc of response.docsUpdated) {
|
|
12514
|
-
console.log(` ${
|
|
12787
|
+
console.log(` ${chalk18.yellow("~")} ${doc}`);
|
|
12515
12788
|
}
|
|
12516
12789
|
if (response.changesSummary) {
|
|
12517
|
-
console.log(
|
|
12790
|
+
console.log(chalk18.dim(`
|
|
12518
12791
|
${response.changesSummary}`));
|
|
12519
12792
|
}
|
|
12520
12793
|
return { written: [], fileChanges: [], syncedAgents: [], changesSummary: null };
|
|
@@ -12555,7 +12828,7 @@ async function refreshDir(repoDir, dir, diff, options) {
|
|
|
12555
12828
|
);
|
|
12556
12829
|
log2(
|
|
12557
12830
|
effectiveQuiet,
|
|
12558
|
-
|
|
12831
|
+
chalk18.dim(` Config quality gate prevented a regression. No files were changed.`)
|
|
12559
12832
|
);
|
|
12560
12833
|
return { written: [], fileChanges: [], syncedAgents: [], changesSummary: null };
|
|
12561
12834
|
}
|
|
@@ -12568,18 +12841,18 @@ async function refreshDir(repoDir, dir, diff, options) {
|
|
|
12568
12841
|
if (!suppress) {
|
|
12569
12842
|
for (const file of written) {
|
|
12570
12843
|
const desc = fileChangesMap.get(file);
|
|
12571
|
-
const suffix = desc ?
|
|
12572
|
-
log2(effectiveQuiet, ` ${
|
|
12844
|
+
const suffix = desc ? chalk18.dim(` \u2014 ${desc}`) : "";
|
|
12845
|
+
log2(effectiveQuiet, ` ${chalk18.green("\u2713")} ${file}${suffix}`);
|
|
12573
12846
|
}
|
|
12574
12847
|
if (syncedAgents.length > 1) {
|
|
12575
12848
|
log2(
|
|
12576
12849
|
effectiveQuiet,
|
|
12577
|
-
|
|
12850
|
+
chalk18.cyan(`
|
|
12578
12851
|
${syncedAgents.length} agent formats in sync (${syncedAgents.join(", ")})`)
|
|
12579
12852
|
);
|
|
12580
12853
|
}
|
|
12581
12854
|
if (response.changesSummary) {
|
|
12582
|
-
log2(effectiveQuiet,
|
|
12855
|
+
log2(effectiveQuiet, chalk18.dim(`
|
|
12583
12856
|
${response.changesSummary}`));
|
|
12584
12857
|
}
|
|
12585
12858
|
}
|
|
@@ -12587,7 +12860,7 @@ async function refreshDir(repoDir, dir, diff, options) {
|
|
|
12587
12860
|
}
|
|
12588
12861
|
async function refreshSingleRepo(repoDir, options) {
|
|
12589
12862
|
const quiet = !!options.quiet;
|
|
12590
|
-
const prefix = options.label ? `${
|
|
12863
|
+
const prefix = options.label ? `${chalk18.bold(options.label)} ` : "";
|
|
12591
12864
|
const state = readState();
|
|
12592
12865
|
const lastSha = state?.lastRefreshSha ?? null;
|
|
12593
12866
|
const currentSha = getCurrentHeadSha();
|
|
@@ -12596,7 +12869,7 @@ async function refreshSingleRepo(repoDir, options) {
|
|
|
12596
12869
|
if (elapsed < REFRESH_COOLDOWN_MS && elapsed > 0) {
|
|
12597
12870
|
log2(
|
|
12598
12871
|
quiet,
|
|
12599
|
-
|
|
12872
|
+
chalk18.dim(`${prefix}Skipped \u2014 last refresh was ${Math.round(elapsed / 1e3)}s ago.`)
|
|
12600
12873
|
);
|
|
12601
12874
|
return;
|
|
12602
12875
|
}
|
|
@@ -12606,14 +12879,14 @@ async function refreshSingleRepo(repoDir, options) {
|
|
|
12606
12879
|
if (currentSha) {
|
|
12607
12880
|
writeState({ lastRefreshSha: currentSha, lastRefreshTimestamp: (/* @__PURE__ */ new Date()).toISOString() });
|
|
12608
12881
|
}
|
|
12609
|
-
log2(quiet,
|
|
12882
|
+
log2(quiet, chalk18.dim(`${prefix}No changes since last refresh.`));
|
|
12610
12883
|
return;
|
|
12611
12884
|
}
|
|
12612
12885
|
const configDirs = discoverConfigDirs(repoDir);
|
|
12613
12886
|
if (configDirs.length <= 1) {
|
|
12614
12887
|
await refreshDir(repoDir, ".", diff, options);
|
|
12615
12888
|
} else {
|
|
12616
|
-
log2(quiet,
|
|
12889
|
+
log2(quiet, chalk18.dim(`${prefix}Found configs in ${configDirs.length} directories
|
|
12617
12890
|
`));
|
|
12618
12891
|
const dirsWithChanges = configDirs.map((dir) => ({ dir, scopedDiff: scopeDiffToDir(diff, dir, configDirs) })).filter(({ scopedDiff }) => scopedDiff.hasChanges);
|
|
12619
12892
|
const parallelSpinner = quiet ? null : ora6(
|
|
@@ -12641,7 +12914,7 @@ async function refreshSingleRepo(repoDir, options) {
|
|
|
12641
12914
|
hadFailure = true;
|
|
12642
12915
|
log2(
|
|
12643
12916
|
quiet,
|
|
12644
|
-
|
|
12917
|
+
chalk18.yellow(
|
|
12645
12918
|
` ${dirLabel}: refresh failed \u2014 ${result.reason instanceof Error ? result.reason.message : "unknown error"}`
|
|
12646
12919
|
)
|
|
12647
12920
|
);
|
|
@@ -12650,20 +12923,20 @@ async function refreshSingleRepo(repoDir, options) {
|
|
|
12650
12923
|
const fileChangesMap = new Map(fileChanges.map((fc) => [fc.file, fc.description]));
|
|
12651
12924
|
for (const file of written) {
|
|
12652
12925
|
const desc = fileChangesMap.get(file);
|
|
12653
|
-
const suffix = desc ?
|
|
12654
|
-
log2(quiet, ` ${
|
|
12926
|
+
const suffix = desc ? chalk18.dim(` \u2014 ${desc}`) : "";
|
|
12927
|
+
log2(quiet, ` ${chalk18.green("\u2713")} ${dirLabel}/${file}${suffix}`);
|
|
12655
12928
|
}
|
|
12656
12929
|
if (syncedAgents.length > 1) {
|
|
12657
12930
|
log2(
|
|
12658
12931
|
quiet,
|
|
12659
|
-
|
|
12932
|
+
chalk18.cyan(
|
|
12660
12933
|
`
|
|
12661
12934
|
${syncedAgents.length} agent formats in sync (${syncedAgents.join(", ")})`
|
|
12662
12935
|
)
|
|
12663
12936
|
);
|
|
12664
12937
|
}
|
|
12665
12938
|
if (changesSummary) {
|
|
12666
|
-
log2(quiet,
|
|
12939
|
+
log2(quiet, chalk18.dim(`
|
|
12667
12940
|
${changesSummary}`));
|
|
12668
12941
|
}
|
|
12669
12942
|
}
|
|
@@ -12674,7 +12947,7 @@ async function refreshSingleRepo(repoDir, options) {
|
|
|
12674
12947
|
}
|
|
12675
12948
|
const builtinWritten = ensureBuiltinSkills();
|
|
12676
12949
|
for (const file of builtinWritten) {
|
|
12677
|
-
log2(quiet, ` ${
|
|
12950
|
+
log2(quiet, ` ${chalk18.green("\u2713")} ${file} ${chalk18.dim("(built-in)")}`);
|
|
12678
12951
|
}
|
|
12679
12952
|
clearRefreshError();
|
|
12680
12953
|
if (currentSha) {
|
|
@@ -12690,11 +12963,11 @@ async function refreshCommand(options) {
|
|
|
12690
12963
|
if (!quiet) {
|
|
12691
12964
|
const lastError = readRefreshError();
|
|
12692
12965
|
if (lastError) {
|
|
12693
|
-
console.log(
|
|
12966
|
+
console.log(chalk18.yellow(`
|
|
12694
12967
|
\u26A0 Last refresh failed (${lastError.timestamp}):`));
|
|
12695
|
-
console.log(
|
|
12968
|
+
console.log(chalk18.dim(` ${lastError.error}`));
|
|
12696
12969
|
console.log(
|
|
12697
|
-
|
|
12970
|
+
chalk18.dim(
|
|
12698
12971
|
` Run with --debug for full details, or report at https://github.com/caliber-ai-org/ai-setup/issues
|
|
12699
12972
|
`
|
|
12700
12973
|
)
|
|
@@ -12707,7 +12980,7 @@ async function refreshCommand(options) {
|
|
|
12707
12980
|
if (!config) {
|
|
12708
12981
|
if (quiet) return;
|
|
12709
12982
|
console.log(
|
|
12710
|
-
|
|
12983
|
+
chalk18.red("No LLM provider configured. Run ") + chalk18.hex("#83D1EB")(`${resolveCaliber()} config`) + chalk18.red(" (e.g. choose Cursor) or set an API key.")
|
|
12711
12984
|
);
|
|
12712
12985
|
throw new Error("__exit__");
|
|
12713
12986
|
}
|
|
@@ -12720,11 +12993,11 @@ async function refreshCommand(options) {
|
|
|
12720
12993
|
if (repos.length === 0) {
|
|
12721
12994
|
if (quiet) return;
|
|
12722
12995
|
console.log(
|
|
12723
|
-
|
|
12996
|
+
chalk18.red("Not inside a git repository and no git repos found in child directories.")
|
|
12724
12997
|
);
|
|
12725
12998
|
throw new Error("__exit__");
|
|
12726
12999
|
}
|
|
12727
|
-
log2(quiet,
|
|
13000
|
+
log2(quiet, chalk18.dim(`Found ${repos.length} git repo${repos.length === 1 ? "" : "s"}
|
|
12728
13001
|
`));
|
|
12729
13002
|
const originalDir = process.cwd();
|
|
12730
13003
|
for (const repo of repos) {
|
|
@@ -12737,7 +13010,7 @@ async function refreshCommand(options) {
|
|
|
12737
13010
|
writeRefreshError(err);
|
|
12738
13011
|
log2(
|
|
12739
13012
|
quiet,
|
|
12740
|
-
|
|
13013
|
+
chalk18.yellow(
|
|
12741
13014
|
`${repoName}: refresh failed \u2014 ${err instanceof Error ? err.message : "unknown error"}`
|
|
12742
13015
|
)
|
|
12743
13016
|
);
|
|
@@ -12750,13 +13023,13 @@ async function refreshCommand(options) {
|
|
|
12750
13023
|
writeRefreshError(err);
|
|
12751
13024
|
if (quiet) return;
|
|
12752
13025
|
const msg = err instanceof Error ? err.message : "Unknown error";
|
|
12753
|
-
console.log(
|
|
13026
|
+
console.log(chalk18.red(`Refresh failed: ${msg}`));
|
|
12754
13027
|
throw new Error("__exit__");
|
|
12755
13028
|
}
|
|
12756
13029
|
}
|
|
12757
13030
|
|
|
12758
13031
|
// src/commands/hooks.ts
|
|
12759
|
-
import
|
|
13032
|
+
import chalk19 from "chalk";
|
|
12760
13033
|
import fs43 from "fs";
|
|
12761
13034
|
var HOOKS = [
|
|
12762
13035
|
{
|
|
@@ -12793,41 +13066,41 @@ var HOOKS = [
|
|
|
12793
13066
|
}
|
|
12794
13067
|
];
|
|
12795
13068
|
function printStatus() {
|
|
12796
|
-
console.log(
|
|
13069
|
+
console.log(chalk19.bold("\n Hooks\n"));
|
|
12797
13070
|
for (const hook of HOOKS) {
|
|
12798
13071
|
const installed = hook.isInstalled();
|
|
12799
|
-
const icon = installed ?
|
|
12800
|
-
const state = installed ?
|
|
13072
|
+
const icon = installed ? chalk19.green("\u2713") : chalk19.dim("\u2717");
|
|
13073
|
+
const state = installed ? chalk19.green("enabled") : chalk19.dim("disabled");
|
|
12801
13074
|
console.log(` ${icon} ${hook.label.padEnd(26)} ${state}`);
|
|
12802
|
-
console.log(
|
|
13075
|
+
console.log(chalk19.dim(` ${hook.description}`));
|
|
12803
13076
|
}
|
|
12804
13077
|
console.log("");
|
|
12805
13078
|
}
|
|
12806
13079
|
async function hooksCommand(options) {
|
|
12807
13080
|
if (!options.install && !options.remove) {
|
|
12808
13081
|
console.log(
|
|
12809
|
-
|
|
13082
|
+
chalk19.dim("\n Note: caliber now adds refresh instructions directly to config files.")
|
|
12810
13083
|
);
|
|
12811
13084
|
console.log(
|
|
12812
|
-
|
|
13085
|
+
chalk19.dim(" These hooks are available for non-agent workflows (manual commits).\n")
|
|
12813
13086
|
);
|
|
12814
13087
|
}
|
|
12815
13088
|
if (options.install) {
|
|
12816
13089
|
for (const hook of HOOKS) {
|
|
12817
13090
|
const result = hook.install();
|
|
12818
13091
|
if (result.alreadyInstalled) {
|
|
12819
|
-
console.log(
|
|
13092
|
+
console.log(chalk19.dim(` ${hook.label} already enabled.`));
|
|
12820
13093
|
} else {
|
|
12821
|
-
console.log(
|
|
13094
|
+
console.log(chalk19.green(" \u2713") + ` ${hook.label} enabled`);
|
|
12822
13095
|
}
|
|
12823
13096
|
}
|
|
12824
13097
|
if (fs43.existsSync(".claude")) {
|
|
12825
13098
|
const r = installLearningHooks();
|
|
12826
|
-
if (r.installed) console.log(
|
|
13099
|
+
if (r.installed) console.log(chalk19.green(" \u2713") + " Claude Code learning hooks enabled");
|
|
12827
13100
|
}
|
|
12828
13101
|
if (fs43.existsSync(".cursor")) {
|
|
12829
13102
|
const r = installCursorLearningHooks();
|
|
12830
|
-
if (r.installed) console.log(
|
|
13103
|
+
if (r.installed) console.log(chalk19.green(" \u2713") + " Cursor learning hooks enabled");
|
|
12831
13104
|
}
|
|
12832
13105
|
return;
|
|
12833
13106
|
}
|
|
@@ -12835,9 +13108,9 @@ async function hooksCommand(options) {
|
|
|
12835
13108
|
for (const hook of HOOKS) {
|
|
12836
13109
|
const result = hook.remove();
|
|
12837
13110
|
if (result.notFound) {
|
|
12838
|
-
console.log(
|
|
13111
|
+
console.log(chalk19.dim(` ${hook.label} already disabled.`));
|
|
12839
13112
|
} else {
|
|
12840
|
-
console.log(
|
|
13113
|
+
console.log(chalk19.green(" \u2713") + ` ${hook.label} removed`);
|
|
12841
13114
|
}
|
|
12842
13115
|
}
|
|
12843
13116
|
return;
|
|
@@ -12852,18 +13125,18 @@ async function hooksCommand(options) {
|
|
|
12852
13125
|
const states = HOOKS.map((h) => h.isInstalled());
|
|
12853
13126
|
function render() {
|
|
12854
13127
|
const lines = [];
|
|
12855
|
-
lines.push(
|
|
13128
|
+
lines.push(chalk19.bold(" Hooks"));
|
|
12856
13129
|
lines.push("");
|
|
12857
13130
|
for (let i = 0; i < HOOKS.length; i++) {
|
|
12858
13131
|
const hook = HOOKS[i];
|
|
12859
13132
|
const enabled = states[i];
|
|
12860
|
-
const toggle = enabled ?
|
|
12861
|
-
const ptr = i === cursor ?
|
|
13133
|
+
const toggle = enabled ? chalk19.green("[on] ") : chalk19.dim("[off]");
|
|
13134
|
+
const ptr = i === cursor ? chalk19.cyan(">") : " ";
|
|
12862
13135
|
lines.push(` ${ptr} ${toggle} ${hook.label}`);
|
|
12863
|
-
lines.push(
|
|
13136
|
+
lines.push(chalk19.dim(` ${hook.description}`));
|
|
12864
13137
|
}
|
|
12865
13138
|
lines.push("");
|
|
12866
|
-
lines.push(
|
|
13139
|
+
lines.push(chalk19.dim(" \u2191\u2193 navigate \u23B5 toggle a all on n all off \u23CE apply q cancel"));
|
|
12867
13140
|
return lines.join("\n");
|
|
12868
13141
|
}
|
|
12869
13142
|
function draw(initial) {
|
|
@@ -12894,16 +13167,16 @@ async function hooksCommand(options) {
|
|
|
12894
13167
|
const wantEnabled = states[i];
|
|
12895
13168
|
if (wantEnabled && !wasInstalled) {
|
|
12896
13169
|
hook.install();
|
|
12897
|
-
console.log(
|
|
13170
|
+
console.log(chalk19.green(" \u2713") + ` ${hook.label} enabled`);
|
|
12898
13171
|
changed++;
|
|
12899
13172
|
} else if (!wantEnabled && wasInstalled) {
|
|
12900
13173
|
hook.remove();
|
|
12901
|
-
console.log(
|
|
13174
|
+
console.log(chalk19.green(" \u2713") + ` ${hook.label} disabled`);
|
|
12902
13175
|
changed++;
|
|
12903
13176
|
}
|
|
12904
13177
|
}
|
|
12905
13178
|
if (changed === 0) {
|
|
12906
|
-
console.log(
|
|
13179
|
+
console.log(chalk19.dim(" No changes."));
|
|
12907
13180
|
}
|
|
12908
13181
|
console.log("");
|
|
12909
13182
|
}
|
|
@@ -12939,7 +13212,7 @@ async function hooksCommand(options) {
|
|
|
12939
13212
|
case "\x1B":
|
|
12940
13213
|
case "":
|
|
12941
13214
|
cleanup();
|
|
12942
|
-
console.log(
|
|
13215
|
+
console.log(chalk19.dim("\n Cancelled.\n"));
|
|
12943
13216
|
resolve3();
|
|
12944
13217
|
break;
|
|
12945
13218
|
}
|
|
@@ -12950,52 +13223,52 @@ async function hooksCommand(options) {
|
|
|
12950
13223
|
|
|
12951
13224
|
// src/commands/config.ts
|
|
12952
13225
|
init_config();
|
|
12953
|
-
import
|
|
13226
|
+
import chalk20 from "chalk";
|
|
12954
13227
|
async function configCommand() {
|
|
12955
13228
|
const existing = loadConfig();
|
|
12956
13229
|
if (existing) {
|
|
12957
13230
|
const displayModel = getDisplayModel(existing);
|
|
12958
13231
|
const fastModel = getFastModel();
|
|
12959
|
-
console.log(
|
|
12960
|
-
console.log(` Provider: ${
|
|
12961
|
-
console.log(` Model: ${
|
|
13232
|
+
console.log(chalk20.bold("\nCurrent Configuration\n"));
|
|
13233
|
+
console.log(` Provider: ${chalk20.cyan(existing.provider)}`);
|
|
13234
|
+
console.log(` Model: ${chalk20.cyan(displayModel)}`);
|
|
12962
13235
|
if (fastModel) {
|
|
12963
|
-
console.log(` Scan: ${
|
|
13236
|
+
console.log(` Scan: ${chalk20.cyan(fastModel)}`);
|
|
12964
13237
|
}
|
|
12965
13238
|
if (existing.apiKey) {
|
|
12966
13239
|
const masked = existing.apiKey.slice(0, 8) + "..." + existing.apiKey.slice(-4);
|
|
12967
|
-
console.log(` API Key: ${
|
|
13240
|
+
console.log(` API Key: ${chalk20.dim(masked)}`);
|
|
12968
13241
|
}
|
|
12969
13242
|
if (existing.provider === "cursor") {
|
|
12970
|
-
console.log(` Seat: ${
|
|
13243
|
+
console.log(` Seat: ${chalk20.dim("Cursor (agent acp)")}`);
|
|
12971
13244
|
}
|
|
12972
13245
|
if (existing.provider === "claude-cli") {
|
|
12973
|
-
console.log(` Seat: ${
|
|
13246
|
+
console.log(` Seat: ${chalk20.dim("Claude Code (claude -p)")}`);
|
|
12974
13247
|
}
|
|
12975
13248
|
if (existing.baseUrl) {
|
|
12976
|
-
console.log(` Base URL: ${
|
|
13249
|
+
console.log(` Base URL: ${chalk20.dim(existing.baseUrl)}`);
|
|
12977
13250
|
}
|
|
12978
13251
|
if (existing.vertexProjectId) {
|
|
12979
|
-
console.log(` Vertex Project: ${
|
|
12980
|
-
console.log(` Vertex Region: ${
|
|
13252
|
+
console.log(` Vertex Project: ${chalk20.dim(existing.vertexProjectId)}`);
|
|
13253
|
+
console.log(` Vertex Region: ${chalk20.dim(existing.vertexRegion || "us-east5")}`);
|
|
12981
13254
|
}
|
|
12982
|
-
console.log(` Source: ${
|
|
13255
|
+
console.log(` Source: ${chalk20.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())}`);
|
|
12983
13256
|
console.log("");
|
|
12984
13257
|
}
|
|
12985
13258
|
await runInteractiveProviderSetup();
|
|
12986
13259
|
const updated = loadConfig();
|
|
12987
13260
|
if (updated) trackConfigProviderSet(updated.provider);
|
|
12988
|
-
console.log(
|
|
12989
|
-
console.log(
|
|
13261
|
+
console.log(chalk20.green("\n\u2713 Configuration saved"));
|
|
13262
|
+
console.log(chalk20.dim(` ${getConfigFilePath()}
|
|
12990
13263
|
`));
|
|
12991
|
-
console.log(
|
|
12992
|
-
console.log(
|
|
13264
|
+
console.log(chalk20.dim(" You can also set environment variables instead:"));
|
|
13265
|
+
console.log(chalk20.dim(" ANTHROPIC_API_KEY, OPENAI_API_KEY, VERTEX_PROJECT_ID, CALIBER_USE_CURSOR_SEAT=1, or CALIBER_USE_CLAUDE_CLI=1\n"));
|
|
12993
13266
|
}
|
|
12994
13267
|
|
|
12995
13268
|
// src/commands/learn.ts
|
|
12996
13269
|
import fs47 from "fs";
|
|
12997
13270
|
import path38 from "path";
|
|
12998
|
-
import
|
|
13271
|
+
import chalk22 from "chalk";
|
|
12999
13272
|
|
|
13000
13273
|
// src/learner/stdin.ts
|
|
13001
13274
|
var STDIN_TIMEOUT_MS = 5e3;
|
|
@@ -13195,7 +13468,7 @@ function releaseFinalizeLock() {
|
|
|
13195
13468
|
// src/lib/notifications.ts
|
|
13196
13469
|
import fs45 from "fs";
|
|
13197
13470
|
import path36 from "path";
|
|
13198
|
-
import
|
|
13471
|
+
import chalk21 from "chalk";
|
|
13199
13472
|
function notificationFilePath() {
|
|
13200
13473
|
return path36.join(getLearningDir(), "last-finalize-summary.json");
|
|
13201
13474
|
}
|
|
@@ -13215,13 +13488,13 @@ function checkPendingNotifications() {
|
|
|
13215
13488
|
if (!summary.newItemCount || summary.newItemCount === 0) return;
|
|
13216
13489
|
const wasteLabel = summary.wasteTokens > 0 ? ` (~${summary.wasteTokens.toLocaleString()} wasted tokens captured)` : "";
|
|
13217
13490
|
console.log(
|
|
13218
|
-
|
|
13491
|
+
chalk21.dim(`caliber: learned ${summary.newItemCount} new pattern${summary.newItemCount === 1 ? "" : "s"} from your last session${wasteLabel}`)
|
|
13219
13492
|
);
|
|
13220
13493
|
for (const item of summary.newItems.slice(0, 3)) {
|
|
13221
|
-
console.log(
|
|
13494
|
+
console.log(chalk21.dim(` + ${item.replace(/^- /, "").slice(0, 80)}`));
|
|
13222
13495
|
}
|
|
13223
13496
|
if (summary.newItems.length > 3) {
|
|
13224
|
-
console.log(
|
|
13497
|
+
console.log(chalk21.dim(` ... and ${summary.newItems.length - 3} more`));
|
|
13225
13498
|
}
|
|
13226
13499
|
console.log("");
|
|
13227
13500
|
} catch {
|
|
@@ -13694,13 +13967,13 @@ async function learnObserveCommand(options) {
|
|
|
13694
13967
|
try {
|
|
13695
13968
|
const { resolveCaliber: resolveCaliber2, isNpxResolution: isNpxResolution2 } = await Promise.resolve().then(() => (init_resolve_caliber(), resolve_caliber_exports));
|
|
13696
13969
|
const bin = resolveCaliber2();
|
|
13697
|
-
const { spawn:
|
|
13970
|
+
const { spawn: spawn5 } = await import("child_process");
|
|
13698
13971
|
const logPath = path38.join(getLearningDir(), LEARNING_FINALIZE_LOG);
|
|
13699
13972
|
if (!fs47.existsSync(getLearningDir())) fs47.mkdirSync(getLearningDir(), { recursive: true });
|
|
13700
13973
|
const logFd = fs47.openSync(logPath, "a");
|
|
13701
13974
|
const NPX_SUFFIX = " --yes @rely-ai/caliber";
|
|
13702
13975
|
const [exe, binArgs] = isNpxResolution2() ? [bin.slice(0, -NPX_SUFFIX.length) || "npx", ["--yes", "@rely-ai/caliber"]] : [bin, []];
|
|
13703
|
-
|
|
13976
|
+
spawn5(exe, [...binArgs, "learn", "finalize", "--auto", "--incremental"], {
|
|
13704
13977
|
detached: true,
|
|
13705
13978
|
stdio: ["ignore", logFd, logFd]
|
|
13706
13979
|
}).unref();
|
|
@@ -13718,7 +13991,7 @@ async function learnFinalizeCommand(options) {
|
|
|
13718
13991
|
const { isCaliberRunning: isCaliberRunning2 } = await Promise.resolve().then(() => (init_lock(), lock_exports));
|
|
13719
13992
|
if (isCaliberRunning2()) {
|
|
13720
13993
|
if (!isAuto)
|
|
13721
|
-
console.log(
|
|
13994
|
+
console.log(chalk22.dim("caliber: skipping finalize \u2014 another caliber process is running"));
|
|
13722
13995
|
return;
|
|
13723
13996
|
}
|
|
13724
13997
|
}
|
|
@@ -13727,7 +14000,7 @@ async function learnFinalizeCommand(options) {
|
|
|
13727
14000
|
}
|
|
13728
14001
|
if (!acquireFinalizeLock()) {
|
|
13729
14002
|
if (!isAuto)
|
|
13730
|
-
console.log(
|
|
14003
|
+
console.log(chalk22.dim("caliber: skipping finalize \u2014 another finalize is in progress"));
|
|
13731
14004
|
return;
|
|
13732
14005
|
}
|
|
13733
14006
|
let analyzed = false;
|
|
@@ -13736,7 +14009,7 @@ async function learnFinalizeCommand(options) {
|
|
|
13736
14009
|
if (!config) {
|
|
13737
14010
|
if (isAuto) return;
|
|
13738
14011
|
console.log(
|
|
13739
|
-
|
|
14012
|
+
chalk22.yellow(
|
|
13740
14013
|
`caliber: no LLM provider configured \u2014 run \`${resolveCaliber()} config\` first`
|
|
13741
14014
|
)
|
|
13742
14015
|
);
|
|
@@ -13749,7 +14022,7 @@ async function learnFinalizeCommand(options) {
|
|
|
13749
14022
|
if (allEvents.length < threshold) {
|
|
13750
14023
|
if (!isAuto)
|
|
13751
14024
|
console.log(
|
|
13752
|
-
|
|
14025
|
+
chalk22.dim(
|
|
13753
14026
|
`caliber: ${allEvents.length}/${threshold} events recorded \u2014 need more before analysis`
|
|
13754
14027
|
)
|
|
13755
14028
|
);
|
|
@@ -13763,7 +14036,7 @@ async function learnFinalizeCommand(options) {
|
|
|
13763
14036
|
if (events.length < threshold) {
|
|
13764
14037
|
if (!isAuto)
|
|
13765
14038
|
console.log(
|
|
13766
|
-
|
|
14039
|
+
chalk22.dim(
|
|
13767
14040
|
`caliber: ${events.length}/${threshold} new events since last analysis \u2014 need more`
|
|
13768
14041
|
)
|
|
13769
14042
|
);
|
|
@@ -13803,12 +14076,12 @@ async function learnFinalizeCommand(options) {
|
|
|
13803
14076
|
} else {
|
|
13804
14077
|
const wasteLabel = waste.totalWasteTokens > 0 ? ` (~${waste.totalWasteTokens.toLocaleString()} wasted tokens captured)` : "";
|
|
13805
14078
|
console.log(
|
|
13806
|
-
|
|
14079
|
+
chalk22.dim(
|
|
13807
14080
|
`caliber: learned ${result.newItemCount} new pattern${result.newItemCount === 1 ? "" : "s"}${wasteLabel}`
|
|
13808
14081
|
)
|
|
13809
14082
|
);
|
|
13810
14083
|
for (const item of result.newItems) {
|
|
13811
|
-
console.log(
|
|
14084
|
+
console.log(chalk22.dim(` + ${item.replace(/^- /, "").slice(0, 80)}`));
|
|
13812
14085
|
}
|
|
13813
14086
|
}
|
|
13814
14087
|
const wastePerLearning = Math.round(waste.totalWasteTokens / result.newItemCount);
|
|
@@ -13902,7 +14175,7 @@ async function learnFinalizeCommand(options) {
|
|
|
13902
14175
|
const staleLearnings = findStaleLearnings(roiStats);
|
|
13903
14176
|
if (staleLearnings.length > 0 && !isAuto) {
|
|
13904
14177
|
console.log(
|
|
13905
|
-
|
|
14178
|
+
chalk22.yellow(
|
|
13906
14179
|
`caliber: ${staleLearnings.length} learning${staleLearnings.length === 1 ? "" : "s"} never activated \u2014 run \`${resolveCaliber()} learn list --verbose\` to review`
|
|
13907
14180
|
)
|
|
13908
14181
|
);
|
|
@@ -13911,7 +14184,7 @@ async function learnFinalizeCommand(options) {
|
|
|
13911
14184
|
if (!isAuto && t.estimatedSavingsTokens > 0) {
|
|
13912
14185
|
const totalLearnings = existingLearnedItems + newLearningsProduced;
|
|
13913
14186
|
console.log(
|
|
13914
|
-
|
|
14187
|
+
chalk22.dim(
|
|
13915
14188
|
`caliber: ${totalLearnings} learnings active \u2014 est. ~${t.estimatedSavingsTokens.toLocaleString()} tokens saved across ${t.totalSessionsWithLearnings} sessions`
|
|
13916
14189
|
)
|
|
13917
14190
|
);
|
|
@@ -13919,7 +14192,7 @@ async function learnFinalizeCommand(options) {
|
|
|
13919
14192
|
} catch (err) {
|
|
13920
14193
|
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
13921
14194
|
if (options?.force && !isAuto) {
|
|
13922
|
-
console.error(
|
|
14195
|
+
console.error(chalk22.red("caliber: finalize failed \u2014"), errorMsg);
|
|
13923
14196
|
}
|
|
13924
14197
|
writeFinalizeError(errorMsg);
|
|
13925
14198
|
} finally {
|
|
@@ -13942,51 +14215,51 @@ async function learnInstallCommand() {
|
|
|
13942
14215
|
if (fs47.existsSync(".claude")) {
|
|
13943
14216
|
const r = installLearningHooks();
|
|
13944
14217
|
if (r.installed) {
|
|
13945
|
-
console.log(
|
|
14218
|
+
console.log(chalk22.green("\u2713") + " Claude Code learning hooks installed");
|
|
13946
14219
|
anyInstalled = true;
|
|
13947
14220
|
} else if (r.alreadyInstalled) {
|
|
13948
|
-
console.log(
|
|
14221
|
+
console.log(chalk22.dim(" Claude Code hooks already installed"));
|
|
13949
14222
|
}
|
|
13950
14223
|
}
|
|
13951
14224
|
if (fs47.existsSync(".cursor")) {
|
|
13952
14225
|
const r = installCursorLearningHooks();
|
|
13953
14226
|
if (r.installed) {
|
|
13954
|
-
console.log(
|
|
14227
|
+
console.log(chalk22.green("\u2713") + " Cursor learning hooks installed");
|
|
13955
14228
|
anyInstalled = true;
|
|
13956
14229
|
} else if (r.alreadyInstalled) {
|
|
13957
|
-
console.log(
|
|
14230
|
+
console.log(chalk22.dim(" Cursor hooks already installed"));
|
|
13958
14231
|
}
|
|
13959
14232
|
}
|
|
13960
14233
|
if (!fs47.existsSync(".claude") && !fs47.existsSync(".cursor")) {
|
|
13961
|
-
console.log(
|
|
14234
|
+
console.log(chalk22.yellow("No .claude/ or .cursor/ directory found."));
|
|
13962
14235
|
console.log(
|
|
13963
|
-
|
|
14236
|
+
chalk22.dim(` Run \`${resolveCaliber()} init\` first, or create the directory manually.`)
|
|
13964
14237
|
);
|
|
13965
14238
|
return;
|
|
13966
14239
|
}
|
|
13967
14240
|
if (anyInstalled) {
|
|
13968
14241
|
console.log(
|
|
13969
|
-
|
|
14242
|
+
chalk22.dim(
|
|
13970
14243
|
` Tool usage will be recorded and learnings extracted after \u2265${MIN_EVENTS_FOR_ANALYSIS} events.`
|
|
13971
14244
|
)
|
|
13972
14245
|
);
|
|
13973
|
-
console.log(
|
|
14246
|
+
console.log(chalk22.dim(" Learnings written to CALIBER_LEARNINGS.md."));
|
|
13974
14247
|
}
|
|
13975
14248
|
}
|
|
13976
14249
|
async function learnRemoveCommand() {
|
|
13977
14250
|
let anyRemoved = false;
|
|
13978
14251
|
const r1 = removeLearningHooks();
|
|
13979
14252
|
if (r1.removed) {
|
|
13980
|
-
console.log(
|
|
14253
|
+
console.log(chalk22.green("\u2713") + " Claude Code learning hooks removed");
|
|
13981
14254
|
anyRemoved = true;
|
|
13982
14255
|
}
|
|
13983
14256
|
const r2 = removeCursorLearningHooks();
|
|
13984
14257
|
if (r2.removed) {
|
|
13985
|
-
console.log(
|
|
14258
|
+
console.log(chalk22.green("\u2713") + " Cursor learning hooks removed");
|
|
13986
14259
|
anyRemoved = true;
|
|
13987
14260
|
}
|
|
13988
14261
|
if (!anyRemoved) {
|
|
13989
|
-
console.log(
|
|
14262
|
+
console.log(chalk22.dim("No learning hooks found."));
|
|
13990
14263
|
}
|
|
13991
14264
|
}
|
|
13992
14265
|
async function learnStatusCommand() {
|
|
@@ -13994,51 +14267,51 @@ async function learnStatusCommand() {
|
|
|
13994
14267
|
const cursorInstalled = areCursorLearningHooksInstalled();
|
|
13995
14268
|
const state = readState2();
|
|
13996
14269
|
const eventCount = getEventCount();
|
|
13997
|
-
console.log(
|
|
14270
|
+
console.log(chalk22.bold("Session Learning Status"));
|
|
13998
14271
|
console.log();
|
|
13999
14272
|
if (claudeInstalled) {
|
|
14000
|
-
console.log(
|
|
14273
|
+
console.log(chalk22.green("\u2713") + " Claude Code hooks " + chalk22.green("installed"));
|
|
14001
14274
|
} else {
|
|
14002
|
-
console.log(
|
|
14275
|
+
console.log(chalk22.dim("\u2717") + " Claude Code hooks " + chalk22.dim("not installed"));
|
|
14003
14276
|
}
|
|
14004
14277
|
if (cursorInstalled) {
|
|
14005
|
-
console.log(
|
|
14278
|
+
console.log(chalk22.green("\u2713") + " Cursor hooks " + chalk22.green("installed"));
|
|
14006
14279
|
} else {
|
|
14007
|
-
console.log(
|
|
14280
|
+
console.log(chalk22.dim("\u2717") + " Cursor hooks " + chalk22.dim("not installed"));
|
|
14008
14281
|
}
|
|
14009
14282
|
if (!claudeInstalled && !cursorInstalled) {
|
|
14010
14283
|
console.log(
|
|
14011
|
-
|
|
14284
|
+
chalk22.dim(` Run \`${resolveCaliber()} learn install\` to enable session learning.`)
|
|
14012
14285
|
);
|
|
14013
14286
|
}
|
|
14014
14287
|
console.log();
|
|
14015
|
-
console.log(`Events recorded: ${
|
|
14016
|
-
console.log(`Threshold for analysis: ${
|
|
14288
|
+
console.log(`Events recorded: ${chalk22.cyan(String(eventCount))}`);
|
|
14289
|
+
console.log(`Threshold for analysis: ${chalk22.cyan(String(MIN_EVENTS_FOR_ANALYSIS))}`);
|
|
14017
14290
|
if (state.lastAnalysisTimestamp) {
|
|
14018
|
-
console.log(`Last analysis: ${
|
|
14291
|
+
console.log(`Last analysis: ${chalk22.cyan(state.lastAnalysisTimestamp)}`);
|
|
14019
14292
|
} else {
|
|
14020
|
-
console.log(`Last analysis: ${
|
|
14293
|
+
console.log(`Last analysis: ${chalk22.dim("none")}`);
|
|
14021
14294
|
}
|
|
14022
14295
|
const lastError = readFinalizeError();
|
|
14023
14296
|
if (lastError) {
|
|
14024
|
-
console.log(`Last error: ${
|
|
14025
|
-
console.log(
|
|
14297
|
+
console.log(`Last error: ${chalk22.red(lastError.error)}`);
|
|
14298
|
+
console.log(chalk22.dim(` at ${lastError.timestamp}`));
|
|
14026
14299
|
const logPath = path38.join(getLearningDir(), LEARNING_FINALIZE_LOG);
|
|
14027
14300
|
if (fs47.existsSync(logPath)) {
|
|
14028
|
-
console.log(
|
|
14301
|
+
console.log(chalk22.dim(` Full log: ${logPath}`));
|
|
14029
14302
|
}
|
|
14030
14303
|
}
|
|
14031
14304
|
const learnedSection = readLearnedSection();
|
|
14032
14305
|
if (learnedSection) {
|
|
14033
14306
|
const lineCount = learnedSection.split("\n").filter(Boolean).length;
|
|
14034
14307
|
console.log(`
|
|
14035
|
-
Learned items in CALIBER_LEARNINGS.md: ${
|
|
14308
|
+
Learned items in CALIBER_LEARNINGS.md: ${chalk22.cyan(String(lineCount))}`);
|
|
14036
14309
|
}
|
|
14037
14310
|
const roiStats = readROIStats();
|
|
14038
14311
|
const roiSummary = formatROISummary(roiStats);
|
|
14039
14312
|
if (roiSummary) {
|
|
14040
14313
|
console.log();
|
|
14041
|
-
console.log(
|
|
14314
|
+
console.log(chalk22.bold(roiSummary.split("\n")[0]));
|
|
14042
14315
|
for (const line of roiSummary.split("\n").slice(1)) {
|
|
14043
14316
|
console.log(line);
|
|
14044
14317
|
}
|
|
@@ -14064,26 +14337,26 @@ function getAllLearnings() {
|
|
|
14064
14337
|
async function learnListCommand(options) {
|
|
14065
14338
|
const items = getAllLearnings();
|
|
14066
14339
|
if (items.length === 0) {
|
|
14067
|
-
console.log(
|
|
14340
|
+
console.log(chalk22.dim(`No learnings yet. Run \`${resolveCaliber()} learn install\` to start.`));
|
|
14068
14341
|
return;
|
|
14069
14342
|
}
|
|
14070
14343
|
const roiStats = options?.verbose ? readROIStats() : null;
|
|
14071
|
-
console.log(
|
|
14344
|
+
console.log(chalk22.bold(`
|
|
14072
14345
|
Learnings (${items.length})
|
|
14073
14346
|
`));
|
|
14074
14347
|
for (const item of items) {
|
|
14075
|
-
const tag = item.source === "personal" ?
|
|
14348
|
+
const tag = item.source === "personal" ? chalk22.magenta("[personal]") : chalk22.blue("[project]");
|
|
14076
14349
|
const display = item.text.replace(/^- /, "").slice(0, 100);
|
|
14077
|
-
console.log(` ${
|
|
14350
|
+
console.log(` ${chalk22.dim(String(item.index + 1).padStart(2, " "))}. ${tag} ${display}`);
|
|
14078
14351
|
if (options?.verbose && roiStats) {
|
|
14079
14352
|
const match = roiStats.learnings.find((l) => display.includes(l.summary.slice(0, 40)));
|
|
14080
14353
|
if (match) {
|
|
14081
14354
|
const activations = match.activationCount ?? 0;
|
|
14082
14355
|
const stale = activations === 0 && roiStats.sessions.length >= 10;
|
|
14083
|
-
const activationLabel = stale ?
|
|
14356
|
+
const activationLabel = stale ? chalk22.yellow(`${activations} activations [stale]`) : chalk22.dim(`${activations} activation${activations === 1 ? "" : "s"}`);
|
|
14084
14357
|
console.log(` ${activationLabel}`);
|
|
14085
14358
|
if (match.explanation) {
|
|
14086
|
-
console.log(` ${
|
|
14359
|
+
console.log(` ${chalk22.dim("Why: " + match.explanation.slice(0, 80))}`);
|
|
14087
14360
|
}
|
|
14088
14361
|
}
|
|
14089
14362
|
}
|
|
@@ -14094,7 +14367,7 @@ async function learnDeleteCommand(indexStr) {
|
|
|
14094
14367
|
const index = parseInt(indexStr, 10);
|
|
14095
14368
|
if (isNaN(index) || index < 1) {
|
|
14096
14369
|
console.log(
|
|
14097
|
-
|
|
14370
|
+
chalk22.red(
|
|
14098
14371
|
`Invalid index: "${indexStr}". Use a number from \`${resolveCaliber()} learn list\`.`
|
|
14099
14372
|
)
|
|
14100
14373
|
);
|
|
@@ -14103,13 +14376,13 @@ async function learnDeleteCommand(indexStr) {
|
|
|
14103
14376
|
const items = getAllLearnings();
|
|
14104
14377
|
const targetIdx = index - 1;
|
|
14105
14378
|
if (targetIdx >= items.length) {
|
|
14106
|
-
console.log(
|
|
14379
|
+
console.log(chalk22.red(`Index ${index} is out of range. You have ${items.length} learnings.`));
|
|
14107
14380
|
return;
|
|
14108
14381
|
}
|
|
14109
14382
|
const item = items[targetIdx];
|
|
14110
14383
|
const filePath = item.source === "personal" ? PERSONAL_LEARNINGS_FILE : "CALIBER_LEARNINGS.md";
|
|
14111
14384
|
if (!fs47.existsSync(filePath)) {
|
|
14112
|
-
console.log(
|
|
14385
|
+
console.log(chalk22.red("Learnings file not found."));
|
|
14113
14386
|
return;
|
|
14114
14387
|
}
|
|
14115
14388
|
const content = fs47.readFileSync(filePath, "utf-8");
|
|
@@ -14128,7 +14401,7 @@ async function learnDeleteCommand(indexStr) {
|
|
|
14128
14401
|
}
|
|
14129
14402
|
}
|
|
14130
14403
|
if (lineToRemove === -1) {
|
|
14131
|
-
console.log(
|
|
14404
|
+
console.log(chalk22.red("Could not locate learning in file."));
|
|
14132
14405
|
return;
|
|
14133
14406
|
}
|
|
14134
14407
|
const bulletToRemove = lines[lineToRemove];
|
|
@@ -14144,24 +14417,24 @@ async function learnDeleteCommand(indexStr) {
|
|
|
14144
14417
|
roiStats.learnings.splice(roiIdx, 1);
|
|
14145
14418
|
writeROIStats(roiStats);
|
|
14146
14419
|
}
|
|
14147
|
-
console.log(
|
|
14420
|
+
console.log(chalk22.green("\u2713") + ` Removed: ${bulletToRemove.replace(/^- /, "").slice(0, 80)}`);
|
|
14148
14421
|
}
|
|
14149
14422
|
async function learnAddCommand(content, options) {
|
|
14150
14423
|
if (!content.trim()) {
|
|
14151
|
-
console.log(
|
|
14424
|
+
console.log(chalk22.yellow("Please provide learning content."));
|
|
14152
14425
|
throw new Error("__exit__");
|
|
14153
14426
|
}
|
|
14154
14427
|
const scope = options.personal ? "personal" : "project";
|
|
14155
14428
|
const result = addLearning(content.trim(), scope);
|
|
14156
14429
|
if (result.added) {
|
|
14157
|
-
console.log(
|
|
14430
|
+
console.log(chalk22.green("\u2713") + ` Learning saved to ${result.file}`);
|
|
14158
14431
|
} else {
|
|
14159
|
-
console.log(
|
|
14432
|
+
console.log(chalk22.dim(" Similar learning already exists \u2014 skipped."));
|
|
14160
14433
|
}
|
|
14161
14434
|
}
|
|
14162
14435
|
|
|
14163
14436
|
// src/commands/insights.ts
|
|
14164
|
-
import
|
|
14437
|
+
import chalk23 from "chalk";
|
|
14165
14438
|
init_resolve_caliber();
|
|
14166
14439
|
var MIN_SESSIONS_FULL = 20;
|
|
14167
14440
|
function buildInsightsData(stats) {
|
|
@@ -14202,85 +14475,85 @@ function buildInsightsData(stats) {
|
|
|
14202
14475
|
};
|
|
14203
14476
|
}
|
|
14204
14477
|
function displayColdStart(score) {
|
|
14205
|
-
console.log(
|
|
14478
|
+
console.log(chalk23.bold("\n Agent Insights\n"));
|
|
14206
14479
|
const hooksInstalled = areLearningHooksInstalled() || areCursorLearningHooksInstalled();
|
|
14207
14480
|
if (!hooksInstalled) {
|
|
14208
|
-
console.log(
|
|
14209
|
-
console.log(
|
|
14210
|
-
console.log(
|
|
14211
|
-
console.log(
|
|
14481
|
+
console.log(chalk23.yellow(" Learning hooks not installed."));
|
|
14482
|
+
console.log(chalk23.dim(" Session learning captures patterns from your AI coding sessions \u2014 what"));
|
|
14483
|
+
console.log(chalk23.dim(" fails, what works, corrections you make \u2014 so your agents improve over time.\n"));
|
|
14484
|
+
console.log(chalk23.dim(" Run ") + chalk23.cyan(`${resolveCaliber()} learn install`) + chalk23.dim(" to enable."));
|
|
14212
14485
|
} else {
|
|
14213
|
-
console.log(
|
|
14214
|
-
console.log(
|
|
14215
|
-
console.log(
|
|
14486
|
+
console.log(chalk23.dim(" Learning hooks are active. Use your AI agent and insights"));
|
|
14487
|
+
console.log(chalk23.dim(" will appear automatically after each session.\n"));
|
|
14488
|
+
console.log(chalk23.dim(` Progress: 0/${MIN_SESSIONS_FULL} sessions \u2014 full insights unlock at ${MIN_SESSIONS_FULL}`));
|
|
14216
14489
|
}
|
|
14217
|
-
console.log(
|
|
14490
|
+
console.log(chalk23.dim(`
|
|
14218
14491
|
Config score: ${score.score}/100 (${score.grade})`));
|
|
14219
14492
|
console.log("");
|
|
14220
14493
|
}
|
|
14221
14494
|
function displayEarlyData(data, score) {
|
|
14222
|
-
console.log(
|
|
14495
|
+
console.log(chalk23.bold("\n Agent Insights") + chalk23.yellow(" (early data)\n"));
|
|
14223
14496
|
const remaining = MIN_SESSIONS_FULL - data.totalSessions;
|
|
14224
|
-
console.log(
|
|
14497
|
+
console.log(chalk23.dim(` ${data.totalSessions}/${MIN_SESSIONS_FULL} sessions tracked \u2014 ${remaining} more for full insights.
|
|
14225
14498
|
`));
|
|
14226
|
-
console.log(` Sessions tracked: ${
|
|
14227
|
-
console.log(` Learnings accumulated: ${
|
|
14499
|
+
console.log(` Sessions tracked: ${chalk23.cyan(String(data.totalSessions))}`);
|
|
14500
|
+
console.log(` Learnings accumulated: ${chalk23.cyan(String(data.learningCount))}`);
|
|
14228
14501
|
if (data.totalWasteTokens > 0) {
|
|
14229
|
-
console.log(` Waste captured: ${
|
|
14502
|
+
console.log(` Waste captured: ${chalk23.cyan(data.totalWasteTokens.toLocaleString())} tokens`);
|
|
14230
14503
|
}
|
|
14231
14504
|
if (data.failureRateImprovement !== null && data.failureRateImprovement > 0) {
|
|
14232
|
-
console.log(` Failure rate trend: ${
|
|
14505
|
+
console.log(` Failure rate trend: ${chalk23.green(`${data.failureRateImprovement}% fewer`)} failures with learnings ${chalk23.dim("(early signal)")}`);
|
|
14233
14506
|
} else if (data.totalSessions > 0 && data.failureRateImprovement === null) {
|
|
14234
|
-
console.log(` Failure rate trend: ${
|
|
14507
|
+
console.log(` Failure rate trend: ${chalk23.dim("collecting data (need 3+ sessions in each group)")}`);
|
|
14235
14508
|
}
|
|
14236
14509
|
if (data.taskSuccessRate !== null) {
|
|
14237
|
-
console.log(` Task success rate: ${
|
|
14510
|
+
console.log(` Task success rate: ${chalk23.cyan(`${data.taskSuccessRate}%`)} ${chalk23.dim(`(${data.taskCount} tasks)`)}`);
|
|
14238
14511
|
}
|
|
14239
|
-
console.log(` Config score: ${
|
|
14512
|
+
console.log(` Config score: ${chalk23.cyan(`${score.score}/100`)} (${score.grade})`);
|
|
14240
14513
|
console.log("");
|
|
14241
14514
|
}
|
|
14242
14515
|
function displayFullInsights(data, score) {
|
|
14243
|
-
console.log(
|
|
14244
|
-
console.log(
|
|
14516
|
+
console.log(chalk23.bold("\n Agent Insights\n"));
|
|
14517
|
+
console.log(chalk23.bold(" Agent Health"));
|
|
14245
14518
|
if (data.taskSuccessRate !== null) {
|
|
14246
|
-
const color = data.taskSuccessRate >= 80 ?
|
|
14519
|
+
const color = data.taskSuccessRate >= 80 ? chalk23.green : data.taskSuccessRate >= 60 ? chalk23.yellow : chalk23.red;
|
|
14247
14520
|
console.log(` Task success rate: ${color(`${data.taskSuccessRate}%`)} across ${data.taskCount} tasks`);
|
|
14248
14521
|
if (data.taskCorrectionCount > 0) {
|
|
14249
|
-
console.log(` Corrections needed: ${
|
|
14522
|
+
console.log(` Corrections needed: ${chalk23.yellow(String(data.taskCorrectionCount))} tasks required user correction`);
|
|
14250
14523
|
}
|
|
14251
14524
|
}
|
|
14252
|
-
console.log(` Sessions tracked: ${
|
|
14253
|
-
console.log(
|
|
14254
|
-
console.log(` Learnings active: ${
|
|
14525
|
+
console.log(` Sessions tracked: ${chalk23.cyan(String(data.totalSessions))}`);
|
|
14526
|
+
console.log(chalk23.bold("\n Learning Impact"));
|
|
14527
|
+
console.log(` Learnings active: ${chalk23.cyan(String(data.learningCount))}`);
|
|
14255
14528
|
if (data.failureRateWith !== null && data.failureRateWithout !== null) {
|
|
14256
|
-
console.log(` Failure rate: ${
|
|
14529
|
+
console.log(` Failure rate: ${chalk23.red(data.failureRateWithout.toFixed(1))}/session ${chalk23.dim("\u2192")} ${chalk23.green(data.failureRateWith.toFixed(1))}/session with learnings`);
|
|
14257
14530
|
if (data.failureRateImprovement !== null && data.failureRateImprovement > 0) {
|
|
14258
|
-
console.log(` Improvement: ${
|
|
14531
|
+
console.log(` Improvement: ${chalk23.green(`${data.failureRateImprovement}%`)} fewer failures`);
|
|
14259
14532
|
} else if (data.failureRateImprovement === null) {
|
|
14260
|
-
console.log(` Improvement: ${
|
|
14533
|
+
console.log(` Improvement: ${chalk23.dim("collecting data (need 3+ sessions in each group)")}`);
|
|
14261
14534
|
}
|
|
14262
14535
|
}
|
|
14263
14536
|
if (data.totalWasteTokens > 0 || data.estimatedSavingsTokens > 0) {
|
|
14264
|
-
console.log(
|
|
14537
|
+
console.log(chalk23.bold("\n Efficiency"));
|
|
14265
14538
|
if (data.totalWasteTokens > 0) {
|
|
14266
|
-
console.log(` Waste captured: ${
|
|
14539
|
+
console.log(` Waste captured: ${chalk23.cyan(data.totalWasteTokens.toLocaleString())} tokens`);
|
|
14267
14540
|
}
|
|
14268
14541
|
if (data.estimatedSavingsTokens > 0) {
|
|
14269
|
-
console.log(` Estimated savings: ~${
|
|
14542
|
+
console.log(` Estimated savings: ~${chalk23.green(data.estimatedSavingsTokens.toLocaleString())} tokens`);
|
|
14270
14543
|
}
|
|
14271
14544
|
if (data.estimatedSavingsSeconds > 0) {
|
|
14272
|
-
console.log(` Time saved: ~${
|
|
14545
|
+
console.log(` Time saved: ~${chalk23.green(formatDuration(data.estimatedSavingsSeconds))}`);
|
|
14273
14546
|
}
|
|
14274
14547
|
}
|
|
14275
|
-
console.log(
|
|
14276
|
-
console.log(` Score: ${
|
|
14548
|
+
console.log(chalk23.bold("\n Config Quality"));
|
|
14549
|
+
console.log(` Score: ${chalk23.cyan(`${score.score}/100`)} (${score.grade})`);
|
|
14277
14550
|
const history = readScoreHistory();
|
|
14278
14551
|
const trend = getScoreTrend(history);
|
|
14279
14552
|
if (trend) {
|
|
14280
|
-
const trendColor = trend.direction === "up" ?
|
|
14553
|
+
const trendColor = trend.direction === "up" ? chalk23.green : trend.direction === "down" ? chalk23.red : chalk23.gray;
|
|
14281
14554
|
const arrow = trend.direction === "up" ? "\u2191" : trend.direction === "down" ? "\u2193" : "\u2192";
|
|
14282
14555
|
const sign = trend.delta > 0 ? "+" : "";
|
|
14283
|
-
console.log(` Trend: ${trendColor(`${arrow} ${sign}${trend.delta} pts`)} ${
|
|
14556
|
+
console.log(` Trend: ${trendColor(`${arrow} ${sign}${trend.delta} pts`)} ${chalk23.dim(`over ${trend.entries} checks`)}`);
|
|
14284
14557
|
}
|
|
14285
14558
|
console.log("");
|
|
14286
14559
|
}
|
|
@@ -14310,36 +14583,36 @@ async function insightsCommand(options) {
|
|
|
14310
14583
|
// src/commands/sources.ts
|
|
14311
14584
|
import fs48 from "fs";
|
|
14312
14585
|
import path39 from "path";
|
|
14313
|
-
import
|
|
14586
|
+
import chalk24 from "chalk";
|
|
14314
14587
|
init_resolve_caliber();
|
|
14315
14588
|
async function sourcesListCommand() {
|
|
14316
14589
|
const dir = process.cwd();
|
|
14317
14590
|
const configSources = loadSourcesConfig(dir);
|
|
14318
14591
|
const workspaces = getDetectedWorkspaces(dir);
|
|
14319
14592
|
if (configSources.length === 0 && workspaces.length === 0) {
|
|
14320
|
-
console.log(
|
|
14321
|
-
console.log(
|
|
14322
|
-
console.log(
|
|
14593
|
+
console.log(chalk24.dim("\n No sources configured.\n"));
|
|
14594
|
+
console.log(chalk24.dim(" Add a source: ") + chalk24.hex("#83D1EB")(`${resolveCaliber()} sources add <path>`));
|
|
14595
|
+
console.log(chalk24.dim(" Or add to .caliber/sources.json manually.\n"));
|
|
14323
14596
|
return;
|
|
14324
14597
|
}
|
|
14325
|
-
console.log(
|
|
14598
|
+
console.log(chalk24.bold("\n External Sources\n"));
|
|
14326
14599
|
if (configSources.length > 0) {
|
|
14327
14600
|
for (const source of configSources) {
|
|
14328
14601
|
const sourcePath = source.path || source.url || "";
|
|
14329
14602
|
const exists = source.path ? fs48.existsSync(path39.resolve(dir, source.path)) : false;
|
|
14330
|
-
const status = exists ?
|
|
14603
|
+
const status = exists ? chalk24.green("reachable") : chalk24.red("not found");
|
|
14331
14604
|
const hasSummary = source.path && fs48.existsSync(path39.join(path39.resolve(dir, source.path), ".caliber", "summary.json"));
|
|
14332
|
-
console.log(` ${
|
|
14333
|
-
console.log(` Type: ${source.type} Status: ${status}${hasSummary ? " " +
|
|
14334
|
-
if (source.description) console.log(` ${
|
|
14605
|
+
console.log(` ${chalk24.bold(source.role || source.type)} ${chalk24.dim(sourcePath)}`);
|
|
14606
|
+
console.log(` Type: ${source.type} Status: ${status}${hasSummary ? " " + chalk24.cyan("has summary.json") : ""}`);
|
|
14607
|
+
if (source.description) console.log(` ${chalk24.dim(source.description)}`);
|
|
14335
14608
|
console.log("");
|
|
14336
14609
|
}
|
|
14337
14610
|
}
|
|
14338
14611
|
if (workspaces.length > 0) {
|
|
14339
|
-
console.log(
|
|
14612
|
+
console.log(chalk24.dim(" Auto-detected workspaces:"));
|
|
14340
14613
|
for (const ws of workspaces) {
|
|
14341
14614
|
const exists = fs48.existsSync(path39.resolve(dir, ws));
|
|
14342
|
-
console.log(` ${exists ?
|
|
14615
|
+
console.log(` ${exists ? chalk24.green("\u25CF") : chalk24.red("\u25CF")} ${ws}`);
|
|
14343
14616
|
}
|
|
14344
14617
|
console.log("");
|
|
14345
14618
|
}
|
|
@@ -14348,14 +14621,14 @@ async function sourcesAddCommand(sourcePath) {
|
|
|
14348
14621
|
const dir = process.cwd();
|
|
14349
14622
|
const absPath = path39.resolve(dir, sourcePath);
|
|
14350
14623
|
if (!fs48.existsSync(absPath)) {
|
|
14351
|
-
console.log(
|
|
14624
|
+
console.log(chalk24.red(`
|
|
14352
14625
|
Path not found: ${sourcePath}
|
|
14353
14626
|
`));
|
|
14354
14627
|
throw new Error("__exit__");
|
|
14355
14628
|
}
|
|
14356
14629
|
const type = detectSourceType(absPath);
|
|
14357
14630
|
if (isInsideDir(absPath, dir)) {
|
|
14358
|
-
console.log(
|
|
14631
|
+
console.log(chalk24.red(`
|
|
14359
14632
|
Cannot add a path inside the current project as a source.
|
|
14360
14633
|
`));
|
|
14361
14634
|
throw new Error("__exit__");
|
|
@@ -14365,7 +14638,7 @@ async function sourcesAddCommand(sourcePath) {
|
|
|
14365
14638
|
(s) => s.path && path39.resolve(dir, s.path) === absPath
|
|
14366
14639
|
);
|
|
14367
14640
|
if (alreadyConfigured) {
|
|
14368
|
-
console.log(
|
|
14641
|
+
console.log(chalk24.yellow(`
|
|
14369
14642
|
Already configured: ${sourcePath}
|
|
14370
14643
|
`));
|
|
14371
14644
|
return;
|
|
@@ -14382,7 +14655,7 @@ async function sourcesAddCommand(sourcePath) {
|
|
|
14382
14655
|
};
|
|
14383
14656
|
existing.push(newSource);
|
|
14384
14657
|
writeSourcesConfig(dir, existing);
|
|
14385
|
-
console.log(
|
|
14658
|
+
console.log(chalk24.green(`
|
|
14386
14659
|
\u2713 Added ${sourcePath} as ${type} source (${role})
|
|
14387
14660
|
`));
|
|
14388
14661
|
}
|
|
@@ -14393,18 +14666,18 @@ async function sourcesRemoveCommand(name) {
|
|
|
14393
14666
|
(s) => s.path?.includes(name) || s.role === name
|
|
14394
14667
|
);
|
|
14395
14668
|
if (idx === -1) {
|
|
14396
|
-
console.log(
|
|
14669
|
+
console.log(chalk24.red(`
|
|
14397
14670
|
Source not found: ${name}
|
|
14398
14671
|
`));
|
|
14399
|
-
console.log(
|
|
14672
|
+
console.log(chalk24.dim(" Available sources:"));
|
|
14400
14673
|
for (const s of existing) {
|
|
14401
|
-
console.log(
|
|
14674
|
+
console.log(chalk24.dim(` ${s.path || s.url} (${s.role || s.type})`));
|
|
14402
14675
|
}
|
|
14403
14676
|
throw new Error("__exit__");
|
|
14404
14677
|
}
|
|
14405
14678
|
const removed = existing.splice(idx, 1)[0];
|
|
14406
14679
|
writeSourcesConfig(dir, existing);
|
|
14407
|
-
console.log(
|
|
14680
|
+
console.log(chalk24.green(`
|
|
14408
14681
|
\u2713 Removed ${removed.path || removed.url} (${removed.role || removed.type})
|
|
14409
14682
|
`));
|
|
14410
14683
|
}
|
|
@@ -14412,7 +14685,7 @@ async function sourcesRemoveCommand(name) {
|
|
|
14412
14685
|
// src/commands/publish.ts
|
|
14413
14686
|
import fs49 from "fs";
|
|
14414
14687
|
import path40 from "path";
|
|
14415
|
-
import
|
|
14688
|
+
import chalk25 from "chalk";
|
|
14416
14689
|
import ora7 from "ora";
|
|
14417
14690
|
init_config();
|
|
14418
14691
|
init_resolve_caliber();
|
|
@@ -14420,7 +14693,7 @@ async function publishCommand() {
|
|
|
14420
14693
|
const dir = process.cwd();
|
|
14421
14694
|
const config = loadConfig();
|
|
14422
14695
|
if (!config) {
|
|
14423
|
-
console.log(
|
|
14696
|
+
console.log(chalk25.red("No LLM provider configured. Run ") + chalk25.hex("#83D1EB")(`${resolveCaliber()} config`) + chalk25.red(" first."));
|
|
14424
14697
|
throw new Error("__exit__");
|
|
14425
14698
|
}
|
|
14426
14699
|
const spinner = ora7("Generating project summary...").start();
|
|
@@ -14461,13 +14734,13 @@ async function publishCommand() {
|
|
|
14461
14734
|
const outputPath = path40.join(outputDir, "summary.json");
|
|
14462
14735
|
fs49.writeFileSync(outputPath, JSON.stringify(summary, null, 2) + "\n", "utf-8");
|
|
14463
14736
|
spinner.succeed("Project summary published");
|
|
14464
|
-
console.log(` ${
|
|
14465
|
-
console.log(
|
|
14466
|
-
console.log(
|
|
14737
|
+
console.log(` ${chalk25.green("\u2713")} ${path40.relative(dir, outputPath)}`);
|
|
14738
|
+
console.log(chalk25.dim("\n Other projects can now reference this repo as a source."));
|
|
14739
|
+
console.log(chalk25.dim(" When they run `caliber init`, they'll read this summary automatically.\n"));
|
|
14467
14740
|
} catch (err) {
|
|
14468
14741
|
spinner.fail("Failed to generate summary");
|
|
14469
14742
|
if (err instanceof Error && err.message === "__exit__") throw err;
|
|
14470
|
-
console.error(
|
|
14743
|
+
console.error(chalk25.red(err instanceof Error ? err.message : "Unknown error"));
|
|
14471
14744
|
throw new Error("__exit__");
|
|
14472
14745
|
}
|
|
14473
14746
|
}
|
|
@@ -14475,7 +14748,7 @@ async function publishCommand() {
|
|
|
14475
14748
|
// src/commands/bootstrap.ts
|
|
14476
14749
|
init_builtin_skills();
|
|
14477
14750
|
import fs50 from "fs";
|
|
14478
|
-
import
|
|
14751
|
+
import chalk26 from "chalk";
|
|
14479
14752
|
var PLATFORM_SKILL_DIRS = {
|
|
14480
14753
|
claude: ".claude/skills",
|
|
14481
14754
|
cursor: ".cursor/skills",
|
|
@@ -14501,21 +14774,21 @@ async function bootstrapCommand() {
|
|
|
14501
14774
|
}
|
|
14502
14775
|
}
|
|
14503
14776
|
if (written.length === 0) {
|
|
14504
|
-
console.log(
|
|
14777
|
+
console.log(chalk26.yellow("No skills were written."));
|
|
14505
14778
|
return;
|
|
14506
14779
|
}
|
|
14507
|
-
console.log(
|
|
14780
|
+
console.log(chalk26.bold.green("\n Caliber skills installed!\n"));
|
|
14508
14781
|
for (const file of written) {
|
|
14509
|
-
console.log(` ${
|
|
14782
|
+
console.log(` ${chalk26.green("\u2713")} ${file}`);
|
|
14510
14783
|
}
|
|
14511
|
-
console.log(
|
|
14512
|
-
console.log(
|
|
14784
|
+
console.log(chalk26.dim("\n Your agent can now run /setup-caliber to complete the setup."));
|
|
14785
|
+
console.log(chalk26.dim(' Just tell your agent: "Run /setup-caliber"\n'));
|
|
14513
14786
|
}
|
|
14514
14787
|
|
|
14515
14788
|
// src/commands/uninstall.ts
|
|
14516
14789
|
import fs51 from "fs";
|
|
14517
14790
|
import path41 from "path";
|
|
14518
|
-
import
|
|
14791
|
+
import chalk27 from "chalk";
|
|
14519
14792
|
import confirm3 from "@inquirer/confirm";
|
|
14520
14793
|
init_pre_commit_block();
|
|
14521
14794
|
init_builtin_skills();
|
|
@@ -14578,19 +14851,19 @@ function removeDirectory(dir) {
|
|
|
14578
14851
|
return true;
|
|
14579
14852
|
}
|
|
14580
14853
|
async function uninstallCommand(options) {
|
|
14581
|
-
console.log(
|
|
14582
|
-
console.log(
|
|
14583
|
-
console.log(
|
|
14584
|
-
console.log(
|
|
14585
|
-
console.log(
|
|
14586
|
-
console.log(
|
|
14587
|
-
console.log(
|
|
14588
|
-
console.log(
|
|
14589
|
-
console.log(
|
|
14854
|
+
console.log(chalk27.bold("\n Caliber Uninstall\n"));
|
|
14855
|
+
console.log(chalk27.dim(" This will remove all Caliber resources from this project:\n"));
|
|
14856
|
+
console.log(chalk27.dim(" \u2022 Pre-commit hook"));
|
|
14857
|
+
console.log(chalk27.dim(" \u2022 Session learning hooks"));
|
|
14858
|
+
console.log(chalk27.dim(" \u2022 Managed blocks in CLAUDE.md, AGENTS.md, copilot-instructions.md"));
|
|
14859
|
+
console.log(chalk27.dim(" \u2022 Cursor rules (caliber-*.mdc)"));
|
|
14860
|
+
console.log(chalk27.dim(" \u2022 Built-in skills (setup-caliber, find-skills, save-learning)"));
|
|
14861
|
+
console.log(chalk27.dim(" \u2022 CALIBER_LEARNINGS.md"));
|
|
14862
|
+
console.log(chalk27.dim(" \u2022 .caliber/ directory (backups, cache, state)\n"));
|
|
14590
14863
|
if (!options.force) {
|
|
14591
14864
|
const proceed = await confirm3({ message: "Continue with uninstall?" });
|
|
14592
14865
|
if (!proceed) {
|
|
14593
|
-
console.log(
|
|
14866
|
+
console.log(chalk27.dim("\n Cancelled.\n"));
|
|
14594
14867
|
return;
|
|
14595
14868
|
}
|
|
14596
14869
|
}
|
|
@@ -14598,65 +14871,65 @@ async function uninstallCommand(options) {
|
|
|
14598
14871
|
const actions = [];
|
|
14599
14872
|
const hookResult = removePreCommitHook();
|
|
14600
14873
|
if (hookResult.removed) {
|
|
14601
|
-
console.log(` ${
|
|
14874
|
+
console.log(` ${chalk27.red("\u2717")} Pre-commit hook removed`);
|
|
14602
14875
|
actions.push("pre-commit hook");
|
|
14603
14876
|
}
|
|
14604
14877
|
const stopHookResult = removeStopHook();
|
|
14605
14878
|
if (stopHookResult.removed) {
|
|
14606
|
-
console.log(` ${
|
|
14879
|
+
console.log(` ${chalk27.red("\u2717")} Onboarding hook removed`);
|
|
14607
14880
|
actions.push("onboarding hook");
|
|
14608
14881
|
}
|
|
14609
14882
|
const notificationHookResult = removeNotificationHook();
|
|
14610
14883
|
if (notificationHookResult.removed) {
|
|
14611
|
-
console.log(` ${
|
|
14884
|
+
console.log(` ${chalk27.red("\u2717")} Notification hook removed`);
|
|
14612
14885
|
actions.push("notification hook");
|
|
14613
14886
|
}
|
|
14614
14887
|
const sessionStartResult = removeSessionStartHook();
|
|
14615
14888
|
if (sessionStartResult.removed) {
|
|
14616
|
-
console.log(` ${
|
|
14889
|
+
console.log(` ${chalk27.red("\u2717")} SessionStart hook removed`);
|
|
14617
14890
|
actions.push("session-start hook");
|
|
14618
14891
|
}
|
|
14619
14892
|
const learnResult = removeLearningHooks();
|
|
14620
14893
|
if (learnResult.removed) {
|
|
14621
|
-
console.log(` ${
|
|
14894
|
+
console.log(` ${chalk27.red("\u2717")} Claude Code learning hooks removed`);
|
|
14622
14895
|
actions.push("claude learning hooks");
|
|
14623
14896
|
}
|
|
14624
14897
|
const cursorLearnResult = removeCursorLearningHooks();
|
|
14625
14898
|
if (cursorLearnResult.removed) {
|
|
14626
|
-
console.log(` ${
|
|
14899
|
+
console.log(` ${chalk27.red("\u2717")} Cursor learning hooks removed`);
|
|
14627
14900
|
actions.push("cursor learning hooks");
|
|
14628
14901
|
}
|
|
14629
14902
|
const strippedFiles = stripManagedBlocksFromFiles();
|
|
14630
14903
|
for (const file of strippedFiles) {
|
|
14631
|
-
console.log(` ${
|
|
14904
|
+
console.log(` ${chalk27.yellow("~")} ${file} \u2014 managed blocks removed`);
|
|
14632
14905
|
actions.push(file);
|
|
14633
14906
|
}
|
|
14634
14907
|
const removedCursorRules = removeCaliberManagedFiles(CURSOR_RULES_DIR, ".mdc");
|
|
14635
14908
|
for (const rule of removedCursorRules) {
|
|
14636
|
-
console.log(` ${
|
|
14909
|
+
console.log(` ${chalk27.red("\u2717")} ${rule}`);
|
|
14637
14910
|
}
|
|
14638
14911
|
if (removedCursorRules.length > 0) actions.push("cursor rules");
|
|
14639
14912
|
const removedClaudeRules = removeCaliberManagedFiles(CLAUDE_RULES_DIR, ".md");
|
|
14640
14913
|
for (const rule of removedClaudeRules) {
|
|
14641
|
-
console.log(` ${
|
|
14914
|
+
console.log(` ${chalk27.red("\u2717")} ${rule}`);
|
|
14642
14915
|
}
|
|
14643
14916
|
if (removedClaudeRules.length > 0) actions.push("claude rules");
|
|
14644
14917
|
const removedSkills = removeBuiltinSkills();
|
|
14645
14918
|
for (const skill of removedSkills) {
|
|
14646
|
-
console.log(` ${
|
|
14919
|
+
console.log(` ${chalk27.red("\u2717")} ${skill}/`);
|
|
14647
14920
|
}
|
|
14648
14921
|
if (removedSkills.length > 0) actions.push("builtin skills");
|
|
14649
14922
|
if (fs51.existsSync("CALIBER_LEARNINGS.md")) {
|
|
14650
14923
|
fs51.unlinkSync("CALIBER_LEARNINGS.md");
|
|
14651
|
-
console.log(` ${
|
|
14924
|
+
console.log(` ${chalk27.red("\u2717")} CALIBER_LEARNINGS.md`);
|
|
14652
14925
|
actions.push("learnings file");
|
|
14653
14926
|
}
|
|
14654
14927
|
if (removeDirectory(CALIBER_DIR)) {
|
|
14655
|
-
console.log(` ${
|
|
14928
|
+
console.log(` ${chalk27.red("\u2717")} .caliber/ directory`);
|
|
14656
14929
|
actions.push(".caliber directory");
|
|
14657
14930
|
}
|
|
14658
14931
|
if (actions.length === 0) {
|
|
14659
|
-
console.log(
|
|
14932
|
+
console.log(chalk27.dim(" Nothing to remove \u2014 Caliber is not installed in this project.\n"));
|
|
14660
14933
|
return;
|
|
14661
14934
|
}
|
|
14662
14935
|
trackUninstallExecuted();
|
|
@@ -14668,7 +14941,7 @@ async function uninstallCommand(options) {
|
|
|
14668
14941
|
});
|
|
14669
14942
|
if (removeConfig) {
|
|
14670
14943
|
fs51.unlinkSync(configPath);
|
|
14671
|
-
console.log(` ${
|
|
14944
|
+
console.log(` ${chalk27.red("\u2717")} ${configPath}`);
|
|
14672
14945
|
const configDir = path41.dirname(configPath);
|
|
14673
14946
|
try {
|
|
14674
14947
|
const remaining = fs51.readdirSync(configDir);
|
|
@@ -14677,9 +14950,9 @@ async function uninstallCommand(options) {
|
|
|
14677
14950
|
}
|
|
14678
14951
|
}
|
|
14679
14952
|
}
|
|
14680
|
-
console.log(
|
|
14953
|
+
console.log(chalk27.bold.green(`
|
|
14681
14954
|
Caliber has been removed from this project.`));
|
|
14682
|
-
console.log(
|
|
14955
|
+
console.log(chalk27.dim(" Your code is untouched \u2014 only Caliber config files were removed.\n"));
|
|
14683
14956
|
}
|
|
14684
14957
|
|
|
14685
14958
|
// src/cli.ts
|
|
@@ -14798,8 +15071,8 @@ learn.command("add <content>").description("Add a learning directly (used by age
|
|
|
14798
15071
|
import fs53 from "fs";
|
|
14799
15072
|
import path43 from "path";
|
|
14800
15073
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
14801
|
-
import { execSync as
|
|
14802
|
-
import
|
|
15074
|
+
import { execSync as execSync18, execFileSync as execFileSync5 } from "child_process";
|
|
15075
|
+
import chalk28 from "chalk";
|
|
14803
15076
|
import ora8 from "ora";
|
|
14804
15077
|
import confirm4 from "@inquirer/confirm";
|
|
14805
15078
|
var __dirname_vc = path43.dirname(fileURLToPath2(import.meta.url));
|
|
@@ -14826,7 +15099,7 @@ function isNewer(registry, current) {
|
|
|
14826
15099
|
}
|
|
14827
15100
|
function getInstalledVersion() {
|
|
14828
15101
|
try {
|
|
14829
|
-
const globalRoot =
|
|
15102
|
+
const globalRoot = execSync18("npm root -g", {
|
|
14830
15103
|
encoding: "utf-8",
|
|
14831
15104
|
stdio: ["pipe", "pipe", "pipe"]
|
|
14832
15105
|
}).trim();
|
|
@@ -14856,16 +15129,16 @@ async function checkForUpdates() {
|
|
|
14856
15129
|
if (!isInteractive) {
|
|
14857
15130
|
const installTag = channel === "latest" ? "" : `@${channel}`;
|
|
14858
15131
|
console.log(
|
|
14859
|
-
|
|
15132
|
+
chalk28.yellow(
|
|
14860
15133
|
`
|
|
14861
15134
|
Update available: ${current} -> ${latest}
|
|
14862
|
-
Run ${
|
|
15135
|
+
Run ${chalk28.bold(`npm install -g @rely-ai/caliber${installTag}`)} to upgrade.
|
|
14863
15136
|
`
|
|
14864
15137
|
)
|
|
14865
15138
|
);
|
|
14866
15139
|
return;
|
|
14867
15140
|
}
|
|
14868
|
-
console.log(
|
|
15141
|
+
console.log(chalk28.yellow(`
|
|
14869
15142
|
Update available: ${current} -> ${latest}`));
|
|
14870
15143
|
const shouldUpdate = await confirm4({
|
|
14871
15144
|
message: "Would you like to update now? (Y/n)",
|
|
@@ -14888,14 +15161,14 @@ Update available: ${current} -> ${latest}`));
|
|
|
14888
15161
|
if (installed !== latest) {
|
|
14889
15162
|
spinner.fail(`Update incomplete \u2014 got ${installed ?? "unknown"}, expected ${latest}`);
|
|
14890
15163
|
console.log(
|
|
14891
|
-
|
|
15164
|
+
chalk28.yellow(`Run ${chalk28.bold(`npm install -g @rely-ai/caliber@${tag}`)} manually.
|
|
14892
15165
|
`)
|
|
14893
15166
|
);
|
|
14894
15167
|
return;
|
|
14895
15168
|
}
|
|
14896
|
-
spinner.succeed(
|
|
15169
|
+
spinner.succeed(chalk28.green(`Updated to ${latest}`));
|
|
14897
15170
|
const args = process.argv.slice(2);
|
|
14898
|
-
console.log(
|
|
15171
|
+
console.log(chalk28.dim(`
|
|
14899
15172
|
Restarting: caliber ${args.join(" ")}
|
|
14900
15173
|
`));
|
|
14901
15174
|
execFileSync5("caliber", args, {
|
|
@@ -14908,11 +15181,11 @@ Restarting: caliber ${args.join(" ")}
|
|
|
14908
15181
|
if (err instanceof Error) {
|
|
14909
15182
|
const stderr = err.stderr;
|
|
14910
15183
|
const errMsg = stderr ? String(stderr).trim().split("\n").pop() : err.message.split("\n")[0];
|
|
14911
|
-
if (errMsg && !errMsg.includes("SIGTERM")) console.log(
|
|
15184
|
+
if (errMsg && !errMsg.includes("SIGTERM")) console.log(chalk28.dim(` ${errMsg}`));
|
|
14912
15185
|
}
|
|
14913
15186
|
console.log(
|
|
14914
|
-
|
|
14915
|
-
`Run ${
|
|
15187
|
+
chalk28.yellow(
|
|
15188
|
+
`Run ${chalk28.bold(`npm install -g @rely-ai/caliber@${tag}`)} manually to upgrade.
|
|
14916
15189
|
`
|
|
14917
15190
|
)
|
|
14918
15191
|
);
|