@rely-ai/caliber 1.7.4 → 1.7.5
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 +196 -159
- package/package.json +1 -1
package/dist/bin.js
CHANGED
|
@@ -165,7 +165,7 @@ var init_constants = __esm({
|
|
|
165
165
|
|
|
166
166
|
// src/cli.ts
|
|
167
167
|
import { Command } from "commander";
|
|
168
|
-
import
|
|
168
|
+
import fs29 from "fs";
|
|
169
169
|
import path22 from "path";
|
|
170
170
|
import { fileURLToPath } from "url";
|
|
171
171
|
|
|
@@ -175,7 +175,7 @@ import ora2 from "ora";
|
|
|
175
175
|
import readline3 from "readline";
|
|
176
176
|
import select5 from "@inquirer/select";
|
|
177
177
|
import checkbox from "@inquirer/checkbox";
|
|
178
|
-
import
|
|
178
|
+
import fs23 from "fs";
|
|
179
179
|
|
|
180
180
|
// src/fingerprint/index.ts
|
|
181
181
|
import fs6 from "fs";
|
|
@@ -2670,28 +2670,64 @@ ${agentRefs.join(" ")}
|
|
|
2670
2670
|
}
|
|
2671
2671
|
|
|
2672
2672
|
// src/lib/hooks.ts
|
|
2673
|
-
import
|
|
2673
|
+
import fs17 from "fs";
|
|
2674
2674
|
import path12 from "path";
|
|
2675
|
+
import { execSync as execSync6 } from "child_process";
|
|
2676
|
+
|
|
2677
|
+
// src/lib/resolve-caliber.ts
|
|
2678
|
+
import fs16 from "fs";
|
|
2675
2679
|
import { execSync as execSync5 } from "child_process";
|
|
2680
|
+
var _resolved = null;
|
|
2681
|
+
function resolveCaliber() {
|
|
2682
|
+
if (_resolved) return _resolved;
|
|
2683
|
+
try {
|
|
2684
|
+
const found = execSync5("which caliber", {
|
|
2685
|
+
encoding: "utf-8",
|
|
2686
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
2687
|
+
}).trim();
|
|
2688
|
+
if (found) {
|
|
2689
|
+
_resolved = found;
|
|
2690
|
+
return _resolved;
|
|
2691
|
+
}
|
|
2692
|
+
} catch {
|
|
2693
|
+
}
|
|
2694
|
+
const binPath = process.argv[1];
|
|
2695
|
+
if (binPath && fs16.existsSync(binPath)) {
|
|
2696
|
+
_resolved = binPath;
|
|
2697
|
+
return _resolved;
|
|
2698
|
+
}
|
|
2699
|
+
_resolved = "caliber";
|
|
2700
|
+
return _resolved;
|
|
2701
|
+
}
|
|
2702
|
+
function isCaliberCommand(command, subcommandTail) {
|
|
2703
|
+
if (command === `caliber ${subcommandTail}`) return true;
|
|
2704
|
+
if (command.endsWith(`/caliber ${subcommandTail}`)) return true;
|
|
2705
|
+
return false;
|
|
2706
|
+
}
|
|
2707
|
+
|
|
2708
|
+
// src/lib/hooks.ts
|
|
2676
2709
|
var SETTINGS_PATH = path12.join(".claude", "settings.json");
|
|
2677
|
-
var
|
|
2710
|
+
var REFRESH_TAIL = "refresh --quiet";
|
|
2678
2711
|
var HOOK_DESCRIPTION = "Caliber: auto-refreshing docs based on code changes";
|
|
2712
|
+
function getHookCommand() {
|
|
2713
|
+
return `${resolveCaliber()} ${REFRESH_TAIL}`;
|
|
2714
|
+
}
|
|
2679
2715
|
function readSettings() {
|
|
2680
|
-
if (!
|
|
2716
|
+
if (!fs17.existsSync(SETTINGS_PATH)) return {};
|
|
2681
2717
|
try {
|
|
2682
|
-
return JSON.parse(
|
|
2718
|
+
return JSON.parse(fs17.readFileSync(SETTINGS_PATH, "utf-8"));
|
|
2683
2719
|
} catch {
|
|
2684
2720
|
return {};
|
|
2685
2721
|
}
|
|
2686
2722
|
}
|
|
2687
2723
|
function writeSettings(settings) {
|
|
2688
2724
|
const dir = path12.dirname(SETTINGS_PATH);
|
|
2689
|
-
if (!
|
|
2690
|
-
|
|
2725
|
+
if (!fs17.existsSync(dir)) fs17.mkdirSync(dir, { recursive: true });
|
|
2726
|
+
fs17.writeFileSync(SETTINGS_PATH, JSON.stringify(settings, null, 2));
|
|
2691
2727
|
}
|
|
2692
2728
|
function findHookIndex(sessionEnd) {
|
|
2693
2729
|
return sessionEnd.findIndex(
|
|
2694
|
-
(entry) => entry.hooks?.some((h) => h.command
|
|
2730
|
+
(entry) => entry.hooks?.some((h) => isCaliberCommand(h.command, REFRESH_TAIL))
|
|
2695
2731
|
);
|
|
2696
2732
|
}
|
|
2697
2733
|
function isHookInstalled() {
|
|
@@ -2709,7 +2745,7 @@ function installHook() {
|
|
|
2709
2745
|
}
|
|
2710
2746
|
settings.hooks.SessionEnd.push({
|
|
2711
2747
|
matcher: "",
|
|
2712
|
-
hooks: [{ type: "command", command:
|
|
2748
|
+
hooks: [{ type: "command", command: getHookCommand(), description: HOOK_DESCRIPTION }]
|
|
2713
2749
|
});
|
|
2714
2750
|
writeSettings(settings);
|
|
2715
2751
|
return { installed: true, alreadyInstalled: false };
|
|
@@ -2736,16 +2772,19 @@ function removeHook() {
|
|
|
2736
2772
|
}
|
|
2737
2773
|
var PRECOMMIT_START = "# caliber:pre-commit:start";
|
|
2738
2774
|
var PRECOMMIT_END = "# caliber:pre-commit:end";
|
|
2739
|
-
|
|
2740
|
-
|
|
2775
|
+
function getPrecommitBlock() {
|
|
2776
|
+
const bin = resolveCaliber();
|
|
2777
|
+
return `${PRECOMMIT_START}
|
|
2778
|
+
if [ -x "${bin}" ] || command -v "${bin}" >/dev/null 2>&1; then
|
|
2741
2779
|
echo "\\033[2mcaliber: refreshing docs...\\033[0m"
|
|
2742
|
-
|
|
2780
|
+
"${bin}" refresh 2>/dev/null || true
|
|
2743
2781
|
git diff --name-only -- CLAUDE.md .claude/ .cursor/ AGENTS.md 2>/dev/null | xargs git add 2>/dev/null || true
|
|
2744
2782
|
fi
|
|
2745
2783
|
${PRECOMMIT_END}`;
|
|
2784
|
+
}
|
|
2746
2785
|
function getGitHooksDir() {
|
|
2747
2786
|
try {
|
|
2748
|
-
const gitDir =
|
|
2787
|
+
const gitDir = execSync6("git rev-parse --git-dir", { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
|
|
2749
2788
|
return path12.join(gitDir, "hooks");
|
|
2750
2789
|
} catch {
|
|
2751
2790
|
return null;
|
|
@@ -2757,8 +2796,8 @@ function getPreCommitPath() {
|
|
|
2757
2796
|
}
|
|
2758
2797
|
function isPreCommitHookInstalled() {
|
|
2759
2798
|
const hookPath = getPreCommitPath();
|
|
2760
|
-
if (!hookPath || !
|
|
2761
|
-
const content =
|
|
2799
|
+
if (!hookPath || !fs17.existsSync(hookPath)) return false;
|
|
2800
|
+
const content = fs17.readFileSync(hookPath, "utf-8");
|
|
2762
2801
|
return content.includes(PRECOMMIT_START);
|
|
2763
2802
|
}
|
|
2764
2803
|
function installPreCommitHook() {
|
|
@@ -2768,81 +2807,78 @@ function installPreCommitHook() {
|
|
|
2768
2807
|
const hookPath = getPreCommitPath();
|
|
2769
2808
|
if (!hookPath) return { installed: false, alreadyInstalled: false };
|
|
2770
2809
|
const hooksDir = path12.dirname(hookPath);
|
|
2771
|
-
if (!
|
|
2810
|
+
if (!fs17.existsSync(hooksDir)) fs17.mkdirSync(hooksDir, { recursive: true });
|
|
2772
2811
|
let content = "";
|
|
2773
|
-
if (
|
|
2774
|
-
content =
|
|
2812
|
+
if (fs17.existsSync(hookPath)) {
|
|
2813
|
+
content = fs17.readFileSync(hookPath, "utf-8");
|
|
2775
2814
|
if (!content.endsWith("\n")) content += "\n";
|
|
2776
|
-
content += "\n" +
|
|
2815
|
+
content += "\n" + getPrecommitBlock() + "\n";
|
|
2777
2816
|
} else {
|
|
2778
|
-
content = "#!/bin/sh\n\n" +
|
|
2817
|
+
content = "#!/bin/sh\n\n" + getPrecommitBlock() + "\n";
|
|
2779
2818
|
}
|
|
2780
|
-
|
|
2781
|
-
|
|
2819
|
+
fs17.writeFileSync(hookPath, content);
|
|
2820
|
+
fs17.chmodSync(hookPath, 493);
|
|
2782
2821
|
return { installed: true, alreadyInstalled: false };
|
|
2783
2822
|
}
|
|
2784
2823
|
function removePreCommitHook() {
|
|
2785
2824
|
const hookPath = getPreCommitPath();
|
|
2786
|
-
if (!hookPath || !
|
|
2825
|
+
if (!hookPath || !fs17.existsSync(hookPath)) {
|
|
2787
2826
|
return { removed: false, notFound: true };
|
|
2788
2827
|
}
|
|
2789
|
-
let content =
|
|
2828
|
+
let content = fs17.readFileSync(hookPath, "utf-8");
|
|
2790
2829
|
if (!content.includes(PRECOMMIT_START)) {
|
|
2791
2830
|
return { removed: false, notFound: true };
|
|
2792
2831
|
}
|
|
2793
2832
|
const regex = new RegExp(`\\n?${PRECOMMIT_START}[\\s\\S]*?${PRECOMMIT_END}\\n?`);
|
|
2794
2833
|
content = content.replace(regex, "\n");
|
|
2795
2834
|
if (content.trim() === "#!/bin/sh" || content.trim() === "") {
|
|
2796
|
-
|
|
2835
|
+
fs17.unlinkSync(hookPath);
|
|
2797
2836
|
} else {
|
|
2798
|
-
|
|
2837
|
+
fs17.writeFileSync(hookPath, content);
|
|
2799
2838
|
}
|
|
2800
2839
|
return { removed: true, notFound: false };
|
|
2801
2840
|
}
|
|
2802
2841
|
|
|
2803
2842
|
// src/lib/learning-hooks.ts
|
|
2804
|
-
import
|
|
2843
|
+
import fs18 from "fs";
|
|
2805
2844
|
import path13 from "path";
|
|
2806
2845
|
var SETTINGS_PATH2 = path13.join(".claude", "settings.json");
|
|
2807
|
-
var
|
|
2808
|
-
{
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
description: "Caliber: recording tool usage for session learning"
|
|
2812
|
-
},
|
|
2813
|
-
{
|
|
2814
|
-
event: "PostToolUseFailure",
|
|
2815
|
-
command: "caliber learn observe --failure",
|
|
2816
|
-
description: "Caliber: recording tool failure for session learning"
|
|
2817
|
-
},
|
|
2818
|
-
{
|
|
2819
|
-
event: "SessionEnd",
|
|
2820
|
-
command: "caliber learn finalize",
|
|
2821
|
-
description: "Caliber: finalizing session learnings"
|
|
2822
|
-
}
|
|
2846
|
+
var HOOK_TAILS = [
|
|
2847
|
+
{ event: "PostToolUse", tail: "learn observe", description: "Caliber: recording tool usage for session learning" },
|
|
2848
|
+
{ event: "PostToolUseFailure", tail: "learn observe --failure", description: "Caliber: recording tool failure for session learning" },
|
|
2849
|
+
{ event: "SessionEnd", tail: "learn finalize", description: "Caliber: finalizing session learnings" }
|
|
2823
2850
|
];
|
|
2851
|
+
function getHookConfigs() {
|
|
2852
|
+
const bin = resolveCaliber();
|
|
2853
|
+
return HOOK_TAILS.map(({ event, tail, description }) => ({
|
|
2854
|
+
event,
|
|
2855
|
+
command: `${bin} ${tail}`,
|
|
2856
|
+
tail,
|
|
2857
|
+
description
|
|
2858
|
+
}));
|
|
2859
|
+
}
|
|
2824
2860
|
function readSettings2() {
|
|
2825
|
-
if (!
|
|
2861
|
+
if (!fs18.existsSync(SETTINGS_PATH2)) return {};
|
|
2826
2862
|
try {
|
|
2827
|
-
return JSON.parse(
|
|
2863
|
+
return JSON.parse(fs18.readFileSync(SETTINGS_PATH2, "utf-8"));
|
|
2828
2864
|
} catch {
|
|
2829
2865
|
return {};
|
|
2830
2866
|
}
|
|
2831
2867
|
}
|
|
2832
2868
|
function writeSettings2(settings) {
|
|
2833
2869
|
const dir = path13.dirname(SETTINGS_PATH2);
|
|
2834
|
-
if (!
|
|
2835
|
-
|
|
2870
|
+
if (!fs18.existsSync(dir)) fs18.mkdirSync(dir, { recursive: true });
|
|
2871
|
+
fs18.writeFileSync(SETTINGS_PATH2, JSON.stringify(settings, null, 2));
|
|
2836
2872
|
}
|
|
2837
|
-
function hasLearningHook(matchers,
|
|
2838
|
-
return matchers.some((entry) => entry.hooks?.some((h) => h.command
|
|
2873
|
+
function hasLearningHook(matchers, tail) {
|
|
2874
|
+
return matchers.some((entry) => entry.hooks?.some((h) => isCaliberCommand(h.command, tail)));
|
|
2839
2875
|
}
|
|
2840
2876
|
function areLearningHooksInstalled() {
|
|
2841
2877
|
const settings = readSettings2();
|
|
2842
2878
|
if (!settings.hooks) return false;
|
|
2843
|
-
return
|
|
2879
|
+
return HOOK_TAILS.every((cfg) => {
|
|
2844
2880
|
const matchers = settings.hooks[cfg.event];
|
|
2845
|
-
return Array.isArray(matchers) && hasLearningHook(matchers, cfg.
|
|
2881
|
+
return Array.isArray(matchers) && hasLearningHook(matchers, cfg.tail);
|
|
2846
2882
|
});
|
|
2847
2883
|
}
|
|
2848
2884
|
function installLearningHooks() {
|
|
@@ -2851,11 +2887,12 @@ function installLearningHooks() {
|
|
|
2851
2887
|
}
|
|
2852
2888
|
const settings = readSettings2();
|
|
2853
2889
|
if (!settings.hooks) settings.hooks = {};
|
|
2854
|
-
|
|
2890
|
+
const configs = getHookConfigs();
|
|
2891
|
+
for (const cfg of configs) {
|
|
2855
2892
|
if (!Array.isArray(settings.hooks[cfg.event])) {
|
|
2856
2893
|
settings.hooks[cfg.event] = [];
|
|
2857
2894
|
}
|
|
2858
|
-
if (!hasLearningHook(settings.hooks[cfg.event], cfg.
|
|
2895
|
+
if (!hasLearningHook(settings.hooks[cfg.event], cfg.tail)) {
|
|
2859
2896
|
settings.hooks[cfg.event].push({
|
|
2860
2897
|
matcher: "",
|
|
2861
2898
|
hooks: [{ type: "command", command: cfg.command, description: cfg.description }]
|
|
@@ -2869,10 +2906,10 @@ function removeLearningHooks() {
|
|
|
2869
2906
|
const settings = readSettings2();
|
|
2870
2907
|
if (!settings.hooks) return { removed: false, notFound: true };
|
|
2871
2908
|
let removedAny = false;
|
|
2872
|
-
for (const cfg of
|
|
2909
|
+
for (const cfg of HOOK_TAILS) {
|
|
2873
2910
|
const matchers = settings.hooks[cfg.event];
|
|
2874
2911
|
if (!Array.isArray(matchers)) continue;
|
|
2875
|
-
const idx = matchers.findIndex((entry) => entry.hooks?.some((h) => h.command
|
|
2912
|
+
const idx = matchers.findIndex((entry) => entry.hooks?.some((h) => isCaliberCommand(h.command, cfg.tail)));
|
|
2876
2913
|
if (idx !== -1) {
|
|
2877
2914
|
matchers.splice(idx, 1);
|
|
2878
2915
|
removedAny = true;
|
|
@@ -2889,9 +2926,9 @@ function removeLearningHooks() {
|
|
|
2889
2926
|
|
|
2890
2927
|
// src/lib/state.ts
|
|
2891
2928
|
init_constants();
|
|
2892
|
-
import
|
|
2929
|
+
import fs19 from "fs";
|
|
2893
2930
|
import path14 from "path";
|
|
2894
|
-
import { execSync as
|
|
2931
|
+
import { execSync as execSync7 } from "child_process";
|
|
2895
2932
|
var STATE_FILE = path14.join(CALIBER_DIR, ".caliber-state.json");
|
|
2896
2933
|
function normalizeTargetAgent(value) {
|
|
2897
2934
|
if (Array.isArray(value)) return value;
|
|
@@ -2903,8 +2940,8 @@ function normalizeTargetAgent(value) {
|
|
|
2903
2940
|
}
|
|
2904
2941
|
function readState() {
|
|
2905
2942
|
try {
|
|
2906
|
-
if (!
|
|
2907
|
-
const raw = JSON.parse(
|
|
2943
|
+
if (!fs19.existsSync(STATE_FILE)) return null;
|
|
2944
|
+
const raw = JSON.parse(fs19.readFileSync(STATE_FILE, "utf-8"));
|
|
2908
2945
|
if (raw.targetAgent) raw.targetAgent = normalizeTargetAgent(raw.targetAgent);
|
|
2909
2946
|
return raw;
|
|
2910
2947
|
} catch {
|
|
@@ -2912,14 +2949,14 @@ function readState() {
|
|
|
2912
2949
|
}
|
|
2913
2950
|
}
|
|
2914
2951
|
function writeState(state) {
|
|
2915
|
-
if (!
|
|
2916
|
-
|
|
2952
|
+
if (!fs19.existsSync(CALIBER_DIR)) {
|
|
2953
|
+
fs19.mkdirSync(CALIBER_DIR, { recursive: true });
|
|
2917
2954
|
}
|
|
2918
|
-
|
|
2955
|
+
fs19.writeFileSync(STATE_FILE, JSON.stringify(state, null, 2));
|
|
2919
2956
|
}
|
|
2920
2957
|
function getCurrentHeadSha() {
|
|
2921
2958
|
try {
|
|
2922
|
-
return
|
|
2959
|
+
return execSync7("git rev-parse HEAD", {
|
|
2923
2960
|
encoding: "utf-8",
|
|
2924
2961
|
stdio: ["pipe", "pipe", "pipe"]
|
|
2925
2962
|
}).trim();
|
|
@@ -4041,7 +4078,7 @@ function checkFreshness(dir) {
|
|
|
4041
4078
|
|
|
4042
4079
|
// src/scoring/checks/bonus.ts
|
|
4043
4080
|
import { existsSync as existsSync7, readFileSync as readFileSync6, readdirSync as readdirSync4 } from "fs";
|
|
4044
|
-
import { execSync as
|
|
4081
|
+
import { execSync as execSync8 } from "child_process";
|
|
4045
4082
|
import { join as join6 } from "path";
|
|
4046
4083
|
function readFileOrNull5(path24) {
|
|
4047
4084
|
try {
|
|
@@ -4052,7 +4089,7 @@ function readFileOrNull5(path24) {
|
|
|
4052
4089
|
}
|
|
4053
4090
|
function hasPreCommitHook(dir) {
|
|
4054
4091
|
try {
|
|
4055
|
-
const gitDir =
|
|
4092
|
+
const gitDir = execSync8("git rev-parse --git-dir", { cwd: dir, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
|
|
4056
4093
|
const hookPath = join6(gitDir, "hooks", "pre-commit");
|
|
4057
4094
|
const content = readFileOrNull5(hookPath);
|
|
4058
4095
|
return content ? content.includes("caliber") : false;
|
|
@@ -4140,22 +4177,22 @@ function checkBonus(dir) {
|
|
|
4140
4177
|
|
|
4141
4178
|
// src/scoring/dismissed.ts
|
|
4142
4179
|
init_constants();
|
|
4143
|
-
import
|
|
4180
|
+
import fs20 from "fs";
|
|
4144
4181
|
import path15 from "path";
|
|
4145
4182
|
var DISMISSED_FILE = path15.join(CALIBER_DIR, "dismissed-checks.json");
|
|
4146
4183
|
function readDismissedChecks() {
|
|
4147
4184
|
try {
|
|
4148
|
-
if (!
|
|
4149
|
-
return JSON.parse(
|
|
4185
|
+
if (!fs20.existsSync(DISMISSED_FILE)) return [];
|
|
4186
|
+
return JSON.parse(fs20.readFileSync(DISMISSED_FILE, "utf-8"));
|
|
4150
4187
|
} catch {
|
|
4151
4188
|
return [];
|
|
4152
4189
|
}
|
|
4153
4190
|
}
|
|
4154
4191
|
function writeDismissedChecks(checks) {
|
|
4155
|
-
if (!
|
|
4156
|
-
|
|
4192
|
+
if (!fs20.existsSync(CALIBER_DIR)) {
|
|
4193
|
+
fs20.mkdirSync(CALIBER_DIR, { recursive: true });
|
|
4157
4194
|
}
|
|
4158
|
-
|
|
4195
|
+
fs20.writeFileSync(DISMISSED_FILE, JSON.stringify(checks, null, 2) + "\n");
|
|
4159
4196
|
}
|
|
4160
4197
|
function getDismissedIds() {
|
|
4161
4198
|
return new Set(readDismissedChecks().map((c) => c.id));
|
|
@@ -4350,13 +4387,13 @@ import { mkdirSync, readFileSync as readFileSync7, readdirSync as readdirSync5,
|
|
|
4350
4387
|
import { join as join8, dirname as dirname2 } from "path";
|
|
4351
4388
|
|
|
4352
4389
|
// src/scanner/index.ts
|
|
4353
|
-
import
|
|
4390
|
+
import fs21 from "fs";
|
|
4354
4391
|
import path16 from "path";
|
|
4355
4392
|
import crypto2 from "crypto";
|
|
4356
4393
|
function scanLocalState(dir) {
|
|
4357
4394
|
const items = [];
|
|
4358
4395
|
const claudeMdPath = path16.join(dir, "CLAUDE.md");
|
|
4359
|
-
if (
|
|
4396
|
+
if (fs21.existsSync(claudeMdPath)) {
|
|
4360
4397
|
items.push({
|
|
4361
4398
|
type: "rule",
|
|
4362
4399
|
platform: "claude",
|
|
@@ -4366,8 +4403,8 @@ function scanLocalState(dir) {
|
|
|
4366
4403
|
});
|
|
4367
4404
|
}
|
|
4368
4405
|
const skillsDir = path16.join(dir, ".claude", "skills");
|
|
4369
|
-
if (
|
|
4370
|
-
for (const file of
|
|
4406
|
+
if (fs21.existsSync(skillsDir)) {
|
|
4407
|
+
for (const file of fs21.readdirSync(skillsDir).filter((f) => f.endsWith(".md"))) {
|
|
4371
4408
|
const filePath = path16.join(skillsDir, file);
|
|
4372
4409
|
items.push({
|
|
4373
4410
|
type: "skill",
|
|
@@ -4379,9 +4416,9 @@ function scanLocalState(dir) {
|
|
|
4379
4416
|
}
|
|
4380
4417
|
}
|
|
4381
4418
|
const mcpJsonPath = path16.join(dir, ".mcp.json");
|
|
4382
|
-
if (
|
|
4419
|
+
if (fs21.existsSync(mcpJsonPath)) {
|
|
4383
4420
|
try {
|
|
4384
|
-
const mcpJson = JSON.parse(
|
|
4421
|
+
const mcpJson = JSON.parse(fs21.readFileSync(mcpJsonPath, "utf-8"));
|
|
4385
4422
|
if (mcpJson.mcpServers) {
|
|
4386
4423
|
for (const name of Object.keys(mcpJson.mcpServers)) {
|
|
4387
4424
|
items.push({
|
|
@@ -4397,7 +4434,7 @@ function scanLocalState(dir) {
|
|
|
4397
4434
|
}
|
|
4398
4435
|
}
|
|
4399
4436
|
const agentsMdPath = path16.join(dir, "AGENTS.md");
|
|
4400
|
-
if (
|
|
4437
|
+
if (fs21.existsSync(agentsMdPath)) {
|
|
4401
4438
|
items.push({
|
|
4402
4439
|
type: "rule",
|
|
4403
4440
|
platform: "codex",
|
|
@@ -4407,11 +4444,11 @@ function scanLocalState(dir) {
|
|
|
4407
4444
|
});
|
|
4408
4445
|
}
|
|
4409
4446
|
const codexSkillsDir = path16.join(dir, ".agents", "skills");
|
|
4410
|
-
if (
|
|
4447
|
+
if (fs21.existsSync(codexSkillsDir)) {
|
|
4411
4448
|
try {
|
|
4412
|
-
for (const name of
|
|
4449
|
+
for (const name of fs21.readdirSync(codexSkillsDir)) {
|
|
4413
4450
|
const skillFile = path16.join(codexSkillsDir, name, "SKILL.md");
|
|
4414
|
-
if (
|
|
4451
|
+
if (fs21.existsSync(skillFile)) {
|
|
4415
4452
|
items.push({
|
|
4416
4453
|
type: "skill",
|
|
4417
4454
|
platform: "codex",
|
|
@@ -4425,7 +4462,7 @@ function scanLocalState(dir) {
|
|
|
4425
4462
|
}
|
|
4426
4463
|
}
|
|
4427
4464
|
const cursorrulesPath = path16.join(dir, ".cursorrules");
|
|
4428
|
-
if (
|
|
4465
|
+
if (fs21.existsSync(cursorrulesPath)) {
|
|
4429
4466
|
items.push({
|
|
4430
4467
|
type: "rule",
|
|
4431
4468
|
platform: "cursor",
|
|
@@ -4435,8 +4472,8 @@ function scanLocalState(dir) {
|
|
|
4435
4472
|
});
|
|
4436
4473
|
}
|
|
4437
4474
|
const cursorRulesDir = path16.join(dir, ".cursor", "rules");
|
|
4438
|
-
if (
|
|
4439
|
-
for (const file of
|
|
4475
|
+
if (fs21.existsSync(cursorRulesDir)) {
|
|
4476
|
+
for (const file of fs21.readdirSync(cursorRulesDir).filter((f) => f.endsWith(".mdc"))) {
|
|
4440
4477
|
const filePath = path16.join(cursorRulesDir, file);
|
|
4441
4478
|
items.push({
|
|
4442
4479
|
type: "rule",
|
|
@@ -4448,11 +4485,11 @@ function scanLocalState(dir) {
|
|
|
4448
4485
|
}
|
|
4449
4486
|
}
|
|
4450
4487
|
const cursorSkillsDir = path16.join(dir, ".cursor", "skills");
|
|
4451
|
-
if (
|
|
4488
|
+
if (fs21.existsSync(cursorSkillsDir)) {
|
|
4452
4489
|
try {
|
|
4453
|
-
for (const name of
|
|
4490
|
+
for (const name of fs21.readdirSync(cursorSkillsDir)) {
|
|
4454
4491
|
const skillFile = path16.join(cursorSkillsDir, name, "SKILL.md");
|
|
4455
|
-
if (
|
|
4492
|
+
if (fs21.existsSync(skillFile)) {
|
|
4456
4493
|
items.push({
|
|
4457
4494
|
type: "skill",
|
|
4458
4495
|
platform: "cursor",
|
|
@@ -4466,9 +4503,9 @@ function scanLocalState(dir) {
|
|
|
4466
4503
|
}
|
|
4467
4504
|
}
|
|
4468
4505
|
const cursorMcpPath = path16.join(dir, ".cursor", "mcp.json");
|
|
4469
|
-
if (
|
|
4506
|
+
if (fs21.existsSync(cursorMcpPath)) {
|
|
4470
4507
|
try {
|
|
4471
|
-
const mcpJson = JSON.parse(
|
|
4508
|
+
const mcpJson = JSON.parse(fs21.readFileSync(cursorMcpPath, "utf-8"));
|
|
4472
4509
|
if (mcpJson.mcpServers) {
|
|
4473
4510
|
for (const name of Object.keys(mcpJson.mcpServers)) {
|
|
4474
4511
|
items.push({
|
|
@@ -4486,7 +4523,7 @@ function scanLocalState(dir) {
|
|
|
4486
4523
|
return items;
|
|
4487
4524
|
}
|
|
4488
4525
|
function hashFile(filePath) {
|
|
4489
|
-
const text =
|
|
4526
|
+
const text = fs21.readFileSync(filePath, "utf-8");
|
|
4490
4527
|
return crypto2.createHash("sha256").update(JSON.stringify({ text })).digest("hex");
|
|
4491
4528
|
}
|
|
4492
4529
|
function hashJson(obj) {
|
|
@@ -4501,27 +4538,27 @@ import { PostHog } from "posthog-node";
|
|
|
4501
4538
|
import chalk6 from "chalk";
|
|
4502
4539
|
|
|
4503
4540
|
// src/telemetry/config.ts
|
|
4504
|
-
import
|
|
4541
|
+
import fs22 from "fs";
|
|
4505
4542
|
import path17 from "path";
|
|
4506
4543
|
import os3 from "os";
|
|
4507
4544
|
import crypto3 from "crypto";
|
|
4508
|
-
import { execSync as
|
|
4545
|
+
import { execSync as execSync9 } from "child_process";
|
|
4509
4546
|
var CONFIG_DIR2 = path17.join(os3.homedir(), ".caliber");
|
|
4510
4547
|
var CONFIG_FILE2 = path17.join(CONFIG_DIR2, "config.json");
|
|
4511
4548
|
var runtimeDisabled = false;
|
|
4512
4549
|
function readConfig() {
|
|
4513
4550
|
try {
|
|
4514
|
-
if (!
|
|
4515
|
-
return JSON.parse(
|
|
4551
|
+
if (!fs22.existsSync(CONFIG_FILE2)) return {};
|
|
4552
|
+
return JSON.parse(fs22.readFileSync(CONFIG_FILE2, "utf-8"));
|
|
4516
4553
|
} catch {
|
|
4517
4554
|
return {};
|
|
4518
4555
|
}
|
|
4519
4556
|
}
|
|
4520
4557
|
function writeConfig(config) {
|
|
4521
|
-
if (!
|
|
4522
|
-
|
|
4558
|
+
if (!fs22.existsSync(CONFIG_DIR2)) {
|
|
4559
|
+
fs22.mkdirSync(CONFIG_DIR2, { recursive: true });
|
|
4523
4560
|
}
|
|
4524
|
-
|
|
4561
|
+
fs22.writeFileSync(CONFIG_FILE2, JSON.stringify(config, null, 2) + "\n", { mode: 384 });
|
|
4525
4562
|
}
|
|
4526
4563
|
function getMachineId() {
|
|
4527
4564
|
const config = readConfig();
|
|
@@ -4532,7 +4569,7 @@ function getMachineId() {
|
|
|
4532
4569
|
}
|
|
4533
4570
|
function getGitEmailHash() {
|
|
4534
4571
|
try {
|
|
4535
|
-
const email =
|
|
4572
|
+
const email = execSync9("git config user.email", { encoding: "utf-8" }).trim();
|
|
4536
4573
|
if (!email) return void 0;
|
|
4537
4574
|
return crypto3.createHash("sha256").update(email).digest("hex");
|
|
4538
4575
|
} catch {
|
|
@@ -5738,7 +5775,7 @@ function printSetupSummary(setup) {
|
|
|
5738
5775
|
};
|
|
5739
5776
|
if (claude) {
|
|
5740
5777
|
if (claude.claudeMd) {
|
|
5741
|
-
const icon =
|
|
5778
|
+
const icon = fs23.existsSync("CLAUDE.md") ? chalk8.yellow("~") : chalk8.green("+");
|
|
5742
5779
|
const desc = getDescription("CLAUDE.md");
|
|
5743
5780
|
console.log(` ${icon} ${chalk8.bold("CLAUDE.md")}`);
|
|
5744
5781
|
if (desc) console.log(chalk8.dim(` ${desc}`));
|
|
@@ -5748,7 +5785,7 @@ function printSetupSummary(setup) {
|
|
|
5748
5785
|
if (Array.isArray(skills) && skills.length > 0) {
|
|
5749
5786
|
for (const skill of skills) {
|
|
5750
5787
|
const skillPath = `.claude/skills/${skill.name}/SKILL.md`;
|
|
5751
|
-
const icon =
|
|
5788
|
+
const icon = fs23.existsSync(skillPath) ? chalk8.yellow("~") : chalk8.green("+");
|
|
5752
5789
|
const desc = getDescription(skillPath);
|
|
5753
5790
|
console.log(` ${icon} ${chalk8.bold(skillPath)}`);
|
|
5754
5791
|
console.log(chalk8.dim(` ${desc || skill.description || skill.name}`));
|
|
@@ -5759,7 +5796,7 @@ function printSetupSummary(setup) {
|
|
|
5759
5796
|
const codex = setup.codex;
|
|
5760
5797
|
if (codex) {
|
|
5761
5798
|
if (codex.agentsMd) {
|
|
5762
|
-
const icon =
|
|
5799
|
+
const icon = fs23.existsSync("AGENTS.md") ? chalk8.yellow("~") : chalk8.green("+");
|
|
5763
5800
|
const desc = getDescription("AGENTS.md");
|
|
5764
5801
|
console.log(` ${icon} ${chalk8.bold("AGENTS.md")}`);
|
|
5765
5802
|
if (desc) console.log(chalk8.dim(` ${desc}`));
|
|
@@ -5769,7 +5806,7 @@ function printSetupSummary(setup) {
|
|
|
5769
5806
|
if (Array.isArray(codexSkills) && codexSkills.length > 0) {
|
|
5770
5807
|
for (const skill of codexSkills) {
|
|
5771
5808
|
const skillPath = `.agents/skills/${skill.name}/SKILL.md`;
|
|
5772
|
-
const icon =
|
|
5809
|
+
const icon = fs23.existsSync(skillPath) ? chalk8.yellow("~") : chalk8.green("+");
|
|
5773
5810
|
const desc = getDescription(skillPath);
|
|
5774
5811
|
console.log(` ${icon} ${chalk8.bold(skillPath)}`);
|
|
5775
5812
|
console.log(chalk8.dim(` ${desc || skill.description || skill.name}`));
|
|
@@ -5779,7 +5816,7 @@ function printSetupSummary(setup) {
|
|
|
5779
5816
|
}
|
|
5780
5817
|
if (cursor) {
|
|
5781
5818
|
if (cursor.cursorrules) {
|
|
5782
|
-
const icon =
|
|
5819
|
+
const icon = fs23.existsSync(".cursorrules") ? chalk8.yellow("~") : chalk8.green("+");
|
|
5783
5820
|
const desc = getDescription(".cursorrules");
|
|
5784
5821
|
console.log(` ${icon} ${chalk8.bold(".cursorrules")}`);
|
|
5785
5822
|
if (desc) console.log(chalk8.dim(` ${desc}`));
|
|
@@ -5789,7 +5826,7 @@ function printSetupSummary(setup) {
|
|
|
5789
5826
|
if (Array.isArray(cursorSkills) && cursorSkills.length > 0) {
|
|
5790
5827
|
for (const skill of cursorSkills) {
|
|
5791
5828
|
const skillPath = `.cursor/skills/${skill.name}/SKILL.md`;
|
|
5792
|
-
const icon =
|
|
5829
|
+
const icon = fs23.existsSync(skillPath) ? chalk8.yellow("~") : chalk8.green("+");
|
|
5793
5830
|
const desc = getDescription(skillPath);
|
|
5794
5831
|
console.log(` ${icon} ${chalk8.bold(skillPath)}`);
|
|
5795
5832
|
console.log(chalk8.dim(` ${desc || skill.description || skill.name}`));
|
|
@@ -5800,7 +5837,7 @@ function printSetupSummary(setup) {
|
|
|
5800
5837
|
if (Array.isArray(rules) && rules.length > 0) {
|
|
5801
5838
|
for (const rule of rules) {
|
|
5802
5839
|
const rulePath = `.cursor/rules/${rule.filename}`;
|
|
5803
|
-
const icon =
|
|
5840
|
+
const icon = fs23.existsSync(rulePath) ? chalk8.yellow("~") : chalk8.green("+");
|
|
5804
5841
|
const desc = getDescription(rulePath);
|
|
5805
5842
|
console.log(` ${icon} ${chalk8.bold(rulePath)}`);
|
|
5806
5843
|
if (desc) {
|
|
@@ -5813,7 +5850,7 @@ function printSetupSummary(setup) {
|
|
|
5813
5850
|
}
|
|
5814
5851
|
}
|
|
5815
5852
|
}
|
|
5816
|
-
if (!codex && !
|
|
5853
|
+
if (!codex && !fs23.existsSync("AGENTS.md")) {
|
|
5817
5854
|
console.log(` ${chalk8.green("+")} ${chalk8.bold("AGENTS.md")}`);
|
|
5818
5855
|
console.log(chalk8.dim(" Cross-agent coordination file"));
|
|
5819
5856
|
console.log("");
|
|
@@ -5832,8 +5869,8 @@ function ensurePermissions() {
|
|
|
5832
5869
|
const settingsPath = ".claude/settings.json";
|
|
5833
5870
|
let settings = {};
|
|
5834
5871
|
try {
|
|
5835
|
-
if (
|
|
5836
|
-
settings = JSON.parse(
|
|
5872
|
+
if (fs23.existsSync(settingsPath)) {
|
|
5873
|
+
settings = JSON.parse(fs23.readFileSync(settingsPath, "utf-8"));
|
|
5837
5874
|
}
|
|
5838
5875
|
} catch {
|
|
5839
5876
|
}
|
|
@@ -5847,8 +5884,8 @@ function ensurePermissions() {
|
|
|
5847
5884
|
"Bash(git *)"
|
|
5848
5885
|
];
|
|
5849
5886
|
settings.permissions = permissions;
|
|
5850
|
-
if (!
|
|
5851
|
-
|
|
5887
|
+
if (!fs23.existsSync(".claude")) fs23.mkdirSync(".claude", { recursive: true });
|
|
5888
|
+
fs23.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
|
|
5852
5889
|
}
|
|
5853
5890
|
|
|
5854
5891
|
// src/commands/undo.ts
|
|
@@ -5885,7 +5922,7 @@ function undoCommand() {
|
|
|
5885
5922
|
|
|
5886
5923
|
// src/commands/status.ts
|
|
5887
5924
|
import chalk10 from "chalk";
|
|
5888
|
-
import
|
|
5925
|
+
import fs24 from "fs";
|
|
5889
5926
|
init_config();
|
|
5890
5927
|
async function statusCommand(options) {
|
|
5891
5928
|
const config = loadConfig();
|
|
@@ -5912,7 +5949,7 @@ async function statusCommand(options) {
|
|
|
5912
5949
|
}
|
|
5913
5950
|
console.log(` Files managed: ${chalk10.cyan(manifest.entries.length.toString())}`);
|
|
5914
5951
|
for (const entry of manifest.entries) {
|
|
5915
|
-
const exists =
|
|
5952
|
+
const exists = fs24.existsSync(entry.path);
|
|
5916
5953
|
const icon = exists ? chalk10.green("\u2713") : chalk10.red("\u2717");
|
|
5917
5954
|
console.log(` ${icon} ${entry.path} (${entry.action})`);
|
|
5918
5955
|
}
|
|
@@ -6093,13 +6130,13 @@ async function scoreCommand(options) {
|
|
|
6093
6130
|
}
|
|
6094
6131
|
|
|
6095
6132
|
// src/commands/refresh.ts
|
|
6096
|
-
import
|
|
6133
|
+
import fs26 from "fs";
|
|
6097
6134
|
import path19 from "path";
|
|
6098
6135
|
import chalk13 from "chalk";
|
|
6099
6136
|
import ora5 from "ora";
|
|
6100
6137
|
|
|
6101
6138
|
// src/lib/git-diff.ts
|
|
6102
|
-
import { execSync as
|
|
6139
|
+
import { execSync as execSync10 } from "child_process";
|
|
6103
6140
|
var MAX_DIFF_BYTES = 1e5;
|
|
6104
6141
|
var DOC_PATTERNS = [
|
|
6105
6142
|
"CLAUDE.md",
|
|
@@ -6113,7 +6150,7 @@ function excludeArgs() {
|
|
|
6113
6150
|
}
|
|
6114
6151
|
function safeExec(cmd) {
|
|
6115
6152
|
try {
|
|
6116
|
-
return
|
|
6153
|
+
return execSync10(cmd, {
|
|
6117
6154
|
encoding: "utf-8",
|
|
6118
6155
|
stdio: ["pipe", "pipe", "pipe"],
|
|
6119
6156
|
maxBuffer: 10 * 1024 * 1024
|
|
@@ -6171,37 +6208,37 @@ function collectDiff(lastSha) {
|
|
|
6171
6208
|
}
|
|
6172
6209
|
|
|
6173
6210
|
// src/writers/refresh.ts
|
|
6174
|
-
import
|
|
6211
|
+
import fs25 from "fs";
|
|
6175
6212
|
import path18 from "path";
|
|
6176
6213
|
function writeRefreshDocs(docs) {
|
|
6177
6214
|
const written = [];
|
|
6178
6215
|
if (docs.claudeMd) {
|
|
6179
|
-
|
|
6216
|
+
fs25.writeFileSync("CLAUDE.md", docs.claudeMd);
|
|
6180
6217
|
written.push("CLAUDE.md");
|
|
6181
6218
|
}
|
|
6182
6219
|
if (docs.readmeMd) {
|
|
6183
|
-
|
|
6220
|
+
fs25.writeFileSync("README.md", docs.readmeMd);
|
|
6184
6221
|
written.push("README.md");
|
|
6185
6222
|
}
|
|
6186
6223
|
if (docs.cursorrules) {
|
|
6187
|
-
|
|
6224
|
+
fs25.writeFileSync(".cursorrules", docs.cursorrules);
|
|
6188
6225
|
written.push(".cursorrules");
|
|
6189
6226
|
}
|
|
6190
6227
|
if (docs.cursorRules) {
|
|
6191
6228
|
const rulesDir = path18.join(".cursor", "rules");
|
|
6192
|
-
if (!
|
|
6229
|
+
if (!fs25.existsSync(rulesDir)) fs25.mkdirSync(rulesDir, { recursive: true });
|
|
6193
6230
|
for (const rule of docs.cursorRules) {
|
|
6194
6231
|
const filePath = path18.join(rulesDir, rule.filename);
|
|
6195
|
-
|
|
6232
|
+
fs25.writeFileSync(filePath, rule.content);
|
|
6196
6233
|
written.push(filePath);
|
|
6197
6234
|
}
|
|
6198
6235
|
}
|
|
6199
6236
|
if (docs.claudeSkills) {
|
|
6200
6237
|
const skillsDir = path18.join(".claude", "skills");
|
|
6201
|
-
if (!
|
|
6238
|
+
if (!fs25.existsSync(skillsDir)) fs25.mkdirSync(skillsDir, { recursive: true });
|
|
6202
6239
|
for (const skill of docs.claudeSkills) {
|
|
6203
6240
|
const filePath = path18.join(skillsDir, skill.filename);
|
|
6204
|
-
|
|
6241
|
+
fs25.writeFileSync(filePath, skill.content);
|
|
6205
6242
|
written.push(filePath);
|
|
6206
6243
|
}
|
|
6207
6244
|
}
|
|
@@ -6280,11 +6317,11 @@ function log(quiet, ...args) {
|
|
|
6280
6317
|
function discoverGitRepos(parentDir) {
|
|
6281
6318
|
const repos = [];
|
|
6282
6319
|
try {
|
|
6283
|
-
const entries =
|
|
6320
|
+
const entries = fs26.readdirSync(parentDir, { withFileTypes: true });
|
|
6284
6321
|
for (const entry of entries) {
|
|
6285
6322
|
if (!entry.isDirectory() || entry.name.startsWith(".")) continue;
|
|
6286
6323
|
const childPath = path19.join(parentDir, entry.name);
|
|
6287
|
-
if (
|
|
6324
|
+
if (fs26.existsSync(path19.join(childPath, ".git"))) {
|
|
6288
6325
|
repos.push(childPath);
|
|
6289
6326
|
}
|
|
6290
6327
|
}
|
|
@@ -6636,7 +6673,7 @@ function readStdin() {
|
|
|
6636
6673
|
|
|
6637
6674
|
// src/learner/storage.ts
|
|
6638
6675
|
init_constants();
|
|
6639
|
-
import
|
|
6676
|
+
import fs27 from "fs";
|
|
6640
6677
|
import path20 from "path";
|
|
6641
6678
|
var MAX_RESPONSE_LENGTH = 2e3;
|
|
6642
6679
|
var DEFAULT_STATE = {
|
|
@@ -6645,8 +6682,8 @@ var DEFAULT_STATE = {
|
|
|
6645
6682
|
lastAnalysisTimestamp: null
|
|
6646
6683
|
};
|
|
6647
6684
|
function ensureLearningDir() {
|
|
6648
|
-
if (!
|
|
6649
|
-
|
|
6685
|
+
if (!fs27.existsSync(LEARNING_DIR)) {
|
|
6686
|
+
fs27.mkdirSync(LEARNING_DIR, { recursive: true });
|
|
6650
6687
|
}
|
|
6651
6688
|
}
|
|
6652
6689
|
function sessionFilePath() {
|
|
@@ -6664,49 +6701,49 @@ function appendEvent(event) {
|
|
|
6664
6701
|
ensureLearningDir();
|
|
6665
6702
|
const truncated = { ...event, tool_response: truncateResponse(event.tool_response) };
|
|
6666
6703
|
const filePath = sessionFilePath();
|
|
6667
|
-
|
|
6704
|
+
fs27.appendFileSync(filePath, JSON.stringify(truncated) + "\n");
|
|
6668
6705
|
const count = getEventCount();
|
|
6669
6706
|
if (count > LEARNING_MAX_EVENTS) {
|
|
6670
|
-
const lines =
|
|
6707
|
+
const lines = fs27.readFileSync(filePath, "utf-8").split("\n").filter(Boolean);
|
|
6671
6708
|
const kept = lines.slice(lines.length - LEARNING_MAX_EVENTS);
|
|
6672
|
-
|
|
6709
|
+
fs27.writeFileSync(filePath, kept.join("\n") + "\n");
|
|
6673
6710
|
}
|
|
6674
6711
|
}
|
|
6675
6712
|
function readAllEvents() {
|
|
6676
6713
|
const filePath = sessionFilePath();
|
|
6677
|
-
if (!
|
|
6678
|
-
const lines =
|
|
6714
|
+
if (!fs27.existsSync(filePath)) return [];
|
|
6715
|
+
const lines = fs27.readFileSync(filePath, "utf-8").split("\n").filter(Boolean);
|
|
6679
6716
|
return lines.map((line) => JSON.parse(line));
|
|
6680
6717
|
}
|
|
6681
6718
|
function getEventCount() {
|
|
6682
6719
|
const filePath = sessionFilePath();
|
|
6683
|
-
if (!
|
|
6684
|
-
const content =
|
|
6720
|
+
if (!fs27.existsSync(filePath)) return 0;
|
|
6721
|
+
const content = fs27.readFileSync(filePath, "utf-8");
|
|
6685
6722
|
return content.split("\n").filter(Boolean).length;
|
|
6686
6723
|
}
|
|
6687
6724
|
function clearSession() {
|
|
6688
6725
|
const filePath = sessionFilePath();
|
|
6689
|
-
if (
|
|
6726
|
+
if (fs27.existsSync(filePath)) fs27.unlinkSync(filePath);
|
|
6690
6727
|
}
|
|
6691
6728
|
function readState2() {
|
|
6692
6729
|
const filePath = stateFilePath();
|
|
6693
|
-
if (!
|
|
6730
|
+
if (!fs27.existsSync(filePath)) return { ...DEFAULT_STATE };
|
|
6694
6731
|
try {
|
|
6695
|
-
return JSON.parse(
|
|
6732
|
+
return JSON.parse(fs27.readFileSync(filePath, "utf-8"));
|
|
6696
6733
|
} catch {
|
|
6697
6734
|
return { ...DEFAULT_STATE };
|
|
6698
6735
|
}
|
|
6699
6736
|
}
|
|
6700
6737
|
function writeState2(state) {
|
|
6701
6738
|
ensureLearningDir();
|
|
6702
|
-
|
|
6739
|
+
fs27.writeFileSync(stateFilePath(), JSON.stringify(state, null, 2));
|
|
6703
6740
|
}
|
|
6704
6741
|
function resetState() {
|
|
6705
6742
|
writeState2({ ...DEFAULT_STATE });
|
|
6706
6743
|
}
|
|
6707
6744
|
|
|
6708
6745
|
// src/learner/writer.ts
|
|
6709
|
-
import
|
|
6746
|
+
import fs28 from "fs";
|
|
6710
6747
|
import path21 from "path";
|
|
6711
6748
|
var LEARNED_START = "<!-- caliber:learned -->";
|
|
6712
6749
|
var LEARNED_END = "<!-- /caliber:learned -->";
|
|
@@ -6727,8 +6764,8 @@ function writeLearnedContent(update) {
|
|
|
6727
6764
|
function writeLearnedSection(content) {
|
|
6728
6765
|
const claudeMdPath = "CLAUDE.md";
|
|
6729
6766
|
let existing = "";
|
|
6730
|
-
if (
|
|
6731
|
-
existing =
|
|
6767
|
+
if (fs28.existsSync(claudeMdPath)) {
|
|
6768
|
+
existing = fs28.readFileSync(claudeMdPath, "utf-8");
|
|
6732
6769
|
}
|
|
6733
6770
|
const section = `${LEARNED_START}
|
|
6734
6771
|
${content}
|
|
@@ -6742,15 +6779,15 @@ ${LEARNED_END}`;
|
|
|
6742
6779
|
const separator = existing.endsWith("\n") || existing === "" ? "" : "\n";
|
|
6743
6780
|
updated = existing + separator + "\n" + section + "\n";
|
|
6744
6781
|
}
|
|
6745
|
-
|
|
6782
|
+
fs28.writeFileSync(claudeMdPath, updated);
|
|
6746
6783
|
}
|
|
6747
6784
|
function writeLearnedSkill(skill) {
|
|
6748
6785
|
const skillDir = path21.join(".claude", "skills", skill.name);
|
|
6749
|
-
if (!
|
|
6786
|
+
if (!fs28.existsSync(skillDir)) fs28.mkdirSync(skillDir, { recursive: true });
|
|
6750
6787
|
const skillPath = path21.join(skillDir, "SKILL.md");
|
|
6751
|
-
if (!skill.isNew &&
|
|
6752
|
-
const existing =
|
|
6753
|
-
|
|
6788
|
+
if (!skill.isNew && fs28.existsSync(skillPath)) {
|
|
6789
|
+
const existing = fs28.readFileSync(skillPath, "utf-8");
|
|
6790
|
+
fs28.writeFileSync(skillPath, existing.trimEnd() + "\n\n" + skill.content);
|
|
6754
6791
|
} else {
|
|
6755
6792
|
const frontmatter = [
|
|
6756
6793
|
"---",
|
|
@@ -6759,14 +6796,14 @@ function writeLearnedSkill(skill) {
|
|
|
6759
6796
|
"---",
|
|
6760
6797
|
""
|
|
6761
6798
|
].join("\n");
|
|
6762
|
-
|
|
6799
|
+
fs28.writeFileSync(skillPath, frontmatter + skill.content);
|
|
6763
6800
|
}
|
|
6764
6801
|
return skillPath;
|
|
6765
6802
|
}
|
|
6766
6803
|
function readLearnedSection() {
|
|
6767
6804
|
const claudeMdPath = "CLAUDE.md";
|
|
6768
|
-
if (!
|
|
6769
|
-
const content =
|
|
6805
|
+
if (!fs28.existsSync(claudeMdPath)) return null;
|
|
6806
|
+
const content = fs28.readFileSync(claudeMdPath, "utf-8");
|
|
6770
6807
|
const startIdx = content.indexOf(LEARNED_START);
|
|
6771
6808
|
const endIdx = content.indexOf(LEARNED_END);
|
|
6772
6809
|
if (startIdx === -1 || endIdx === -1) return null;
|
|
@@ -6957,7 +6994,7 @@ Learned items in CLAUDE.md: ${chalk16.cyan(String(lineCount))}`);
|
|
|
6957
6994
|
// src/cli.ts
|
|
6958
6995
|
var __dirname = path22.dirname(fileURLToPath(import.meta.url));
|
|
6959
6996
|
var pkg = JSON.parse(
|
|
6960
|
-
|
|
6997
|
+
fs29.readFileSync(path22.resolve(__dirname, "..", "package.json"), "utf-8")
|
|
6961
6998
|
);
|
|
6962
6999
|
var program = new Command();
|
|
6963
7000
|
var displayVersion = process.env.CALIBER_LOCAL ? `${pkg.version}-local` : pkg.version;
|
|
@@ -7031,22 +7068,22 @@ learn.command("remove").description("Remove learning hooks from .claude/settings
|
|
|
7031
7068
|
learn.command("status").description("Show learning system status").action(tracked("learn:status", learnStatusCommand));
|
|
7032
7069
|
|
|
7033
7070
|
// src/utils/version-check.ts
|
|
7034
|
-
import
|
|
7071
|
+
import fs30 from "fs";
|
|
7035
7072
|
import path23 from "path";
|
|
7036
7073
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
7037
|
-
import { execSync as
|
|
7074
|
+
import { execSync as execSync11 } from "child_process";
|
|
7038
7075
|
import chalk17 from "chalk";
|
|
7039
7076
|
import ora6 from "ora";
|
|
7040
7077
|
import confirm from "@inquirer/confirm";
|
|
7041
7078
|
var __dirname_vc = path23.dirname(fileURLToPath2(import.meta.url));
|
|
7042
7079
|
var pkg2 = JSON.parse(
|
|
7043
|
-
|
|
7080
|
+
fs30.readFileSync(path23.resolve(__dirname_vc, "..", "package.json"), "utf-8")
|
|
7044
7081
|
);
|
|
7045
7082
|
function getInstalledVersion() {
|
|
7046
7083
|
try {
|
|
7047
|
-
const globalRoot =
|
|
7084
|
+
const globalRoot = execSync11("npm root -g", { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
|
|
7048
7085
|
const pkgPath = path23.join(globalRoot, "@rely-ai", "caliber", "package.json");
|
|
7049
|
-
return JSON.parse(
|
|
7086
|
+
return JSON.parse(fs30.readFileSync(pkgPath, "utf-8")).version;
|
|
7050
7087
|
} catch {
|
|
7051
7088
|
return null;
|
|
7052
7089
|
}
|
|
@@ -7089,7 +7126,7 @@ Update available: ${current} -> ${latest}`)
|
|
|
7089
7126
|
}
|
|
7090
7127
|
const spinner = ora6("Updating caliber...").start();
|
|
7091
7128
|
try {
|
|
7092
|
-
|
|
7129
|
+
execSync11(`npm install -g @rely-ai/caliber@${latest}`, {
|
|
7093
7130
|
stdio: "pipe",
|
|
7094
7131
|
timeout: 12e4,
|
|
7095
7132
|
env: { ...process.env, npm_config_fund: "false", npm_config_audit: "false" }
|
|
@@ -7106,7 +7143,7 @@ Update available: ${current} -> ${latest}`)
|
|
|
7106
7143
|
console.log(chalk17.dim(`
|
|
7107
7144
|
Restarting: caliber ${args.join(" ")}
|
|
7108
7145
|
`));
|
|
7109
|
-
|
|
7146
|
+
execSync11(`caliber ${args.map((a) => JSON.stringify(a)).join(" ")}`, {
|
|
7110
7147
|
stdio: "inherit",
|
|
7111
7148
|
env: { ...process.env, CALIBER_SKIP_UPDATE_CHECK: "1" }
|
|
7112
7149
|
});
|
package/package.json
CHANGED