@rely-ai/caliber 1.37.1 → 1.38.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.js +393 -239
- package/package.json +1 -1
package/dist/bin.js
CHANGED
|
@@ -1099,14 +1099,14 @@ __export(lock_exports, {
|
|
|
1099
1099
|
isCaliberRunning: () => isCaliberRunning,
|
|
1100
1100
|
releaseLock: () => releaseLock
|
|
1101
1101
|
});
|
|
1102
|
-
import
|
|
1103
|
-
import
|
|
1102
|
+
import fs40 from "fs";
|
|
1103
|
+
import path33 from "path";
|
|
1104
1104
|
import os8 from "os";
|
|
1105
1105
|
import crypto5 from "crypto";
|
|
1106
1106
|
function buildLockPath() {
|
|
1107
1107
|
const cwd = process.cwd();
|
|
1108
1108
|
const hash = crypto5.createHash("md5").update(cwd).digest("hex").slice(0, 8);
|
|
1109
|
-
return
|
|
1109
|
+
return path33.join(os8.tmpdir(), `.caliber-${hash}.lock`);
|
|
1110
1110
|
}
|
|
1111
1111
|
function getLockFile() {
|
|
1112
1112
|
if (!_lockPath) _lockPath = buildLockPath();
|
|
@@ -1115,8 +1115,8 @@ function getLockFile() {
|
|
|
1115
1115
|
function isCaliberRunning() {
|
|
1116
1116
|
try {
|
|
1117
1117
|
const lockFile = buildLockPath();
|
|
1118
|
-
if (!
|
|
1119
|
-
const raw =
|
|
1118
|
+
if (!fs40.existsSync(lockFile)) return false;
|
|
1119
|
+
const raw = fs40.readFileSync(lockFile, "utf-8").trim();
|
|
1120
1120
|
const { pid, ts } = JSON.parse(raw);
|
|
1121
1121
|
if (Date.now() - ts > STALE_MS) return false;
|
|
1122
1122
|
try {
|
|
@@ -1131,14 +1131,14 @@ function isCaliberRunning() {
|
|
|
1131
1131
|
}
|
|
1132
1132
|
function acquireLock() {
|
|
1133
1133
|
try {
|
|
1134
|
-
|
|
1134
|
+
fs40.writeFileSync(getLockFile(), JSON.stringify({ pid: process.pid, ts: Date.now() }));
|
|
1135
1135
|
} catch {
|
|
1136
1136
|
}
|
|
1137
1137
|
}
|
|
1138
1138
|
function releaseLock() {
|
|
1139
1139
|
try {
|
|
1140
1140
|
const lockFile = getLockFile();
|
|
1141
|
-
if (
|
|
1141
|
+
if (fs40.existsSync(lockFile)) fs40.unlinkSync(lockFile);
|
|
1142
1142
|
} catch {
|
|
1143
1143
|
}
|
|
1144
1144
|
}
|
|
@@ -1153,8 +1153,8 @@ var init_lock = __esm({
|
|
|
1153
1153
|
|
|
1154
1154
|
// src/cli.ts
|
|
1155
1155
|
import { Command } from "commander";
|
|
1156
|
-
import
|
|
1157
|
-
import
|
|
1156
|
+
import fs51 from "fs";
|
|
1157
|
+
import path42 from "path";
|
|
1158
1158
|
import { fileURLToPath } from "url";
|
|
1159
1159
|
|
|
1160
1160
|
// src/commands/init.ts
|
|
@@ -3695,7 +3695,7 @@ function getDetectedWorkspaces(dir) {
|
|
|
3695
3695
|
|
|
3696
3696
|
// src/fingerprint/index.ts
|
|
3697
3697
|
async function collectFingerprint(dir) {
|
|
3698
|
-
const gitRemoteUrl = getGitRemoteUrl();
|
|
3698
|
+
const gitRemoteUrl = getGitRemoteUrl(dir);
|
|
3699
3699
|
const fileTree = getFileTree(dir);
|
|
3700
3700
|
const existingConfigs = readExistingConfigs(dir);
|
|
3701
3701
|
const packageName = readPackageName(dir);
|
|
@@ -4698,15 +4698,15 @@ init_config();
|
|
|
4698
4698
|
// src/utils/dependencies.ts
|
|
4699
4699
|
import { readFileSync as readFileSync2 } from "fs";
|
|
4700
4700
|
import { join as join2 } from "path";
|
|
4701
|
-
function readFileOrNull2(
|
|
4701
|
+
function readFileOrNull2(path44) {
|
|
4702
4702
|
try {
|
|
4703
|
-
return readFileSync2(
|
|
4703
|
+
return readFileSync2(path44, "utf-8");
|
|
4704
4704
|
} catch {
|
|
4705
4705
|
return null;
|
|
4706
4706
|
}
|
|
4707
4707
|
}
|
|
4708
|
-
function readJsonOrNull(
|
|
4709
|
-
const content = readFileOrNull2(
|
|
4708
|
+
function readJsonOrNull(path44) {
|
|
4709
|
+
const content = readFileOrNull2(path44);
|
|
4710
4710
|
if (!content) return null;
|
|
4711
4711
|
try {
|
|
4712
4712
|
return JSON.parse(content);
|
|
@@ -7626,8 +7626,8 @@ function trackInitSkillsSearch(searched, installedCount) {
|
|
|
7626
7626
|
function trackInitScoreRegression(oldScore, newScore) {
|
|
7627
7627
|
trackEvent("init_score_regression", { old_score: oldScore, new_score: newScore });
|
|
7628
7628
|
}
|
|
7629
|
-
function trackInitCompleted(
|
|
7630
|
-
trackEvent("init_completed", { path:
|
|
7629
|
+
function trackInitCompleted(path44, score) {
|
|
7630
|
+
trackEvent("init_completed", { path: path44, score });
|
|
7631
7631
|
}
|
|
7632
7632
|
function trackRegenerateCompleted(action, durationMs) {
|
|
7633
7633
|
trackEvent("regenerate_completed", { action, duration_ms: durationMs });
|
|
@@ -8640,11 +8640,11 @@ async function scoreAndRefine(setup, dir, sessionHistory, callbacks, options) {
|
|
|
8640
8640
|
const maxIterations = options?.thorough ? 3 : MAX_REFINE_ITERATIONS;
|
|
8641
8641
|
const minPoints = options?.thorough ? 1 : MIN_POINTS_TO_REFINE;
|
|
8642
8642
|
const existsCache = /* @__PURE__ */ new Map();
|
|
8643
|
-
const cachedExists = (
|
|
8644
|
-
const cached = existsCache.get(
|
|
8643
|
+
const cachedExists = (path44) => {
|
|
8644
|
+
const cached = existsCache.get(path44);
|
|
8645
8645
|
if (cached !== void 0) return cached;
|
|
8646
|
-
const result = existsSync9(
|
|
8647
|
-
existsCache.set(
|
|
8646
|
+
const result = existsSync9(path44);
|
|
8647
|
+
existsCache.set(path44, result);
|
|
8648
8648
|
return result;
|
|
8649
8649
|
};
|
|
8650
8650
|
const projectStructure = collectProjectStructure(dir);
|
|
@@ -11051,8 +11051,8 @@ async function scoreCommand(options) {
|
|
|
11051
11051
|
}
|
|
11052
11052
|
|
|
11053
11053
|
// src/commands/refresh.ts
|
|
11054
|
-
import
|
|
11055
|
-
import
|
|
11054
|
+
import fs41 from "fs";
|
|
11055
|
+
import path34 from "path";
|
|
11056
11056
|
import chalk19 from "chalk";
|
|
11057
11057
|
import ora6 from "ora";
|
|
11058
11058
|
|
|
@@ -11139,51 +11139,87 @@ function collectDiff(lastSha) {
|
|
|
11139
11139
|
const summary = parts.join(", ") || "no changes";
|
|
11140
11140
|
return { hasChanges, committedDiff, stagedDiff, unstagedDiff, changedFiles, summary };
|
|
11141
11141
|
}
|
|
11142
|
+
function scopeDiffToDir(diff, dir, allConfigDirs) {
|
|
11143
|
+
if (dir === ".") {
|
|
11144
|
+
const otherDirs = allConfigDirs.filter((d) => d !== ".");
|
|
11145
|
+
if (otherDirs.length === 0) return diff;
|
|
11146
|
+
const changedFiles2 = diff.changedFiles.filter(
|
|
11147
|
+
(f) => !otherDirs.some((d) => f.startsWith(`${d}/`))
|
|
11148
|
+
);
|
|
11149
|
+
const hasChanges2 = changedFiles2.length > 0;
|
|
11150
|
+
return {
|
|
11151
|
+
...diff,
|
|
11152
|
+
changedFiles: changedFiles2,
|
|
11153
|
+
hasChanges: hasChanges2,
|
|
11154
|
+
summary: hasChanges2 ? `${changedFiles2.length} files changed` : "no changes"
|
|
11155
|
+
};
|
|
11156
|
+
}
|
|
11157
|
+
const prefix = `${dir}/`;
|
|
11158
|
+
const changedFiles = diff.changedFiles.filter((f) => f.startsWith(prefix)).map((f) => f.slice(prefix.length));
|
|
11159
|
+
const hasChanges = changedFiles.length > 0;
|
|
11160
|
+
return {
|
|
11161
|
+
...diff,
|
|
11162
|
+
changedFiles,
|
|
11163
|
+
hasChanges,
|
|
11164
|
+
summary: hasChanges ? `${changedFiles.length} files changed` : "no changes"
|
|
11165
|
+
};
|
|
11166
|
+
}
|
|
11142
11167
|
|
|
11143
11168
|
// src/writers/refresh.ts
|
|
11144
11169
|
init_pre_commit_block();
|
|
11145
11170
|
import fs37 from "fs";
|
|
11146
11171
|
import path30 from "path";
|
|
11147
|
-
function writeRefreshDocs(docs) {
|
|
11172
|
+
function writeRefreshDocs(docs, dir = ".") {
|
|
11148
11173
|
const written = [];
|
|
11174
|
+
const p = (relPath) => (dir === "." ? relPath : path30.join(dir, relPath)).replace(/\\/g, "/");
|
|
11175
|
+
const ensureParent = (filePath) => {
|
|
11176
|
+
const parent = path30.dirname(filePath);
|
|
11177
|
+
if (parent !== "." && !fs37.existsSync(parent)) fs37.mkdirSync(parent, { recursive: true });
|
|
11178
|
+
};
|
|
11149
11179
|
if (docs.agentsMd) {
|
|
11150
|
-
|
|
11151
|
-
|
|
11180
|
+
const filePath = p("AGENTS.md");
|
|
11181
|
+
ensureParent(filePath);
|
|
11182
|
+
fs37.writeFileSync(filePath, appendManagedBlocks(docs.agentsMd, "codex"));
|
|
11183
|
+
written.push(filePath);
|
|
11152
11184
|
}
|
|
11153
11185
|
if (docs.claudeMd) {
|
|
11154
|
-
|
|
11155
|
-
|
|
11186
|
+
const filePath = p("CLAUDE.md");
|
|
11187
|
+
ensureParent(filePath);
|
|
11188
|
+
fs37.writeFileSync(filePath, appendManagedBlocks(docs.claudeMd));
|
|
11189
|
+
written.push(filePath);
|
|
11156
11190
|
}
|
|
11157
11191
|
if (docs.readmeMd) {
|
|
11158
|
-
|
|
11159
|
-
|
|
11192
|
+
const filePath = p("README.md");
|
|
11193
|
+
ensureParent(filePath);
|
|
11194
|
+
fs37.writeFileSync(filePath, docs.readmeMd);
|
|
11195
|
+
written.push(filePath);
|
|
11160
11196
|
}
|
|
11161
11197
|
if (docs.cursorrules) {
|
|
11162
|
-
|
|
11163
|
-
|
|
11198
|
+
const filePath = p(".cursorrules");
|
|
11199
|
+
ensureParent(filePath);
|
|
11200
|
+
fs37.writeFileSync(filePath, docs.cursorrules);
|
|
11201
|
+
written.push(filePath);
|
|
11164
11202
|
}
|
|
11165
11203
|
if (docs.cursorRules) {
|
|
11166
|
-
const rulesDir = path30.join(".cursor", "rules");
|
|
11204
|
+
const rulesDir = p(path30.join(".cursor", "rules"));
|
|
11167
11205
|
if (!fs37.existsSync(rulesDir)) fs37.mkdirSync(rulesDir, { recursive: true });
|
|
11168
11206
|
for (const rule of docs.cursorRules) {
|
|
11169
11207
|
fs37.writeFileSync(path30.join(rulesDir, rule.filename), rule.content);
|
|
11170
|
-
written.push(
|
|
11208
|
+
written.push(p(path30.join(".cursor", "rules", rule.filename)));
|
|
11171
11209
|
}
|
|
11172
11210
|
}
|
|
11173
11211
|
if (docs.copilotInstructions) {
|
|
11174
|
-
|
|
11175
|
-
|
|
11176
|
-
|
|
11177
|
-
|
|
11178
|
-
);
|
|
11179
|
-
written.push(".github/copilot-instructions.md");
|
|
11212
|
+
const filePath = p(path30.join(".github", "copilot-instructions.md"));
|
|
11213
|
+
ensureParent(filePath);
|
|
11214
|
+
fs37.writeFileSync(filePath, appendManagedBlocks(docs.copilotInstructions, "copilot"));
|
|
11215
|
+
written.push(filePath);
|
|
11180
11216
|
}
|
|
11181
11217
|
if (docs.copilotInstructionFiles) {
|
|
11182
|
-
const instructionsDir = path30.join(".github", "instructions");
|
|
11183
|
-
fs37.mkdirSync(instructionsDir, { recursive: true });
|
|
11218
|
+
const instructionsDir = p(path30.join(".github", "instructions"));
|
|
11219
|
+
if (!fs37.existsSync(instructionsDir)) fs37.mkdirSync(instructionsDir, { recursive: true });
|
|
11184
11220
|
for (const file of docs.copilotInstructionFiles) {
|
|
11185
11221
|
fs37.writeFileSync(path30.join(instructionsDir, file.filename), file.content);
|
|
11186
|
-
written.push(
|
|
11222
|
+
written.push(p(path30.join(".github", "instructions", file.filename)));
|
|
11187
11223
|
}
|
|
11188
11224
|
}
|
|
11189
11225
|
return written;
|
|
@@ -11192,8 +11228,15 @@ function writeRefreshDocs(docs) {
|
|
|
11192
11228
|
// src/ai/refresh.ts
|
|
11193
11229
|
init_config();
|
|
11194
11230
|
init_pre_commit_block();
|
|
11195
|
-
async function refreshDocs(diff, existingDocs, projectContext, learnedSection, sources2) {
|
|
11196
|
-
const prompt = buildRefreshPrompt(
|
|
11231
|
+
async function refreshDocs(diff, existingDocs, projectContext, learnedSection, sources2, scope) {
|
|
11232
|
+
const prompt = buildRefreshPrompt(
|
|
11233
|
+
diff,
|
|
11234
|
+
existingDocs,
|
|
11235
|
+
projectContext,
|
|
11236
|
+
learnedSection,
|
|
11237
|
+
sources2,
|
|
11238
|
+
scope
|
|
11239
|
+
);
|
|
11197
11240
|
const fastModel = getFastModel();
|
|
11198
11241
|
const raw = await llmCall({
|
|
11199
11242
|
system: REFRESH_SYSTEM_PROMPT,
|
|
@@ -11203,8 +11246,14 @@ async function refreshDocs(diff, existingDocs, projectContext, learnedSection, s
|
|
|
11203
11246
|
});
|
|
11204
11247
|
return parseJsonResponse(raw);
|
|
11205
11248
|
}
|
|
11206
|
-
function buildRefreshPrompt(diff, existingDocs, projectContext, learnedSection, sources2) {
|
|
11249
|
+
function buildRefreshPrompt(diff, existingDocs, projectContext, learnedSection, sources2, scope) {
|
|
11207
11250
|
const parts = [];
|
|
11251
|
+
if (scope) {
|
|
11252
|
+
parts.push(`You are updating docs for the \`${scope}\` subdirectory of a monorepo.`);
|
|
11253
|
+
parts.push("Only include changes relevant to files under this directory.");
|
|
11254
|
+
parts.push("The changed files list has been filtered to this directory already.");
|
|
11255
|
+
parts.push("Ignore diff content for files outside this directory.\n");
|
|
11256
|
+
}
|
|
11208
11257
|
parts.push("Update documentation based on the following code changes.\n");
|
|
11209
11258
|
if (projectContext.packageName) parts.push(`Project: ${projectContext.packageName}`);
|
|
11210
11259
|
if (projectContext.languages?.length)
|
|
@@ -11486,10 +11535,77 @@ function migrateInlineLearnings() {
|
|
|
11486
11535
|
init_config();
|
|
11487
11536
|
init_resolve_caliber();
|
|
11488
11537
|
init_builtin_skills();
|
|
11538
|
+
|
|
11539
|
+
// src/lib/config-discovery.ts
|
|
11540
|
+
import fs39 from "fs";
|
|
11541
|
+
import path32 from "path";
|
|
11542
|
+
var CONFIG_FILE_MARKERS = [
|
|
11543
|
+
"CLAUDE.md",
|
|
11544
|
+
"AGENTS.md",
|
|
11545
|
+
".cursorrules",
|
|
11546
|
+
".github/copilot-instructions.md"
|
|
11547
|
+
];
|
|
11548
|
+
var CONFIG_DIR_MARKERS = [".cursor/rules", ".github/instructions", ".opencode/skills"];
|
|
11549
|
+
var IGNORE_DIRS3 = /* @__PURE__ */ new Set([
|
|
11550
|
+
"node_modules",
|
|
11551
|
+
".git",
|
|
11552
|
+
".next",
|
|
11553
|
+
"dist",
|
|
11554
|
+
"build",
|
|
11555
|
+
".cache",
|
|
11556
|
+
".turbo",
|
|
11557
|
+
"coverage",
|
|
11558
|
+
".caliber",
|
|
11559
|
+
"__pycache__",
|
|
11560
|
+
".venv",
|
|
11561
|
+
"vendor",
|
|
11562
|
+
"target"
|
|
11563
|
+
]);
|
|
11564
|
+
var MAX_DEPTH = 4;
|
|
11565
|
+
function hasConfigFiles(dir) {
|
|
11566
|
+
for (const marker of CONFIG_FILE_MARKERS) {
|
|
11567
|
+
if (fs39.existsSync(path32.join(dir, marker))) return true;
|
|
11568
|
+
}
|
|
11569
|
+
for (const marker of CONFIG_DIR_MARKERS) {
|
|
11570
|
+
const markerPath = path32.join(dir, marker);
|
|
11571
|
+
if (fs39.existsSync(markerPath) && fs39.statSync(markerPath).isDirectory()) return true;
|
|
11572
|
+
}
|
|
11573
|
+
return false;
|
|
11574
|
+
}
|
|
11575
|
+
function discoverConfigDirs(rootDir) {
|
|
11576
|
+
const dirs = [];
|
|
11577
|
+
if (hasConfigFiles(rootDir)) {
|
|
11578
|
+
dirs.push(".");
|
|
11579
|
+
}
|
|
11580
|
+
walkForConfigs(rootDir, rootDir, 0, dirs);
|
|
11581
|
+
dirs.sort();
|
|
11582
|
+
return dirs;
|
|
11583
|
+
}
|
|
11584
|
+
function walkForConfigs(baseDir, currentDir, depth, result) {
|
|
11585
|
+
if (depth >= MAX_DEPTH) return;
|
|
11586
|
+
let entries;
|
|
11587
|
+
try {
|
|
11588
|
+
entries = fs39.readdirSync(currentDir, { withFileTypes: true });
|
|
11589
|
+
} catch {
|
|
11590
|
+
return;
|
|
11591
|
+
}
|
|
11592
|
+
for (const entry of entries) {
|
|
11593
|
+
if (!entry.isDirectory()) continue;
|
|
11594
|
+
if (entry.name.startsWith(".") || IGNORE_DIRS3.has(entry.name)) continue;
|
|
11595
|
+
const fullPath = path32.join(currentDir, entry.name);
|
|
11596
|
+
const relPath = path32.relative(baseDir, fullPath).replace(/\\/g, "/");
|
|
11597
|
+
if (hasConfigFiles(fullPath)) {
|
|
11598
|
+
result.push(relPath);
|
|
11599
|
+
}
|
|
11600
|
+
walkForConfigs(baseDir, fullPath, depth + 1, result);
|
|
11601
|
+
}
|
|
11602
|
+
}
|
|
11603
|
+
|
|
11604
|
+
// src/commands/refresh.ts
|
|
11489
11605
|
function writeRefreshError(error) {
|
|
11490
11606
|
try {
|
|
11491
|
-
if (!
|
|
11492
|
-
|
|
11607
|
+
if (!fs41.existsSync(CALIBER_DIR)) fs41.mkdirSync(CALIBER_DIR, { recursive: true });
|
|
11608
|
+
fs41.writeFileSync(
|
|
11493
11609
|
REFRESH_LAST_ERROR_FILE,
|
|
11494
11610
|
JSON.stringify(
|
|
11495
11611
|
{
|
|
@@ -11508,15 +11624,15 @@ function writeRefreshError(error) {
|
|
|
11508
11624
|
}
|
|
11509
11625
|
function readRefreshError() {
|
|
11510
11626
|
try {
|
|
11511
|
-
if (!
|
|
11512
|
-
return JSON.parse(
|
|
11627
|
+
if (!fs41.existsSync(REFRESH_LAST_ERROR_FILE)) return null;
|
|
11628
|
+
return JSON.parse(fs41.readFileSync(REFRESH_LAST_ERROR_FILE, "utf-8"));
|
|
11513
11629
|
} catch {
|
|
11514
11630
|
return null;
|
|
11515
11631
|
}
|
|
11516
11632
|
}
|
|
11517
11633
|
function clearRefreshError() {
|
|
11518
11634
|
try {
|
|
11519
|
-
if (
|
|
11635
|
+
if (fs41.existsSync(REFRESH_LAST_ERROR_FILE)) fs41.unlinkSync(REFRESH_LAST_ERROR_FILE);
|
|
11520
11636
|
} catch {
|
|
11521
11637
|
}
|
|
11522
11638
|
}
|
|
@@ -11536,11 +11652,11 @@ function log2(quiet, ...args) {
|
|
|
11536
11652
|
function discoverGitRepos(parentDir) {
|
|
11537
11653
|
const repos = [];
|
|
11538
11654
|
try {
|
|
11539
|
-
const entries =
|
|
11655
|
+
const entries = fs41.readdirSync(parentDir, { withFileTypes: true });
|
|
11540
11656
|
for (const entry of entries) {
|
|
11541
11657
|
if (!entry.isDirectory() || entry.name.startsWith(".")) continue;
|
|
11542
|
-
const childPath =
|
|
11543
|
-
if (
|
|
11658
|
+
const childPath = path34.join(parentDir, entry.name);
|
|
11659
|
+
if (fs41.existsSync(path34.join(childPath, ".git"))) {
|
|
11544
11660
|
repos.push(childPath);
|
|
11545
11661
|
}
|
|
11546
11662
|
}
|
|
@@ -11548,51 +11664,33 @@ function discoverGitRepos(parentDir) {
|
|
|
11548
11664
|
}
|
|
11549
11665
|
return repos.sort();
|
|
11550
11666
|
}
|
|
11551
|
-
function collectFilesToWrite(updatedDocs) {
|
|
11667
|
+
function collectFilesToWrite(updatedDocs, dir = ".") {
|
|
11552
11668
|
const files = [];
|
|
11553
|
-
|
|
11554
|
-
if (updatedDocs.
|
|
11555
|
-
if (updatedDocs.
|
|
11556
|
-
if (updatedDocs.
|
|
11669
|
+
const p = (relPath) => (dir === "." ? relPath : path34.join(dir, relPath)).replace(/\\/g, "/");
|
|
11670
|
+
if (updatedDocs.agentsMd) files.push(p("AGENTS.md"));
|
|
11671
|
+
if (updatedDocs.claudeMd) files.push(p("CLAUDE.md"));
|
|
11672
|
+
if (updatedDocs.readmeMd) files.push(p("README.md"));
|
|
11673
|
+
if (updatedDocs.cursorrules) files.push(p(".cursorrules"));
|
|
11557
11674
|
if (Array.isArray(updatedDocs.cursorRules)) {
|
|
11558
11675
|
for (const r of updatedDocs.cursorRules)
|
|
11559
|
-
files.push(`.cursor/rules/${r.filename}`);
|
|
11676
|
+
files.push(p(`.cursor/rules/${r.filename}`));
|
|
11560
11677
|
}
|
|
11561
|
-
if (updatedDocs.copilotInstructions) files.push(".github/copilot-instructions.md");
|
|
11678
|
+
if (updatedDocs.copilotInstructions) files.push(p(".github/copilot-instructions.md"));
|
|
11562
11679
|
if (Array.isArray(updatedDocs.copilotInstructionFiles)) {
|
|
11563
11680
|
for (const f of updatedDocs.copilotInstructionFiles)
|
|
11564
|
-
files.push(`.github/instructions/${f.filename}`);
|
|
11681
|
+
files.push(p(`.github/instructions/${f.filename}`));
|
|
11565
11682
|
}
|
|
11566
11683
|
return files;
|
|
11567
11684
|
}
|
|
11568
11685
|
var REFRESH_COOLDOWN_MS = 3e4;
|
|
11569
|
-
async function
|
|
11686
|
+
async function refreshDir(repoDir, dir, diff, options) {
|
|
11570
11687
|
const quiet = !!options.quiet;
|
|
11571
11688
|
const prefix = options.label ? `${chalk19.bold(options.label)} ` : "";
|
|
11572
|
-
const
|
|
11573
|
-
const
|
|
11574
|
-
const currentSha = getCurrentHeadSha();
|
|
11575
|
-
if (state?.lastRefreshTimestamp && lastSha && currentSha === lastSha) {
|
|
11576
|
-
const elapsed = Date.now() - new Date(state.lastRefreshTimestamp).getTime();
|
|
11577
|
-
if (elapsed < REFRESH_COOLDOWN_MS && elapsed > 0) {
|
|
11578
|
-
log2(
|
|
11579
|
-
quiet,
|
|
11580
|
-
chalk19.dim(`${prefix}Skipped \u2014 last refresh was ${Math.round(elapsed / 1e3)}s ago.`)
|
|
11581
|
-
);
|
|
11582
|
-
return;
|
|
11583
|
-
}
|
|
11584
|
-
}
|
|
11585
|
-
const diff = collectDiff(lastSha);
|
|
11586
|
-
if (!diff.hasChanges) {
|
|
11587
|
-
if (currentSha) {
|
|
11588
|
-
writeState({ lastRefreshSha: currentSha, lastRefreshTimestamp: (/* @__PURE__ */ new Date()).toISOString() });
|
|
11589
|
-
}
|
|
11590
|
-
log2(quiet, chalk19.dim(`${prefix}No changes since last refresh.`));
|
|
11591
|
-
return;
|
|
11592
|
-
}
|
|
11689
|
+
const absDir = dir === "." ? repoDir : path34.resolve(repoDir, dir);
|
|
11690
|
+
const scope = dir === "." ? void 0 : dir;
|
|
11593
11691
|
const spinner = quiet ? null : ora6(`${prefix}Analyzing changes...`).start();
|
|
11594
11692
|
const learnedSection = readLearnedSection();
|
|
11595
|
-
const fingerprint = await collectFingerprint(
|
|
11693
|
+
const fingerprint = await collectFingerprint(absDir);
|
|
11596
11694
|
const existingDocs = fingerprint.existingConfigs;
|
|
11597
11695
|
const projectContext = {
|
|
11598
11696
|
languages: fingerprint.languages,
|
|
@@ -11600,8 +11698,8 @@ async function refreshSingleRepo(repoDir, options) {
|
|
|
11600
11698
|
packageName: fingerprint.packageName,
|
|
11601
11699
|
fileTree: fingerprint.fileTree
|
|
11602
11700
|
};
|
|
11603
|
-
const workspaces = getDetectedWorkspaces(
|
|
11604
|
-
const sources2 = resolveAllSources(
|
|
11701
|
+
const workspaces = getDetectedWorkspaces(absDir);
|
|
11702
|
+
const sources2 = resolveAllSources(absDir, [], workspaces);
|
|
11605
11703
|
const diffPayload = {
|
|
11606
11704
|
committed: diff.committedDiff,
|
|
11607
11705
|
staged: diff.stagedDiff,
|
|
@@ -11617,7 +11715,8 @@ async function refreshSingleRepo(repoDir, options) {
|
|
|
11617
11715
|
existingDocs,
|
|
11618
11716
|
projectContext,
|
|
11619
11717
|
learnedSection,
|
|
11620
|
-
sourcesPayload
|
|
11718
|
+
sourcesPayload,
|
|
11719
|
+
scope
|
|
11621
11720
|
);
|
|
11622
11721
|
} catch (firstErr) {
|
|
11623
11722
|
const isTransient = firstErr instanceof Error && TRANSIENT_ERRORS.some((e) => firstErr.message.toLowerCase().includes(e.toLowerCase()));
|
|
@@ -11628,7 +11727,8 @@ async function refreshSingleRepo(repoDir, options) {
|
|
|
11628
11727
|
existingDocs,
|
|
11629
11728
|
projectContext,
|
|
11630
11729
|
learnedSection,
|
|
11631
|
-
sourcesPayload
|
|
11730
|
+
sourcesPayload,
|
|
11731
|
+
scope
|
|
11632
11732
|
);
|
|
11633
11733
|
} catch {
|
|
11634
11734
|
spinner?.fail(`${prefix}Refresh failed after retry`);
|
|
@@ -11637,10 +11737,7 @@ async function refreshSingleRepo(repoDir, options) {
|
|
|
11637
11737
|
}
|
|
11638
11738
|
if (!response.docsUpdated || response.docsUpdated.length === 0) {
|
|
11639
11739
|
spinner?.succeed(`${prefix}No doc updates needed`);
|
|
11640
|
-
|
|
11641
|
-
writeState({ lastRefreshSha: currentSha, lastRefreshTimestamp: (/* @__PURE__ */ new Date()).toISOString() });
|
|
11642
|
-
}
|
|
11643
|
-
return;
|
|
11740
|
+
return { written: [] };
|
|
11644
11741
|
}
|
|
11645
11742
|
if (options.dryRun) {
|
|
11646
11743
|
spinner?.info(`${prefix}Dry run \u2014 would update:`);
|
|
@@ -11651,49 +11748,53 @@ async function refreshSingleRepo(repoDir, options) {
|
|
|
11651
11748
|
console.log(chalk19.dim(`
|
|
11652
11749
|
${response.changesSummary}`));
|
|
11653
11750
|
}
|
|
11654
|
-
return;
|
|
11751
|
+
return { written: [] };
|
|
11655
11752
|
}
|
|
11656
|
-
const
|
|
11657
|
-
const preScore = computeLocalScore(repoDir, targetAgent);
|
|
11658
|
-
const allFilesToWrite = collectFilesToWrite(response.updatedDocs);
|
|
11753
|
+
const allFilesToWrite = collectFilesToWrite(response.updatedDocs, dir);
|
|
11659
11754
|
const preRefreshContents = /* @__PURE__ */ new Map();
|
|
11660
11755
|
for (const filePath of allFilesToWrite) {
|
|
11661
|
-
const fullPath =
|
|
11756
|
+
const fullPath = path34.resolve(repoDir, filePath);
|
|
11662
11757
|
try {
|
|
11663
|
-
preRefreshContents.set(filePath,
|
|
11758
|
+
preRefreshContents.set(filePath, fs41.readFileSync(fullPath, "utf-8"));
|
|
11664
11759
|
} catch {
|
|
11665
11760
|
preRefreshContents.set(filePath, null);
|
|
11666
11761
|
}
|
|
11667
11762
|
}
|
|
11668
|
-
const
|
|
11763
|
+
const state = readState();
|
|
11764
|
+
const targetAgent = state?.targetAgent ?? detectTargetAgent(repoDir);
|
|
11765
|
+
const runQualityGate = dir === ".";
|
|
11766
|
+
const preScore = runQualityGate ? computeLocalScore(absDir, targetAgent) : null;
|
|
11767
|
+
const written = writeRefreshDocs(response.updatedDocs, dir);
|
|
11669
11768
|
const trigger = quiet ? "hook" : "manual";
|
|
11670
11769
|
trackRefreshCompleted(written.length, Date.now(), trigger);
|
|
11671
|
-
|
|
11672
|
-
|
|
11673
|
-
|
|
11674
|
-
const
|
|
11675
|
-
|
|
11676
|
-
|
|
11677
|
-
|
|
11678
|
-
|
|
11770
|
+
if (runQualityGate && preScore) {
|
|
11771
|
+
const postScore = computeLocalScore(absDir, targetAgent);
|
|
11772
|
+
if (postScore.score < preScore.score) {
|
|
11773
|
+
for (const [filePath, content] of preRefreshContents) {
|
|
11774
|
+
const fullPath = path34.resolve(repoDir, filePath);
|
|
11775
|
+
if (content === null) {
|
|
11776
|
+
try {
|
|
11777
|
+
fs41.unlinkSync(fullPath);
|
|
11778
|
+
} catch {
|
|
11779
|
+
}
|
|
11780
|
+
} else {
|
|
11781
|
+
fs41.writeFileSync(fullPath, content);
|
|
11679
11782
|
}
|
|
11680
|
-
} else {
|
|
11681
|
-
fs40.writeFileSync(fullPath, content);
|
|
11682
11783
|
}
|
|
11784
|
+
spinner?.warn(
|
|
11785
|
+
`${prefix}Refresh reverted \u2014 score would drop from ${preScore.score} to ${postScore.score}`
|
|
11786
|
+
);
|
|
11787
|
+
log2(quiet, chalk19.dim(` Config quality gate prevented a regression. No files were changed.`));
|
|
11788
|
+
return { written: [] };
|
|
11683
11789
|
}
|
|
11684
|
-
|
|
11685
|
-
`${prefix}Refresh reverted \u2014 score would drop from ${preScore.score} to ${postScore.score}`
|
|
11686
|
-
);
|
|
11687
|
-
log2(quiet, chalk19.dim(` Config quality gate prevented a regression. No files were changed.`));
|
|
11688
|
-
if (currentSha) {
|
|
11689
|
-
writeState({ lastRefreshSha: currentSha, lastRefreshTimestamp: (/* @__PURE__ */ new Date()).toISOString() });
|
|
11690
|
-
}
|
|
11691
|
-
return;
|
|
11790
|
+
recordScore(postScore, "refresh");
|
|
11692
11791
|
}
|
|
11693
|
-
recordScore(postScore, "refresh");
|
|
11694
11792
|
spinner?.succeed(`${prefix}Updated ${written.length} doc${written.length === 1 ? "" : "s"}`);
|
|
11695
11793
|
const fileChangesMap = new Map(
|
|
11696
|
-
(response.fileChanges || []).map((fc) => [
|
|
11794
|
+
(response.fileChanges || []).map((fc) => [
|
|
11795
|
+
fc.file,
|
|
11796
|
+
fc.description
|
|
11797
|
+
])
|
|
11697
11798
|
);
|
|
11698
11799
|
for (const file of written) {
|
|
11699
11800
|
const desc = fileChangesMap.get(file);
|
|
@@ -11709,6 +11810,59 @@ async function refreshSingleRepo(repoDir, options) {
|
|
|
11709
11810
|
log2(quiet, chalk19.dim(`
|
|
11710
11811
|
${response.changesSummary}`));
|
|
11711
11812
|
}
|
|
11813
|
+
return { written };
|
|
11814
|
+
}
|
|
11815
|
+
async function refreshSingleRepo(repoDir, options) {
|
|
11816
|
+
const quiet = !!options.quiet;
|
|
11817
|
+
const prefix = options.label ? `${chalk19.bold(options.label)} ` : "";
|
|
11818
|
+
const state = readState();
|
|
11819
|
+
const lastSha = state?.lastRefreshSha ?? null;
|
|
11820
|
+
const currentSha = getCurrentHeadSha();
|
|
11821
|
+
if (state?.lastRefreshTimestamp && lastSha && currentSha === lastSha) {
|
|
11822
|
+
const elapsed = Date.now() - new Date(state.lastRefreshTimestamp).getTime();
|
|
11823
|
+
if (elapsed < REFRESH_COOLDOWN_MS && elapsed > 0) {
|
|
11824
|
+
log2(
|
|
11825
|
+
quiet,
|
|
11826
|
+
chalk19.dim(`${prefix}Skipped \u2014 last refresh was ${Math.round(elapsed / 1e3)}s ago.`)
|
|
11827
|
+
);
|
|
11828
|
+
return;
|
|
11829
|
+
}
|
|
11830
|
+
}
|
|
11831
|
+
const diff = collectDiff(lastSha);
|
|
11832
|
+
if (!diff.hasChanges) {
|
|
11833
|
+
if (currentSha) {
|
|
11834
|
+
writeState({ lastRefreshSha: currentSha, lastRefreshTimestamp: (/* @__PURE__ */ new Date()).toISOString() });
|
|
11835
|
+
}
|
|
11836
|
+
log2(quiet, chalk19.dim(`${prefix}No changes since last refresh.`));
|
|
11837
|
+
return;
|
|
11838
|
+
}
|
|
11839
|
+
const configDirs = discoverConfigDirs(repoDir);
|
|
11840
|
+
if (configDirs.length <= 1) {
|
|
11841
|
+
await refreshDir(repoDir, ".", diff, options);
|
|
11842
|
+
} else {
|
|
11843
|
+
log2(quiet, chalk19.dim(`${prefix}Found configs in ${configDirs.length} directories
|
|
11844
|
+
`));
|
|
11845
|
+
let hadFailure = false;
|
|
11846
|
+
for (const dir of configDirs) {
|
|
11847
|
+
const scopedDiff = scopeDiffToDir(diff, dir, configDirs);
|
|
11848
|
+
if (!scopedDiff.hasChanges) continue;
|
|
11849
|
+
const dirLabel = dir === "." ? "root" : dir;
|
|
11850
|
+
try {
|
|
11851
|
+
await refreshDir(repoDir, dir, scopedDiff, { ...options, label: dirLabel });
|
|
11852
|
+
} catch (err) {
|
|
11853
|
+
hadFailure = true;
|
|
11854
|
+
log2(
|
|
11855
|
+
quiet,
|
|
11856
|
+
chalk19.yellow(
|
|
11857
|
+
` ${dirLabel}: refresh failed \u2014 ${err instanceof Error ? err.message : "unknown error"}`
|
|
11858
|
+
)
|
|
11859
|
+
);
|
|
11860
|
+
}
|
|
11861
|
+
}
|
|
11862
|
+
if (hadFailure) {
|
|
11863
|
+
return;
|
|
11864
|
+
}
|
|
11865
|
+
}
|
|
11712
11866
|
const builtinWritten = ensureBuiltinSkills();
|
|
11713
11867
|
for (const file of builtinWritten) {
|
|
11714
11868
|
log2(quiet, ` ${chalk19.green("\u2713")} ${file} ${chalk19.dim("(built-in)")}`);
|
|
@@ -11765,7 +11919,7 @@ async function refreshCommand(options) {
|
|
|
11765
11919
|
`));
|
|
11766
11920
|
const originalDir = process.cwd();
|
|
11767
11921
|
for (const repo of repos) {
|
|
11768
|
-
const repoName =
|
|
11922
|
+
const repoName = path34.basename(repo);
|
|
11769
11923
|
try {
|
|
11770
11924
|
process.chdir(repo);
|
|
11771
11925
|
await refreshSingleRepo(repo, { ...options, label: repoName });
|
|
@@ -11793,7 +11947,7 @@ async function refreshCommand(options) {
|
|
|
11793
11947
|
|
|
11794
11948
|
// src/commands/hooks.ts
|
|
11795
11949
|
import chalk20 from "chalk";
|
|
11796
|
-
import
|
|
11950
|
+
import fs42 from "fs";
|
|
11797
11951
|
var HOOKS = [
|
|
11798
11952
|
{
|
|
11799
11953
|
id: "session-end",
|
|
@@ -11837,11 +11991,11 @@ async function hooksCommand(options) {
|
|
|
11837
11991
|
console.log(chalk20.green(" \u2713") + ` ${hook.label} enabled`);
|
|
11838
11992
|
}
|
|
11839
11993
|
}
|
|
11840
|
-
if (
|
|
11994
|
+
if (fs42.existsSync(".claude")) {
|
|
11841
11995
|
const r = installLearningHooks();
|
|
11842
11996
|
if (r.installed) console.log(chalk20.green(" \u2713") + " Claude Code learning hooks enabled");
|
|
11843
11997
|
}
|
|
11844
|
-
if (
|
|
11998
|
+
if (fs42.existsSync(".cursor")) {
|
|
11845
11999
|
const r = installCursorLearningHooks();
|
|
11846
12000
|
if (r.installed) console.log(chalk20.green(" \u2713") + " Cursor learning hooks enabled");
|
|
11847
12001
|
}
|
|
@@ -12009,8 +12163,8 @@ async function configCommand() {
|
|
|
12009
12163
|
}
|
|
12010
12164
|
|
|
12011
12165
|
// src/commands/learn.ts
|
|
12012
|
-
import
|
|
12013
|
-
import
|
|
12166
|
+
import fs46 from "fs";
|
|
12167
|
+
import path38 from "path";
|
|
12014
12168
|
import chalk23 from "chalk";
|
|
12015
12169
|
|
|
12016
12170
|
// src/learner/stdin.ts
|
|
@@ -12041,8 +12195,8 @@ function readStdin() {
|
|
|
12041
12195
|
}
|
|
12042
12196
|
|
|
12043
12197
|
// src/learner/storage.ts
|
|
12044
|
-
import
|
|
12045
|
-
import
|
|
12198
|
+
import fs43 from "fs";
|
|
12199
|
+
import path35 from "path";
|
|
12046
12200
|
var MAX_RESPONSE_LENGTH = 2e3;
|
|
12047
12201
|
var DEFAULT_STATE = {
|
|
12048
12202
|
sessionId: null,
|
|
@@ -12051,15 +12205,15 @@ var DEFAULT_STATE = {
|
|
|
12051
12205
|
lastAnalysisEventCount: 0
|
|
12052
12206
|
};
|
|
12053
12207
|
function ensureLearningDir() {
|
|
12054
|
-
if (!
|
|
12055
|
-
|
|
12208
|
+
if (!fs43.existsSync(getLearningDir())) {
|
|
12209
|
+
fs43.mkdirSync(getLearningDir(), { recursive: true });
|
|
12056
12210
|
}
|
|
12057
12211
|
}
|
|
12058
12212
|
function sessionFilePath() {
|
|
12059
|
-
return
|
|
12213
|
+
return path35.join(getLearningDir(), LEARNING_SESSION_FILE);
|
|
12060
12214
|
}
|
|
12061
12215
|
function stateFilePath() {
|
|
12062
|
-
return
|
|
12216
|
+
return path35.join(getLearningDir(), LEARNING_STATE_FILE);
|
|
12063
12217
|
}
|
|
12064
12218
|
function truncateResponse(response) {
|
|
12065
12219
|
const str = JSON.stringify(response);
|
|
@@ -12069,10 +12223,10 @@ function truncateResponse(response) {
|
|
|
12069
12223
|
function trimSessionFileIfNeeded(filePath) {
|
|
12070
12224
|
const state = readState2();
|
|
12071
12225
|
if (state.eventCount + 1 > LEARNING_MAX_EVENTS) {
|
|
12072
|
-
const lines =
|
|
12226
|
+
const lines = fs43.readFileSync(filePath, "utf-8").split("\n").filter(Boolean);
|
|
12073
12227
|
if (lines.length > LEARNING_MAX_EVENTS) {
|
|
12074
12228
|
const kept = lines.slice(lines.length - LEARNING_MAX_EVENTS);
|
|
12075
|
-
|
|
12229
|
+
fs43.writeFileSync(filePath, kept.join("\n") + "\n");
|
|
12076
12230
|
}
|
|
12077
12231
|
}
|
|
12078
12232
|
}
|
|
@@ -12080,19 +12234,19 @@ function appendEvent(event) {
|
|
|
12080
12234
|
ensureLearningDir();
|
|
12081
12235
|
const truncated = { ...event, tool_response: truncateResponse(event.tool_response) };
|
|
12082
12236
|
const filePath = sessionFilePath();
|
|
12083
|
-
|
|
12237
|
+
fs43.appendFileSync(filePath, JSON.stringify(truncated) + "\n");
|
|
12084
12238
|
trimSessionFileIfNeeded(filePath);
|
|
12085
12239
|
}
|
|
12086
12240
|
function appendPromptEvent(event) {
|
|
12087
12241
|
ensureLearningDir();
|
|
12088
12242
|
const filePath = sessionFilePath();
|
|
12089
|
-
|
|
12243
|
+
fs43.appendFileSync(filePath, JSON.stringify(event) + "\n");
|
|
12090
12244
|
trimSessionFileIfNeeded(filePath);
|
|
12091
12245
|
}
|
|
12092
12246
|
function readAllEvents() {
|
|
12093
12247
|
const filePath = sessionFilePath();
|
|
12094
|
-
if (!
|
|
12095
|
-
const lines =
|
|
12248
|
+
if (!fs43.existsSync(filePath)) return [];
|
|
12249
|
+
const lines = fs43.readFileSync(filePath, "utf-8").split("\n").filter(Boolean);
|
|
12096
12250
|
const events = [];
|
|
12097
12251
|
for (const line of lines) {
|
|
12098
12252
|
try {
|
|
@@ -12104,26 +12258,26 @@ function readAllEvents() {
|
|
|
12104
12258
|
}
|
|
12105
12259
|
function getEventCount() {
|
|
12106
12260
|
const filePath = sessionFilePath();
|
|
12107
|
-
if (!
|
|
12108
|
-
const content =
|
|
12261
|
+
if (!fs43.existsSync(filePath)) return 0;
|
|
12262
|
+
const content = fs43.readFileSync(filePath, "utf-8");
|
|
12109
12263
|
return content.split("\n").filter(Boolean).length;
|
|
12110
12264
|
}
|
|
12111
12265
|
function clearSession() {
|
|
12112
12266
|
const filePath = sessionFilePath();
|
|
12113
|
-
if (
|
|
12267
|
+
if (fs43.existsSync(filePath)) fs43.unlinkSync(filePath);
|
|
12114
12268
|
}
|
|
12115
12269
|
function readState2() {
|
|
12116
12270
|
const filePath = stateFilePath();
|
|
12117
|
-
if (!
|
|
12271
|
+
if (!fs43.existsSync(filePath)) return { ...DEFAULT_STATE };
|
|
12118
12272
|
try {
|
|
12119
|
-
return JSON.parse(
|
|
12273
|
+
return JSON.parse(fs43.readFileSync(filePath, "utf-8"));
|
|
12120
12274
|
} catch {
|
|
12121
12275
|
return { ...DEFAULT_STATE };
|
|
12122
12276
|
}
|
|
12123
12277
|
}
|
|
12124
12278
|
function writeState2(state) {
|
|
12125
12279
|
ensureLearningDir();
|
|
12126
|
-
|
|
12280
|
+
fs43.writeFileSync(stateFilePath(), JSON.stringify(state, null, 2));
|
|
12127
12281
|
}
|
|
12128
12282
|
function resetState() {
|
|
12129
12283
|
writeState2({ ...DEFAULT_STATE });
|
|
@@ -12131,16 +12285,16 @@ function resetState() {
|
|
|
12131
12285
|
var LOCK_FILE = "finalize.lock";
|
|
12132
12286
|
var LOCK_STALE_MS = 5 * 60 * 1e3;
|
|
12133
12287
|
function lockFilePath() {
|
|
12134
|
-
return
|
|
12288
|
+
return path35.join(getLearningDir(), LOCK_FILE);
|
|
12135
12289
|
}
|
|
12136
12290
|
function acquireFinalizeLock() {
|
|
12137
12291
|
ensureLearningDir();
|
|
12138
12292
|
const lockPath = lockFilePath();
|
|
12139
|
-
if (
|
|
12293
|
+
if (fs43.existsSync(lockPath)) {
|
|
12140
12294
|
try {
|
|
12141
|
-
const stat =
|
|
12295
|
+
const stat = fs43.statSync(lockPath);
|
|
12142
12296
|
if (Date.now() - stat.mtimeMs < LOCK_STALE_MS) {
|
|
12143
|
-
const pid = parseInt(
|
|
12297
|
+
const pid = parseInt(fs43.readFileSync(lockPath, "utf-8").trim(), 10);
|
|
12144
12298
|
if (!isNaN(pid) && isProcessAlive(pid)) {
|
|
12145
12299
|
return false;
|
|
12146
12300
|
}
|
|
@@ -12148,12 +12302,12 @@ function acquireFinalizeLock() {
|
|
|
12148
12302
|
} catch {
|
|
12149
12303
|
}
|
|
12150
12304
|
try {
|
|
12151
|
-
|
|
12305
|
+
fs43.unlinkSync(lockPath);
|
|
12152
12306
|
} catch {
|
|
12153
12307
|
}
|
|
12154
12308
|
}
|
|
12155
12309
|
try {
|
|
12156
|
-
|
|
12310
|
+
fs43.writeFileSync(lockPath, String(process.pid), { flag: "wx" });
|
|
12157
12311
|
return true;
|
|
12158
12312
|
} catch {
|
|
12159
12313
|
return false;
|
|
@@ -12170,30 +12324,30 @@ function isProcessAlive(pid) {
|
|
|
12170
12324
|
function releaseFinalizeLock() {
|
|
12171
12325
|
const lockPath = lockFilePath();
|
|
12172
12326
|
try {
|
|
12173
|
-
if (
|
|
12327
|
+
if (fs43.existsSync(lockPath)) fs43.unlinkSync(lockPath);
|
|
12174
12328
|
} catch {
|
|
12175
12329
|
}
|
|
12176
12330
|
}
|
|
12177
12331
|
|
|
12178
12332
|
// src/lib/notifications.ts
|
|
12179
|
-
import
|
|
12180
|
-
import
|
|
12333
|
+
import fs44 from "fs";
|
|
12334
|
+
import path36 from "path";
|
|
12181
12335
|
import chalk22 from "chalk";
|
|
12182
12336
|
function notificationFilePath() {
|
|
12183
|
-
return
|
|
12337
|
+
return path36.join(getLearningDir(), "last-finalize-summary.json");
|
|
12184
12338
|
}
|
|
12185
12339
|
function writeFinalizeSummary(summary) {
|
|
12186
12340
|
try {
|
|
12187
12341
|
ensureLearningDir();
|
|
12188
|
-
|
|
12342
|
+
fs44.writeFileSync(notificationFilePath(), JSON.stringify(summary, null, 2));
|
|
12189
12343
|
} catch {
|
|
12190
12344
|
}
|
|
12191
12345
|
}
|
|
12192
12346
|
function checkPendingNotifications() {
|
|
12193
12347
|
try {
|
|
12194
|
-
if (!
|
|
12195
|
-
const raw =
|
|
12196
|
-
|
|
12348
|
+
if (!fs44.existsSync(notificationFilePath())) return;
|
|
12349
|
+
const raw = fs44.readFileSync(notificationFilePath(), "utf-8");
|
|
12350
|
+
fs44.unlinkSync(notificationFilePath());
|
|
12197
12351
|
const summary = JSON.parse(raw);
|
|
12198
12352
|
if (!summary.newItemCount || summary.newItemCount === 0) return;
|
|
12199
12353
|
const wasteLabel = summary.wasteTokens > 0 ? ` (~${summary.wasteTokens.toLocaleString()} wasted tokens captured)` : "";
|
|
@@ -12209,7 +12363,7 @@ function checkPendingNotifications() {
|
|
|
12209
12363
|
console.log("");
|
|
12210
12364
|
} catch {
|
|
12211
12365
|
try {
|
|
12212
|
-
|
|
12366
|
+
fs44.unlinkSync(notificationFilePath());
|
|
12213
12367
|
} catch {
|
|
12214
12368
|
}
|
|
12215
12369
|
}
|
|
@@ -12361,8 +12515,8 @@ function calculateSessionWaste(events) {
|
|
|
12361
12515
|
init_config();
|
|
12362
12516
|
|
|
12363
12517
|
// src/learner/roi.ts
|
|
12364
|
-
import
|
|
12365
|
-
import
|
|
12518
|
+
import fs45 from "fs";
|
|
12519
|
+
import path37 from "path";
|
|
12366
12520
|
var DEFAULT_TOTALS = {
|
|
12367
12521
|
totalWasteTokens: 0,
|
|
12368
12522
|
totalWasteSeconds: 0,
|
|
@@ -12376,19 +12530,19 @@ var DEFAULT_TOTALS = {
|
|
|
12376
12530
|
lastSessionTimestamp: ""
|
|
12377
12531
|
};
|
|
12378
12532
|
function roiFilePath() {
|
|
12379
|
-
return
|
|
12533
|
+
return path37.join(getLearningDir(), LEARNING_ROI_FILE);
|
|
12380
12534
|
}
|
|
12381
12535
|
function readROIStats() {
|
|
12382
12536
|
const filePath = roiFilePath();
|
|
12383
|
-
if (!
|
|
12537
|
+
if (!fs45.existsSync(filePath)) {
|
|
12384
12538
|
return { learnings: [], sessions: [], totals: { ...DEFAULT_TOTALS } };
|
|
12385
12539
|
}
|
|
12386
12540
|
try {
|
|
12387
|
-
return JSON.parse(
|
|
12541
|
+
return JSON.parse(fs45.readFileSync(filePath, "utf-8"));
|
|
12388
12542
|
} catch {
|
|
12389
12543
|
try {
|
|
12390
12544
|
const corruptPath = filePath + ".corrupt";
|
|
12391
|
-
|
|
12545
|
+
fs45.renameSync(filePath, corruptPath);
|
|
12392
12546
|
console.error(`caliber: roi-stats.json was corrupt \u2014 renamed to ${corruptPath}`);
|
|
12393
12547
|
} catch {
|
|
12394
12548
|
}
|
|
@@ -12397,7 +12551,7 @@ function readROIStats() {
|
|
|
12397
12551
|
}
|
|
12398
12552
|
function writeROIStats(stats) {
|
|
12399
12553
|
ensureLearningDir();
|
|
12400
|
-
|
|
12554
|
+
fs45.writeFileSync(roiFilePath(), JSON.stringify(stats, null, 2));
|
|
12401
12555
|
}
|
|
12402
12556
|
function recalculateTotals(stats) {
|
|
12403
12557
|
const totals = stats.totals;
|
|
@@ -12606,9 +12760,9 @@ var AUTO_SETTLE_MS = 200;
|
|
|
12606
12760
|
var INCREMENTAL_INTERVAL = 50;
|
|
12607
12761
|
function writeFinalizeError(message) {
|
|
12608
12762
|
try {
|
|
12609
|
-
const errorPath =
|
|
12610
|
-
if (!
|
|
12611
|
-
|
|
12763
|
+
const errorPath = path38.join(getLearningDir(), LEARNING_LAST_ERROR_FILE);
|
|
12764
|
+
if (!fs46.existsSync(getLearningDir())) fs46.mkdirSync(getLearningDir(), { recursive: true });
|
|
12765
|
+
fs46.writeFileSync(errorPath, JSON.stringify({
|
|
12612
12766
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
12613
12767
|
error: message,
|
|
12614
12768
|
pid: process.pid
|
|
@@ -12618,9 +12772,9 @@ function writeFinalizeError(message) {
|
|
|
12618
12772
|
}
|
|
12619
12773
|
function readFinalizeError() {
|
|
12620
12774
|
try {
|
|
12621
|
-
const errorPath =
|
|
12622
|
-
if (!
|
|
12623
|
-
return JSON.parse(
|
|
12775
|
+
const errorPath = path38.join(getLearningDir(), LEARNING_LAST_ERROR_FILE);
|
|
12776
|
+
if (!fs46.existsSync(errorPath)) return null;
|
|
12777
|
+
return JSON.parse(fs46.readFileSync(errorPath, "utf-8"));
|
|
12624
12778
|
} catch {
|
|
12625
12779
|
return null;
|
|
12626
12780
|
}
|
|
@@ -12667,14 +12821,14 @@ async function learnObserveCommand(options) {
|
|
|
12667
12821
|
const { resolveCaliber: resolveCaliber2 } = await Promise.resolve().then(() => (init_resolve_caliber(), resolve_caliber_exports));
|
|
12668
12822
|
const bin = resolveCaliber2();
|
|
12669
12823
|
const { spawn: spawn4 } = await import("child_process");
|
|
12670
|
-
const logPath =
|
|
12671
|
-
if (!
|
|
12672
|
-
const logFd =
|
|
12824
|
+
const logPath = path38.join(getLearningDir(), LEARNING_FINALIZE_LOG);
|
|
12825
|
+
if (!fs46.existsSync(getLearningDir())) fs46.mkdirSync(getLearningDir(), { recursive: true });
|
|
12826
|
+
const logFd = fs46.openSync(logPath, "a");
|
|
12673
12827
|
spawn4(bin, ["learn", "finalize", "--auto", "--incremental"], {
|
|
12674
12828
|
detached: true,
|
|
12675
12829
|
stdio: ["ignore", logFd, logFd]
|
|
12676
12830
|
}).unref();
|
|
12677
|
-
|
|
12831
|
+
fs46.closeSync(logFd);
|
|
12678
12832
|
} catch {
|
|
12679
12833
|
}
|
|
12680
12834
|
}
|
|
@@ -12881,7 +13035,7 @@ async function learnFinalizeCommand(options) {
|
|
|
12881
13035
|
}
|
|
12882
13036
|
async function learnInstallCommand() {
|
|
12883
13037
|
let anyInstalled = false;
|
|
12884
|
-
if (
|
|
13038
|
+
if (fs46.existsSync(".claude")) {
|
|
12885
13039
|
const r = installLearningHooks();
|
|
12886
13040
|
if (r.installed) {
|
|
12887
13041
|
console.log(chalk23.green("\u2713") + " Claude Code learning hooks installed");
|
|
@@ -12890,7 +13044,7 @@ async function learnInstallCommand() {
|
|
|
12890
13044
|
console.log(chalk23.dim(" Claude Code hooks already installed"));
|
|
12891
13045
|
}
|
|
12892
13046
|
}
|
|
12893
|
-
if (
|
|
13047
|
+
if (fs46.existsSync(".cursor")) {
|
|
12894
13048
|
const r = installCursorLearningHooks();
|
|
12895
13049
|
if (r.installed) {
|
|
12896
13050
|
console.log(chalk23.green("\u2713") + " Cursor learning hooks installed");
|
|
@@ -12899,7 +13053,7 @@ async function learnInstallCommand() {
|
|
|
12899
13053
|
console.log(chalk23.dim(" Cursor hooks already installed"));
|
|
12900
13054
|
}
|
|
12901
13055
|
}
|
|
12902
|
-
if (!
|
|
13056
|
+
if (!fs46.existsSync(".claude") && !fs46.existsSync(".cursor")) {
|
|
12903
13057
|
console.log(chalk23.yellow("No .claude/ or .cursor/ directory found."));
|
|
12904
13058
|
console.log(chalk23.dim(` Run \`${resolveCaliber()} init\` first, or create the directory manually.`));
|
|
12905
13059
|
return;
|
|
@@ -12957,8 +13111,8 @@ async function learnStatusCommand() {
|
|
|
12957
13111
|
if (lastError) {
|
|
12958
13112
|
console.log(`Last error: ${chalk23.red(lastError.error)}`);
|
|
12959
13113
|
console.log(chalk23.dim(` at ${lastError.timestamp}`));
|
|
12960
|
-
const logPath =
|
|
12961
|
-
if (
|
|
13114
|
+
const logPath = path38.join(getLearningDir(), LEARNING_FINALIZE_LOG);
|
|
13115
|
+
if (fs46.existsSync(logPath)) {
|
|
12962
13116
|
console.log(chalk23.dim(` Full log: ${logPath}`));
|
|
12963
13117
|
}
|
|
12964
13118
|
}
|
|
@@ -13038,11 +13192,11 @@ async function learnDeleteCommand(indexStr) {
|
|
|
13038
13192
|
}
|
|
13039
13193
|
const item = items[targetIdx];
|
|
13040
13194
|
const filePath = item.source === "personal" ? PERSONAL_LEARNINGS_FILE : "CALIBER_LEARNINGS.md";
|
|
13041
|
-
if (!
|
|
13195
|
+
if (!fs46.existsSync(filePath)) {
|
|
13042
13196
|
console.log(chalk23.red("Learnings file not found."));
|
|
13043
13197
|
return;
|
|
13044
13198
|
}
|
|
13045
|
-
const content =
|
|
13199
|
+
const content = fs46.readFileSync(filePath, "utf-8");
|
|
13046
13200
|
const lines = content.split("\n");
|
|
13047
13201
|
const bulletsOfSource = items.filter((i) => i.source === item.source);
|
|
13048
13202
|
const posInFile = bulletsOfSource.indexOf(item);
|
|
@@ -13063,9 +13217,9 @@ async function learnDeleteCommand(indexStr) {
|
|
|
13063
13217
|
}
|
|
13064
13218
|
const bulletToRemove = lines[lineToRemove];
|
|
13065
13219
|
const newLines = lines.filter((_, i) => i !== lineToRemove);
|
|
13066
|
-
|
|
13220
|
+
fs46.writeFileSync(filePath, newLines.join("\n"));
|
|
13067
13221
|
if (item.source === "personal") {
|
|
13068
|
-
|
|
13222
|
+
fs46.chmodSync(filePath, 384);
|
|
13069
13223
|
}
|
|
13070
13224
|
const roiStats = readROIStats();
|
|
13071
13225
|
const cleanText = bulletToRemove.replace(/^- /, "").replace(/^\*\*\[[^\]]+\]\*\*\s*/, "").trim();
|
|
@@ -13238,8 +13392,8 @@ async function insightsCommand(options) {
|
|
|
13238
13392
|
}
|
|
13239
13393
|
|
|
13240
13394
|
// src/commands/sources.ts
|
|
13241
|
-
import
|
|
13242
|
-
import
|
|
13395
|
+
import fs47 from "fs";
|
|
13396
|
+
import path39 from "path";
|
|
13243
13397
|
import chalk25 from "chalk";
|
|
13244
13398
|
init_resolve_caliber();
|
|
13245
13399
|
async function sourcesListCommand() {
|
|
@@ -13256,9 +13410,9 @@ async function sourcesListCommand() {
|
|
|
13256
13410
|
if (configSources.length > 0) {
|
|
13257
13411
|
for (const source of configSources) {
|
|
13258
13412
|
const sourcePath = source.path || source.url || "";
|
|
13259
|
-
const exists = source.path ?
|
|
13413
|
+
const exists = source.path ? fs47.existsSync(path39.resolve(dir, source.path)) : false;
|
|
13260
13414
|
const status = exists ? chalk25.green("reachable") : chalk25.red("not found");
|
|
13261
|
-
const hasSummary = source.path &&
|
|
13415
|
+
const hasSummary = source.path && fs47.existsSync(path39.join(path39.resolve(dir, source.path), ".caliber", "summary.json"));
|
|
13262
13416
|
console.log(` ${chalk25.bold(source.role || source.type)} ${chalk25.dim(sourcePath)}`);
|
|
13263
13417
|
console.log(` Type: ${source.type} Status: ${status}${hasSummary ? " " + chalk25.cyan("has summary.json") : ""}`);
|
|
13264
13418
|
if (source.description) console.log(` ${chalk25.dim(source.description)}`);
|
|
@@ -13268,7 +13422,7 @@ async function sourcesListCommand() {
|
|
|
13268
13422
|
if (workspaces.length > 0) {
|
|
13269
13423
|
console.log(chalk25.dim(" Auto-detected workspaces:"));
|
|
13270
13424
|
for (const ws of workspaces) {
|
|
13271
|
-
const exists =
|
|
13425
|
+
const exists = fs47.existsSync(path39.resolve(dir, ws));
|
|
13272
13426
|
console.log(` ${exists ? chalk25.green("\u25CF") : chalk25.red("\u25CF")} ${ws}`);
|
|
13273
13427
|
}
|
|
13274
13428
|
console.log("");
|
|
@@ -13276,8 +13430,8 @@ async function sourcesListCommand() {
|
|
|
13276
13430
|
}
|
|
13277
13431
|
async function sourcesAddCommand(sourcePath) {
|
|
13278
13432
|
const dir = process.cwd();
|
|
13279
|
-
const absPath =
|
|
13280
|
-
if (!
|
|
13433
|
+
const absPath = path39.resolve(dir, sourcePath);
|
|
13434
|
+
if (!fs47.existsSync(absPath)) {
|
|
13281
13435
|
console.log(chalk25.red(`
|
|
13282
13436
|
Path not found: ${sourcePath}
|
|
13283
13437
|
`));
|
|
@@ -13292,7 +13446,7 @@ async function sourcesAddCommand(sourcePath) {
|
|
|
13292
13446
|
}
|
|
13293
13447
|
const existing = loadSourcesConfig(dir);
|
|
13294
13448
|
const alreadyConfigured = existing.some(
|
|
13295
|
-
(s) => s.path &&
|
|
13449
|
+
(s) => s.path && path39.resolve(dir, s.path) === absPath
|
|
13296
13450
|
);
|
|
13297
13451
|
if (alreadyConfigured) {
|
|
13298
13452
|
console.log(chalk25.yellow(`
|
|
@@ -13340,8 +13494,8 @@ async function sourcesRemoveCommand(name) {
|
|
|
13340
13494
|
}
|
|
13341
13495
|
|
|
13342
13496
|
// src/commands/publish.ts
|
|
13343
|
-
import
|
|
13344
|
-
import
|
|
13497
|
+
import fs48 from "fs";
|
|
13498
|
+
import path40 from "path";
|
|
13345
13499
|
import chalk26 from "chalk";
|
|
13346
13500
|
import ora7 from "ora";
|
|
13347
13501
|
init_config();
|
|
@@ -13356,10 +13510,10 @@ async function publishCommand() {
|
|
|
13356
13510
|
const spinner = ora7("Generating project summary...").start();
|
|
13357
13511
|
try {
|
|
13358
13512
|
const fingerprint = await collectFingerprint(dir);
|
|
13359
|
-
const claudeMd = readFileOrNull(
|
|
13513
|
+
const claudeMd = readFileOrNull(path40.join(dir, "CLAUDE.md"));
|
|
13360
13514
|
const topLevelDirs = fingerprint.fileTree.filter((f) => f.endsWith("/") && !f.includes("/")).map((f) => f.replace(/\/$/, ""));
|
|
13361
13515
|
const summary = {
|
|
13362
|
-
name: fingerprint.packageName ||
|
|
13516
|
+
name: fingerprint.packageName || path40.basename(dir),
|
|
13363
13517
|
version: "1.0.0",
|
|
13364
13518
|
description: fingerprint.description || "",
|
|
13365
13519
|
languages: fingerprint.languages,
|
|
@@ -13371,7 +13525,7 @@ async function publishCommand() {
|
|
|
13371
13525
|
summary.conventions = claudeMd.slice(0, 2e3);
|
|
13372
13526
|
}
|
|
13373
13527
|
try {
|
|
13374
|
-
const pkgContent = readFileOrNull(
|
|
13528
|
+
const pkgContent = readFileOrNull(path40.join(dir, "package.json"));
|
|
13375
13529
|
if (pkgContent) {
|
|
13376
13530
|
const pkg3 = JSON.parse(pkgContent);
|
|
13377
13531
|
if (pkg3.scripts) {
|
|
@@ -13384,14 +13538,14 @@ async function publishCommand() {
|
|
|
13384
13538
|
}
|
|
13385
13539
|
} catch {
|
|
13386
13540
|
}
|
|
13387
|
-
const outputDir =
|
|
13388
|
-
if (!
|
|
13389
|
-
|
|
13541
|
+
const outputDir = path40.join(dir, ".caliber");
|
|
13542
|
+
if (!fs48.existsSync(outputDir)) {
|
|
13543
|
+
fs48.mkdirSync(outputDir, { recursive: true });
|
|
13390
13544
|
}
|
|
13391
|
-
const outputPath =
|
|
13392
|
-
|
|
13545
|
+
const outputPath = path40.join(outputDir, "summary.json");
|
|
13546
|
+
fs48.writeFileSync(outputPath, JSON.stringify(summary, null, 2) + "\n", "utf-8");
|
|
13393
13547
|
spinner.succeed("Project summary published");
|
|
13394
|
-
console.log(` ${chalk26.green("\u2713")} ${
|
|
13548
|
+
console.log(` ${chalk26.green("\u2713")} ${path40.relative(dir, outputPath)}`);
|
|
13395
13549
|
console.log(chalk26.dim("\n Other projects can now reference this repo as a source."));
|
|
13396
13550
|
console.log(chalk26.dim(" When they run `caliber init`, they'll read this summary automatically.\n"));
|
|
13397
13551
|
} catch (err) {
|
|
@@ -13404,7 +13558,7 @@ async function publishCommand() {
|
|
|
13404
13558
|
|
|
13405
13559
|
// src/commands/bootstrap.ts
|
|
13406
13560
|
init_builtin_skills();
|
|
13407
|
-
import
|
|
13561
|
+
import fs49 from "fs";
|
|
13408
13562
|
import chalk27 from "chalk";
|
|
13409
13563
|
var PLATFORM_SKILL_DIRS = {
|
|
13410
13564
|
claude: ".claude/skills",
|
|
@@ -13425,8 +13579,8 @@ async function bootstrapCommand() {
|
|
|
13425
13579
|
for (const skill of BUILTIN_SKILLS) {
|
|
13426
13580
|
const skillDir = `${skillsDir}/${skill.name}`;
|
|
13427
13581
|
const skillPath = `${skillDir}/SKILL.md`;
|
|
13428
|
-
|
|
13429
|
-
|
|
13582
|
+
fs49.mkdirSync(skillDir, { recursive: true });
|
|
13583
|
+
fs49.writeFileSync(skillPath, buildSkillContent(skill));
|
|
13430
13584
|
written.push(skillPath);
|
|
13431
13585
|
}
|
|
13432
13586
|
}
|
|
@@ -13443,8 +13597,8 @@ async function bootstrapCommand() {
|
|
|
13443
13597
|
}
|
|
13444
13598
|
|
|
13445
13599
|
// src/commands/uninstall.ts
|
|
13446
|
-
import
|
|
13447
|
-
import
|
|
13600
|
+
import fs50 from "fs";
|
|
13601
|
+
import path41 from "path";
|
|
13448
13602
|
import chalk28 from "chalk";
|
|
13449
13603
|
import confirm3 from "@inquirer/confirm";
|
|
13450
13604
|
init_pre_commit_block();
|
|
@@ -13452,18 +13606,18 @@ init_builtin_skills();
|
|
|
13452
13606
|
init_config();
|
|
13453
13607
|
var MANAGED_DOC_FILES = [
|
|
13454
13608
|
"CLAUDE.md",
|
|
13455
|
-
|
|
13609
|
+
path41.join(".github", "copilot-instructions.md"),
|
|
13456
13610
|
"AGENTS.md"
|
|
13457
13611
|
];
|
|
13458
13612
|
var SKILL_DIRS = PLATFORM_CONFIGS.map((c) => c.skillsDir);
|
|
13459
|
-
var CURSOR_RULES_DIR =
|
|
13613
|
+
var CURSOR_RULES_DIR = path41.join(".cursor", "rules");
|
|
13460
13614
|
function removeCaliberCursorRules() {
|
|
13461
13615
|
const removed = [];
|
|
13462
|
-
if (!
|
|
13463
|
-
for (const file of
|
|
13616
|
+
if (!fs50.existsSync(CURSOR_RULES_DIR)) return removed;
|
|
13617
|
+
for (const file of fs50.readdirSync(CURSOR_RULES_DIR)) {
|
|
13464
13618
|
if (file.startsWith("caliber-") && file.endsWith(".mdc")) {
|
|
13465
|
-
const fullPath =
|
|
13466
|
-
|
|
13619
|
+
const fullPath = path41.join(CURSOR_RULES_DIR, file);
|
|
13620
|
+
fs50.unlinkSync(fullPath);
|
|
13467
13621
|
removed.push(fullPath);
|
|
13468
13622
|
}
|
|
13469
13623
|
}
|
|
@@ -13472,11 +13626,11 @@ function removeCaliberCursorRules() {
|
|
|
13472
13626
|
function removeBuiltinSkills() {
|
|
13473
13627
|
const removed = [];
|
|
13474
13628
|
for (const skillsDir of SKILL_DIRS) {
|
|
13475
|
-
if (!
|
|
13629
|
+
if (!fs50.existsSync(skillsDir)) continue;
|
|
13476
13630
|
for (const name of BUILTIN_SKILL_NAMES) {
|
|
13477
|
-
const skillDir =
|
|
13478
|
-
if (
|
|
13479
|
-
|
|
13631
|
+
const skillDir = path41.join(skillsDir, name);
|
|
13632
|
+
if (fs50.existsSync(skillDir)) {
|
|
13633
|
+
fs50.rmSync(skillDir, { recursive: true });
|
|
13480
13634
|
removed.push(skillDir);
|
|
13481
13635
|
}
|
|
13482
13636
|
}
|
|
@@ -13486,15 +13640,15 @@ function removeBuiltinSkills() {
|
|
|
13486
13640
|
function stripManagedBlocksFromFiles() {
|
|
13487
13641
|
const modified = [];
|
|
13488
13642
|
for (const filePath of MANAGED_DOC_FILES) {
|
|
13489
|
-
if (!
|
|
13490
|
-
const original =
|
|
13643
|
+
if (!fs50.existsSync(filePath)) continue;
|
|
13644
|
+
const original = fs50.readFileSync(filePath, "utf-8");
|
|
13491
13645
|
const stripped = stripManagedBlocks(original);
|
|
13492
13646
|
if (stripped !== original) {
|
|
13493
13647
|
const trimmed = stripped.trim();
|
|
13494
13648
|
if (!trimmed || /^#\s*\S*$/.test(trimmed)) {
|
|
13495
|
-
|
|
13649
|
+
fs50.unlinkSync(filePath);
|
|
13496
13650
|
} else {
|
|
13497
|
-
|
|
13651
|
+
fs50.writeFileSync(filePath, stripped);
|
|
13498
13652
|
}
|
|
13499
13653
|
modified.push(filePath);
|
|
13500
13654
|
}
|
|
@@ -13502,8 +13656,8 @@ function stripManagedBlocksFromFiles() {
|
|
|
13502
13656
|
return modified;
|
|
13503
13657
|
}
|
|
13504
13658
|
function removeDirectory(dir) {
|
|
13505
|
-
if (!
|
|
13506
|
-
|
|
13659
|
+
if (!fs50.existsSync(dir)) return false;
|
|
13660
|
+
fs50.rmSync(dir, { recursive: true });
|
|
13507
13661
|
return true;
|
|
13508
13662
|
}
|
|
13509
13663
|
async function uninstallCommand(options) {
|
|
@@ -13560,8 +13714,8 @@ async function uninstallCommand(options) {
|
|
|
13560
13714
|
console.log(` ${chalk28.red("\u2717")} ${skill}/`);
|
|
13561
13715
|
}
|
|
13562
13716
|
if (removedSkills.length > 0) actions.push("builtin skills");
|
|
13563
|
-
if (
|
|
13564
|
-
|
|
13717
|
+
if (fs50.existsSync("CALIBER_LEARNINGS.md")) {
|
|
13718
|
+
fs50.unlinkSync("CALIBER_LEARNINGS.md");
|
|
13565
13719
|
console.log(` ${chalk28.red("\u2717")} CALIBER_LEARNINGS.md`);
|
|
13566
13720
|
actions.push("learnings file");
|
|
13567
13721
|
}
|
|
@@ -13575,18 +13729,18 @@ async function uninstallCommand(options) {
|
|
|
13575
13729
|
}
|
|
13576
13730
|
trackUninstallExecuted();
|
|
13577
13731
|
const configPath = getConfigFilePath();
|
|
13578
|
-
if (
|
|
13732
|
+
if (fs50.existsSync(configPath)) {
|
|
13579
13733
|
console.log("");
|
|
13580
13734
|
const removeConfig = options.force || await confirm3({
|
|
13581
13735
|
message: `Remove global config (~/.caliber/config.json)? This affects all projects.`
|
|
13582
13736
|
});
|
|
13583
13737
|
if (removeConfig) {
|
|
13584
|
-
|
|
13738
|
+
fs50.unlinkSync(configPath);
|
|
13585
13739
|
console.log(` ${chalk28.red("\u2717")} ${configPath}`);
|
|
13586
|
-
const configDir =
|
|
13740
|
+
const configDir = path41.dirname(configPath);
|
|
13587
13741
|
try {
|
|
13588
|
-
const remaining =
|
|
13589
|
-
if (remaining.length === 0)
|
|
13742
|
+
const remaining = fs50.readdirSync(configDir);
|
|
13743
|
+
if (remaining.length === 0) fs50.rmdirSync(configDir);
|
|
13590
13744
|
} catch {
|
|
13591
13745
|
}
|
|
13592
13746
|
}
|
|
@@ -13597,8 +13751,8 @@ async function uninstallCommand(options) {
|
|
|
13597
13751
|
}
|
|
13598
13752
|
|
|
13599
13753
|
// src/cli.ts
|
|
13600
|
-
var __dirname =
|
|
13601
|
-
var pkg = JSON.parse(
|
|
13754
|
+
var __dirname = path42.dirname(fileURLToPath(import.meta.url));
|
|
13755
|
+
var pkg = JSON.parse(fs51.readFileSync(path42.resolve(__dirname, "..", "package.json"), "utf-8"));
|
|
13602
13756
|
var program = new Command();
|
|
13603
13757
|
var displayVersion = process.env.CALIBER_LOCAL ? `${pkg.version}-local` : pkg.version;
|
|
13604
13758
|
program.name(process.env.CALIBER_LOCAL ? "caloc" : "caliber").description("AI context infrastructure for coding agents").version(displayVersion).option("--no-traces", "Disable anonymous telemetry for this run");
|
|
@@ -13709,15 +13863,15 @@ learn.command("delete <index>").description("Delete a learning by its index numb
|
|
|
13709
13863
|
learn.command("add <content>").description("Add a learning directly (used by agent skills)").option("--personal", "Save as a personal learning instead of project-level").action(tracked("learn:add", learnAddCommand));
|
|
13710
13864
|
|
|
13711
13865
|
// src/utils/version-check.ts
|
|
13712
|
-
import
|
|
13713
|
-
import
|
|
13866
|
+
import fs52 from "fs";
|
|
13867
|
+
import path43 from "path";
|
|
13714
13868
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
13715
13869
|
import { execSync as execSync16, execFileSync as execFileSync3 } from "child_process";
|
|
13716
13870
|
import chalk29 from "chalk";
|
|
13717
13871
|
import ora8 from "ora";
|
|
13718
13872
|
import confirm4 from "@inquirer/confirm";
|
|
13719
|
-
var __dirname_vc =
|
|
13720
|
-
var pkg2 = JSON.parse(
|
|
13873
|
+
var __dirname_vc = path43.dirname(fileURLToPath2(import.meta.url));
|
|
13874
|
+
var pkg2 = JSON.parse(fs52.readFileSync(path43.resolve(__dirname_vc, "..", "package.json"), "utf-8"));
|
|
13721
13875
|
function getChannel(version) {
|
|
13722
13876
|
const match = version.match(/-(dev|next)\./);
|
|
13723
13877
|
return match ? match[1] : "latest";
|
|
@@ -13744,8 +13898,8 @@ function getInstalledVersion() {
|
|
|
13744
13898
|
encoding: "utf-8",
|
|
13745
13899
|
stdio: ["pipe", "pipe", "pipe"]
|
|
13746
13900
|
}).trim();
|
|
13747
|
-
const pkgPath =
|
|
13748
|
-
return JSON.parse(
|
|
13901
|
+
const pkgPath = path43.join(globalRoot, "@rely-ai", "caliber", "package.json");
|
|
13902
|
+
return JSON.parse(fs52.readFileSync(pkgPath, "utf-8")).version;
|
|
13749
13903
|
} catch {
|
|
13750
13904
|
return null;
|
|
13751
13905
|
}
|
package/package.json
CHANGED