@rely-ai/caliber 1.36.0 → 1.36.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/bin.js +226 -78
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -285,9 +285,9 @@ No API key? No problem. Caliber works with your existing AI tool subscription:
|
|
|
285
285
|
| **Claude Code** (your seat) | `caliber config` → Claude Code | Inherited from Claude Code |
|
|
286
286
|
| **Cursor** (your seat) | `caliber config` → Cursor | Inherited from Cursor |
|
|
287
287
|
| **Anthropic** | `export ANTHROPIC_API_KEY=sk-ant-...` | `claude-sonnet-4-6` |
|
|
288
|
-
| **OpenAI** | `export OPENAI_API_KEY=sk-...` | `gpt-4
|
|
288
|
+
| **OpenAI** | `export OPENAI_API_KEY=sk-...` | `gpt-5.4-mini` |
|
|
289
289
|
| **Vertex AI** | `export VERTEX_PROJECT_ID=my-project` | `claude-sonnet-4-6` |
|
|
290
|
-
| **Custom endpoint** | `OPENAI_API_KEY` + `OPENAI_BASE_URL` | `gpt-4
|
|
290
|
+
| **Custom endpoint** | `OPENAI_API_KEY` + `OPENAI_BASE_URL` | `gpt-5.4-mini` |
|
|
291
291
|
|
|
292
292
|
Override the model for any provider: `export CALIBER_MODEL=<model-name>` or use `caliber config`.
|
|
293
293
|
|
package/dist/bin.js
CHANGED
|
@@ -35,9 +35,9 @@ function getMaxPromptTokens() {
|
|
|
35
35
|
return Math.max(MIN_PROMPT_TOKENS, Math.min(budget, MAX_PROMPT_TOKENS_CAP));
|
|
36
36
|
}
|
|
37
37
|
function loadConfig() {
|
|
38
|
-
const
|
|
39
|
-
if (
|
|
40
|
-
return
|
|
38
|
+
const fileConfig = readConfigFile();
|
|
39
|
+
if (fileConfig) return fileConfig;
|
|
40
|
+
return resolveFromEnv();
|
|
41
41
|
}
|
|
42
42
|
function resolveFromEnv() {
|
|
43
43
|
if (process.env.ANTHROPIC_API_KEY) {
|
|
@@ -130,7 +130,7 @@ var init_config = __esm({
|
|
|
130
130
|
DEFAULT_MODELS = {
|
|
131
131
|
anthropic: "claude-sonnet-4-6",
|
|
132
132
|
vertex: "claude-sonnet-4-6",
|
|
133
|
-
openai: "gpt-4
|
|
133
|
+
openai: "gpt-5.4-mini",
|
|
134
134
|
cursor: "sonnet-4.6",
|
|
135
135
|
"claude-cli": "default"
|
|
136
136
|
};
|
|
@@ -139,8 +139,7 @@ var init_config = __esm({
|
|
|
139
139
|
"claude-opus-4-6": 2e5,
|
|
140
140
|
"claude-haiku-4-5-20251001": 2e5,
|
|
141
141
|
"claude-sonnet-4-5-20250514": 2e5,
|
|
142
|
-
"gpt-4
|
|
143
|
-
"gpt-4.1-mini": 1e6,
|
|
142
|
+
"gpt-5.4-mini": 1e6,
|
|
144
143
|
"gpt-4o": 128e3,
|
|
145
144
|
"gpt-4o-mini": 128e3,
|
|
146
145
|
"sonnet-4.6": 2e5
|
|
@@ -152,7 +151,7 @@ var init_config = __esm({
|
|
|
152
151
|
DEFAULT_FAST_MODELS = {
|
|
153
152
|
anthropic: "claude-haiku-4-5-20251001",
|
|
154
153
|
vertex: "claude-haiku-4-5-20251001",
|
|
155
|
-
openai: "gpt-4
|
|
154
|
+
openai: "gpt-5.4-mini",
|
|
156
155
|
cursor: "gpt-5.3-codex-fast"
|
|
157
156
|
};
|
|
158
157
|
}
|
|
@@ -2836,13 +2835,7 @@ var KNOWN_MODELS = {
|
|
|
2836
2835
|
"claude-opus-4-6@20250605",
|
|
2837
2836
|
"claude-opus-4-1-20250620"
|
|
2838
2837
|
],
|
|
2839
|
-
openai: [
|
|
2840
|
-
"gpt-4.1",
|
|
2841
|
-
"gpt-4.1-mini",
|
|
2842
|
-
"gpt-4o",
|
|
2843
|
-
"gpt-4o-mini",
|
|
2844
|
-
"o3-mini"
|
|
2845
|
-
],
|
|
2838
|
+
openai: ["gpt-5.4-mini", "gpt-4o", "gpt-4o-mini", "o3-mini"],
|
|
2846
2839
|
cursor: ["auto", "composer-1.5"],
|
|
2847
2840
|
"claude-cli": []
|
|
2848
2841
|
};
|
|
@@ -2850,7 +2843,8 @@ function isModelNotAvailableError(error) {
|
|
|
2850
2843
|
const msg = error.message.toLowerCase();
|
|
2851
2844
|
const status = error.status;
|
|
2852
2845
|
if (status === 404 && msg.includes("model")) return true;
|
|
2853
|
-
if (msg.includes("model") && (msg.includes("not found") || msg.includes("not_found")))
|
|
2846
|
+
if (msg.includes("model") && (msg.includes("not found") || msg.includes("not_found")))
|
|
2847
|
+
return true;
|
|
2854
2848
|
if (msg.includes("model") && msg.includes("not available")) return true;
|
|
2855
2849
|
if (msg.includes("model") && msg.includes("does not exist")) return true;
|
|
2856
2850
|
if (msg.includes("publisher model")) return true;
|
|
@@ -2876,12 +2870,18 @@ function filterRelevantModels(models, provider) {
|
|
|
2876
2870
|
async function handleModelNotAvailable(failedModel, provider, config) {
|
|
2877
2871
|
if (!process.stdin.isTTY) {
|
|
2878
2872
|
console.error(
|
|
2879
|
-
chalk.red(
|
|
2873
|
+
chalk.red(
|
|
2874
|
+
`Model "${failedModel}" is not available. Run \`${resolveCaliber()} config\` to select a different model.`
|
|
2875
|
+
)
|
|
2880
2876
|
);
|
|
2881
2877
|
return null;
|
|
2882
2878
|
}
|
|
2883
|
-
console.log(
|
|
2884
|
-
|
|
2879
|
+
console.log(
|
|
2880
|
+
chalk.yellow(
|
|
2881
|
+
`
|
|
2882
|
+
\u26A0 Model "${failedModel}" is not available on your ${config.provider} deployment.`
|
|
2883
|
+
)
|
|
2884
|
+
);
|
|
2885
2885
|
let models = [];
|
|
2886
2886
|
if (provider.listModels) {
|
|
2887
2887
|
try {
|
|
@@ -2895,7 +2895,11 @@ async function handleModelNotAvailable(failedModel, provider, config) {
|
|
|
2895
2895
|
}
|
|
2896
2896
|
models = models.filter((m) => m !== failedModel);
|
|
2897
2897
|
if (models.length === 0) {
|
|
2898
|
-
console.log(
|
|
2898
|
+
console.log(
|
|
2899
|
+
chalk.red(
|
|
2900
|
+
` No alternative models found. Run \`${resolveCaliber()} config\` to configure manually.`
|
|
2901
|
+
)
|
|
2902
|
+
);
|
|
2899
2903
|
return null;
|
|
2900
2904
|
}
|
|
2901
2905
|
console.log("");
|
|
@@ -6288,14 +6292,17 @@ function checkExistence(dir) {
|
|
|
6288
6292
|
const opencodeSkills = countFiles(join3(dir, ".opencode", "skills"), /SKILL\.md$/);
|
|
6289
6293
|
const skillCount = claudeSkills.length + codexSkills.length + opencodeSkills.length;
|
|
6290
6294
|
const skillBase = skillCount >= 1 ? POINTS_SKILLS_EXIST : 0;
|
|
6291
|
-
const skillBonus = Math.min(
|
|
6295
|
+
const skillBonus = Math.min(
|
|
6296
|
+
(skillCount - 1) * POINTS_SKILLS_BONUS_PER_EXTRA,
|
|
6297
|
+
POINTS_SKILLS_BONUS_CAP
|
|
6298
|
+
);
|
|
6292
6299
|
const skillPoints = skillCount >= 1 ? skillBase + Math.max(0, skillBonus) : 0;
|
|
6293
6300
|
const maxSkillPoints = POINTS_SKILLS_EXIST + POINTS_SKILLS_BONUS_CAP;
|
|
6294
6301
|
checks.push({
|
|
6295
6302
|
id: "skills_exist",
|
|
6296
6303
|
name: "Skills configured",
|
|
6297
6304
|
category: "existence",
|
|
6298
|
-
maxPoints: maxSkillPoints,
|
|
6305
|
+
maxPoints: skillCount >= 1 ? maxSkillPoints : 0,
|
|
6299
6306
|
earnedPoints: Math.min(skillPoints, maxSkillPoints),
|
|
6300
6307
|
passed: skillCount >= 1,
|
|
6301
6308
|
detail: skillCount === 0 ? "No skills found" : `${skillCount} skill${skillCount === 1 ? "" : "s"} found`,
|
|
@@ -6328,7 +6335,7 @@ function checkExistence(dir) {
|
|
|
6328
6335
|
id: "mcp_servers",
|
|
6329
6336
|
name: "MCP servers configured",
|
|
6330
6337
|
category: "existence",
|
|
6331
|
-
maxPoints: POINTS_MCP_SERVERS,
|
|
6338
|
+
maxPoints: mcp.count >= 1 ? POINTS_MCP_SERVERS : 0,
|
|
6332
6339
|
earnedPoints: mcp.count >= 1 ? POINTS_MCP_SERVERS : 0,
|
|
6333
6340
|
passed: mcp.count >= 1,
|
|
6334
6341
|
detail: mcp.count > 0 ? `${mcp.count} server${mcp.count === 1 ? "" : "s"} in ${mcp.sources.join(", ")}` : "No MCP servers configured",
|
|
@@ -6863,7 +6870,11 @@ init_resolve_caliber();
|
|
|
6863
6870
|
init_pre_commit_block();
|
|
6864
6871
|
function hasPreCommitHook(dir) {
|
|
6865
6872
|
try {
|
|
6866
|
-
const gitDir = execSync12("git rev-parse --git-dir", {
|
|
6873
|
+
const gitDir = execSync12("git rev-parse --git-dir", {
|
|
6874
|
+
cwd: dir,
|
|
6875
|
+
encoding: "utf-8",
|
|
6876
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
6877
|
+
}).trim();
|
|
6867
6878
|
const hookPath = join7(gitDir, "hooks", "pre-commit");
|
|
6868
6879
|
const content = readFileOrNull(hookPath);
|
|
6869
6880
|
return content ? content.includes("caliber") : false;
|
|
@@ -6954,9 +6965,9 @@ function checkBonus(dir) {
|
|
|
6954
6965
|
id: "open_skills_format",
|
|
6955
6966
|
name: "Skills use OpenSkills format",
|
|
6956
6967
|
category: "bonus",
|
|
6957
|
-
maxPoints: POINTS_OPEN_SKILLS_FORMAT,
|
|
6968
|
+
maxPoints: totalSkillFiles > 0 ? POINTS_OPEN_SKILLS_FORMAT : 0,
|
|
6958
6969
|
earnedPoints: allOpenSkills ? POINTS_OPEN_SKILLS_FORMAT : 0,
|
|
6959
|
-
passed: allOpenSkills,
|
|
6970
|
+
passed: allOpenSkills || totalSkillFiles === 0,
|
|
6960
6971
|
detail: totalSkillFiles === 0 ? "No skills to check" : allOpenSkills ? `All ${totalSkillFiles} skill${totalSkillFiles === 1 ? "" : "s"} use SKILL.md with frontmatter` : `${openSkillsCount}/${totalSkillFiles} use OpenSkills format`,
|
|
6961
6972
|
suggestion: totalSkillFiles > 0 && !allOpenSkills ? "Migrate skills to .claude/skills/{name}/SKILL.md with YAML frontmatter" : void 0,
|
|
6962
6973
|
fix: totalSkillFiles > 0 && !allOpenSkills ? {
|
|
@@ -9750,27 +9761,47 @@ async function initCommand(options) {
|
|
|
9750
9761
|
const bin = resolveCaliber();
|
|
9751
9762
|
const firstRun = isFirstRun(process.cwd());
|
|
9752
9763
|
if (firstRun) {
|
|
9753
|
-
console.log(
|
|
9764
|
+
console.log(
|
|
9765
|
+
brand.bold(`
|
|
9754
9766
|
\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2557
|
|
9755
9767
|
\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557
|
|
9756
9768
|
\u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D
|
|
9757
9769
|
\u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u255D \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557
|
|
9758
9770
|
\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551
|
|
9759
9771
|
\u255A\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D
|
|
9760
|
-
`)
|
|
9772
|
+
`)
|
|
9773
|
+
);
|
|
9761
9774
|
console.log(chalk14.dim(" Keep your AI agent configs in sync \u2014 automatically."));
|
|
9762
9775
|
console.log(chalk14.dim(" Works across Claude Code, Cursor, Codex, and GitHub Copilot.\n"));
|
|
9763
|
-
console.log(title.bold("
|
|
9764
|
-
console.log(
|
|
9765
|
-
|
|
9766
|
-
|
|
9776
|
+
console.log(title.bold(" What this does:\n"));
|
|
9777
|
+
console.log(
|
|
9778
|
+
chalk14.dim(" Caliber reads your project structure (file tree, package.json, etc.)")
|
|
9779
|
+
);
|
|
9780
|
+
console.log(chalk14.dim(" and generates agent config files (CLAUDE.md, .cursor/rules/, etc.)."));
|
|
9781
|
+
console.log(chalk14.dim(" You review all changes before anything is written to disk.\n"));
|
|
9782
|
+
console.log(title.bold(" Steps:\n"));
|
|
9783
|
+
console.log(
|
|
9784
|
+
chalk14.dim(" 1. Connect Pick your LLM provider (or use your existing subscription)")
|
|
9785
|
+
);
|
|
9786
|
+
console.log(
|
|
9787
|
+
chalk14.dim(" 2. Build Scan project, generate configs, install pre-commit sync")
|
|
9788
|
+
);
|
|
9789
|
+
console.log(
|
|
9790
|
+
chalk14.dim(" 3. Review See exactly what changed \u2014 accept, refine, or decline\n")
|
|
9791
|
+
);
|
|
9767
9792
|
} else {
|
|
9768
9793
|
console.log(brand.bold("\n CALIBER") + chalk14.dim(" \u2014 setting up continuous sync\n"));
|
|
9769
9794
|
}
|
|
9770
9795
|
const platforms = detectPlatforms();
|
|
9771
9796
|
if (!platforms.claude && !platforms.cursor && !platforms.codex && !platforms.opencode) {
|
|
9772
|
-
console.log(
|
|
9773
|
-
|
|
9797
|
+
console.log(
|
|
9798
|
+
chalk14.yellow(" \u26A0 No supported AI platforms detected (Claude, Cursor, Codex, OpenCode).")
|
|
9799
|
+
);
|
|
9800
|
+
console.log(
|
|
9801
|
+
chalk14.yellow(
|
|
9802
|
+
" Caliber will still generate config files, but they won't be auto-installed.\n"
|
|
9803
|
+
)
|
|
9804
|
+
);
|
|
9774
9805
|
}
|
|
9775
9806
|
const report = options.debugReport ? new DebugReport() : null;
|
|
9776
9807
|
console.log(title.bold(" Step 1/3 \u2014 Connect\n"));
|
|
@@ -9825,9 +9856,12 @@ async function initCommand(options) {
|
|
|
9825
9856
|
console.log(chalk14.dim(modelLine + "\n"));
|
|
9826
9857
|
if (report) {
|
|
9827
9858
|
report.markStep("Provider connection");
|
|
9828
|
-
report.addSection(
|
|
9859
|
+
report.addSection(
|
|
9860
|
+
"LLM Provider",
|
|
9861
|
+
`- **Provider**: ${config.provider}
|
|
9829
9862
|
- **Model**: ${displayModel}
|
|
9830
|
-
- **Fast model**: ${fastModel || "none"}`
|
|
9863
|
+
- **Fast model**: ${fastModel || "none"}`
|
|
9864
|
+
);
|
|
9831
9865
|
}
|
|
9832
9866
|
await validateModel({ fast: true });
|
|
9833
9867
|
let targetAgent;
|
|
@@ -9863,9 +9897,12 @@ async function initCommand(options) {
|
|
|
9863
9897
|
console.log(` ${chalk14.green("\u2713")} Onboarding hook \u2014 nudges new team members to set up`);
|
|
9864
9898
|
const { ensureBuiltinSkills: ensureBuiltinSkills2 } = await Promise.resolve().then(() => (init_builtin_skills(), builtin_skills_exports));
|
|
9865
9899
|
for (const agent of targetAgent) {
|
|
9866
|
-
if (agent === "claude" && !fs34.existsSync(".claude"))
|
|
9867
|
-
|
|
9868
|
-
if (agent === "
|
|
9900
|
+
if (agent === "claude" && !fs34.existsSync(".claude"))
|
|
9901
|
+
fs34.mkdirSync(".claude", { recursive: true });
|
|
9902
|
+
if (agent === "cursor" && !fs34.existsSync(".cursor"))
|
|
9903
|
+
fs34.mkdirSync(".cursor", { recursive: true });
|
|
9904
|
+
if (agent === "codex" && !fs34.existsSync(".agents"))
|
|
9905
|
+
fs34.mkdirSync(".agents", { recursive: true });
|
|
9869
9906
|
}
|
|
9870
9907
|
const skillsWritten = ensureBuiltinSkills2();
|
|
9871
9908
|
if (skillsWritten.length > 0) {
|
|
@@ -9883,11 +9920,16 @@ async function initCommand(options) {
|
|
|
9883
9920
|
log(options.verbose, `Baseline score: ${baselineScore.score}/100`);
|
|
9884
9921
|
if (report) {
|
|
9885
9922
|
report.markStep("Baseline scoring");
|
|
9886
|
-
report.addSection(
|
|
9923
|
+
report.addSection(
|
|
9924
|
+
"Scoring: Baseline",
|
|
9925
|
+
`**Score**: ${baselineScore.score}/100
|
|
9887
9926
|
|
|
9888
9927
|
| Check | Passed | Points | Max |
|
|
9889
9928
|
|-------|--------|--------|-----|
|
|
9890
|
-
` + baselineScore.checks.map(
|
|
9929
|
+
` + baselineScore.checks.map(
|
|
9930
|
+
(c) => `| ${c.name} | ${c.passed ? "Yes" : "No"} | ${c.earnedPoints} | ${c.maxPoints} |`
|
|
9931
|
+
).join("\n")
|
|
9932
|
+
);
|
|
9891
9933
|
report.addSection("Generation: Target Agents", targetAgent.join(", "));
|
|
9892
9934
|
}
|
|
9893
9935
|
const hasExistingConfig = !!(baselineScore.checks.some((c) => c.id === "claude_md_exists" && c.passed) || baselineScore.checks.some((c) => c.id === "cursorrules_exists" && c.passed));
|
|
@@ -9906,8 +9948,19 @@ async function initCommand(options) {
|
|
|
9906
9948
|
if (hasExistingConfig && baselineScore.score === 100 && !options.force) {
|
|
9907
9949
|
skipGeneration = true;
|
|
9908
9950
|
} else if (hasExistingConfig && !options.force && !options.autoApprove) {
|
|
9909
|
-
|
|
9951
|
+
const topGains = baselineScore.checks.filter((c) => !c.passed && c.maxPoints > 0).sort((a, b) => b.maxPoints - b.earnedPoints - (a.maxPoints - a.earnedPoints)).slice(0, 3);
|
|
9952
|
+
console.log(chalk14.dim(` Config score: ${baselineScore.score}/100
|
|
9910
9953
|
`));
|
|
9954
|
+
if (topGains.length > 0) {
|
|
9955
|
+
console.log(chalk14.dim(" Top improvements Caliber can make:"));
|
|
9956
|
+
for (const c of topGains) {
|
|
9957
|
+
const pts = c.maxPoints - c.earnedPoints;
|
|
9958
|
+
console.log(
|
|
9959
|
+
chalk14.dim(` +${pts} pts`) + chalk14.white(` ${c.name}`) + (c.suggestion ? chalk14.gray(` \u2014 ${c.suggestion}`) : "")
|
|
9960
|
+
);
|
|
9961
|
+
}
|
|
9962
|
+
console.log("");
|
|
9963
|
+
}
|
|
9911
9964
|
const improveAnswer = await confirm2({ message: "Improve your existing configs?" });
|
|
9912
9965
|
skipGeneration = !improveAnswer;
|
|
9913
9966
|
}
|
|
@@ -9937,7 +9990,12 @@ async function initCommand(options) {
|
|
|
9937
9990
|
if (targetAgent.includes("cursor")) {
|
|
9938
9991
|
const rulesDir = path28.join(".cursor", "rules");
|
|
9939
9992
|
if (!fs34.existsSync(rulesDir)) fs34.mkdirSync(rulesDir, { recursive: true });
|
|
9940
|
-
for (const rule of [
|
|
9993
|
+
for (const rule of [
|
|
9994
|
+
getCursorPreCommitRule2(),
|
|
9995
|
+
getCursorLearningsRule2(),
|
|
9996
|
+
getCursorSyncRule2(),
|
|
9997
|
+
getCursorSetupRule2()
|
|
9998
|
+
]) {
|
|
9941
9999
|
fs34.writeFileSync(path28.join(rulesDir, rule.filename), rule.content);
|
|
9942
10000
|
}
|
|
9943
10001
|
console.log(` ${chalk14.green("\u2713")} Cursor rules \u2014 added Caliber sync rules`);
|
|
@@ -9969,7 +10027,9 @@ async function initCommand(options) {
|
|
|
9969
10027
|
trackInitCompleted("sync-only", baselineScore.score);
|
|
9970
10028
|
console.log(chalk14.bold.green("\n Caliber sync is set up!\n"));
|
|
9971
10029
|
console.log(chalk14.dim(" Your agent configs will sync automatically on every commit."));
|
|
9972
|
-
console.log(
|
|
10030
|
+
console.log(
|
|
10031
|
+
chalk14.dim(" Run ") + title(`${bin} init --force`) + chalk14.dim(" anytime to generate or improve configs.\n")
|
|
10032
|
+
);
|
|
9973
10033
|
return;
|
|
9974
10034
|
}
|
|
9975
10035
|
const genModelInfo = fastModel ? ` Using ${displayModel} for docs, ${fastModel} for skills` : ` Using ${displayModel}`;
|
|
@@ -9987,8 +10047,14 @@ async function initCommand(options) {
|
|
|
9987
10047
|
const TASK_STACK = display.add("Detecting project stack", { pipelineLabel: "Scan" });
|
|
9988
10048
|
const TASK_CONFIG = display.add("Generating configs", { depth: 1, pipelineLabel: "Generate" });
|
|
9989
10049
|
const TASK_SKILLS_GEN = display.add("Generating skills", { depth: 2, pipelineLabel: "Skills" });
|
|
9990
|
-
const TASK_SKILLS_SEARCH = display.add("Searching community skills", {
|
|
9991
|
-
|
|
10050
|
+
const TASK_SKILLS_SEARCH = display.add("Searching community skills", {
|
|
10051
|
+
depth: 1,
|
|
10052
|
+
pipelineLabel: "Search",
|
|
10053
|
+
pipelineRow: 1
|
|
10054
|
+
});
|
|
10055
|
+
const TASK_SCORE_REFINE = display.add("Validating & refining config", {
|
|
10056
|
+
pipelineLabel: "Validate"
|
|
10057
|
+
});
|
|
9992
10058
|
display.start();
|
|
9993
10059
|
display.enableWaitingContent();
|
|
9994
10060
|
try {
|
|
@@ -9998,21 +10064,39 @@ async function initCommand(options) {
|
|
|
9998
10064
|
const stackSummary = stackParts.join(", ") || "no languages";
|
|
9999
10065
|
const largeRepoNote = fingerprint.fileTree.length > 5e3 ? ` (${fingerprint.fileTree.length.toLocaleString()} files, smart sampling active)` : "";
|
|
10000
10066
|
display.update(TASK_STACK, "done", stackSummary + largeRepoNote);
|
|
10001
|
-
trackInitProjectDiscovered(
|
|
10002
|
-
|
|
10067
|
+
trackInitProjectDiscovered(
|
|
10068
|
+
fingerprint.languages.length,
|
|
10069
|
+
fingerprint.frameworks.length,
|
|
10070
|
+
fingerprint.fileTree.length
|
|
10071
|
+
);
|
|
10072
|
+
log(
|
|
10073
|
+
options.verbose,
|
|
10074
|
+
`Fingerprint: ${fingerprint.languages.length} languages, ${fingerprint.frameworks.length} frameworks, ${fingerprint.fileTree.length} files`
|
|
10075
|
+
);
|
|
10003
10076
|
const cliSources = options.source || [];
|
|
10004
10077
|
const workspaces = getDetectedWorkspaces(process.cwd());
|
|
10005
10078
|
const sources2 = resolveAllSources(process.cwd(), cliSources, workspaces);
|
|
10006
10079
|
if (sources2.length > 0) {
|
|
10007
10080
|
fingerprint.sources = sources2;
|
|
10008
|
-
log(
|
|
10081
|
+
log(
|
|
10082
|
+
options.verbose,
|
|
10083
|
+
`Sources: ${sources2.length} resolved (${sources2.map((s) => s.name).join(", ")})`
|
|
10084
|
+
);
|
|
10009
10085
|
}
|
|
10010
10086
|
if (report) {
|
|
10011
|
-
report.addJson("Fingerprint: Git", {
|
|
10087
|
+
report.addJson("Fingerprint: Git", {
|
|
10088
|
+
remote: fingerprint.gitRemoteUrl,
|
|
10089
|
+
packageName: fingerprint.packageName
|
|
10090
|
+
});
|
|
10012
10091
|
report.addCodeBlock("Fingerprint: File Tree", fingerprint.fileTree.join("\n"));
|
|
10013
|
-
report.addJson("Fingerprint: Detected Stack", {
|
|
10092
|
+
report.addJson("Fingerprint: Detected Stack", {
|
|
10093
|
+
languages: fingerprint.languages,
|
|
10094
|
+
frameworks: fingerprint.frameworks,
|
|
10095
|
+
tools: fingerprint.tools
|
|
10096
|
+
});
|
|
10014
10097
|
report.addJson("Fingerprint: Existing Configs", fingerprint.existingConfigs);
|
|
10015
|
-
if (fingerprint.codeAnalysis)
|
|
10098
|
+
if (fingerprint.codeAnalysis)
|
|
10099
|
+
report.addJson("Fingerprint: Code Analysis", fingerprint.codeAnalysis);
|
|
10016
10100
|
}
|
|
10017
10101
|
const isEmpty = fingerprint.fileTree.length < 3;
|
|
10018
10102
|
if (isEmpty) {
|
|
@@ -10043,13 +10127,26 @@ async function initCommand(options) {
|
|
|
10043
10127
|
let passingChecks;
|
|
10044
10128
|
let currentScore;
|
|
10045
10129
|
if (hasExistingConfig && localBaseline.score >= 95 && !options.force) {
|
|
10046
|
-
const currentLlmFixable = localBaseline.checks.filter(
|
|
10047
|
-
|
|
10130
|
+
const currentLlmFixable = localBaseline.checks.filter(
|
|
10131
|
+
(c) => !c.passed && c.maxPoints > 0 && !NON_LLM_CHECKS.has(c.id)
|
|
10132
|
+
);
|
|
10133
|
+
failingChecks = currentLlmFixable.map((c) => ({
|
|
10134
|
+
name: c.name,
|
|
10135
|
+
suggestion: c.suggestion,
|
|
10136
|
+
fix: c.fix
|
|
10137
|
+
}));
|
|
10048
10138
|
passingChecks = localBaseline.checks.filter((c) => c.passed).map((c) => ({ name: c.name }));
|
|
10049
10139
|
currentScore = localBaseline.score;
|
|
10050
10140
|
}
|
|
10051
10141
|
if (report) {
|
|
10052
|
-
const fullPrompt = buildGeneratePrompt(
|
|
10142
|
+
const fullPrompt = buildGeneratePrompt(
|
|
10143
|
+
fingerprint,
|
|
10144
|
+
targetAgent,
|
|
10145
|
+
fingerprint.description,
|
|
10146
|
+
failingChecks,
|
|
10147
|
+
currentScore,
|
|
10148
|
+
passingChecks
|
|
10149
|
+
);
|
|
10053
10150
|
report.addCodeBlock("Generation: Full LLM Prompt", fullPrompt);
|
|
10054
10151
|
}
|
|
10055
10152
|
const result = await generateSetup(
|
|
@@ -10169,7 +10266,10 @@ async function initCommand(options) {
|
|
|
10169
10266
|
if (rawOutput) report.addCodeBlock("Generation: Raw LLM Response", rawOutput);
|
|
10170
10267
|
report.addJson("Generation: Parsed Config", generatedSetup);
|
|
10171
10268
|
}
|
|
10172
|
-
log(
|
|
10269
|
+
log(
|
|
10270
|
+
options.verbose,
|
|
10271
|
+
`Generation completed: ${elapsedMs}ms, stopReason: ${genStopReason || "end_turn"}`
|
|
10272
|
+
);
|
|
10173
10273
|
console.log(title.bold(" Step 3/3 \u2014 Done\n"));
|
|
10174
10274
|
const setupFiles = collectSetupFiles(generatedSetup, targetAgent);
|
|
10175
10275
|
const staged = stageFiles(setupFiles, process.cwd());
|
|
@@ -10181,10 +10281,18 @@ async function initCommand(options) {
|
|
|
10181
10281
|
}
|
|
10182
10282
|
console.log("");
|
|
10183
10283
|
}
|
|
10184
|
-
console.log(
|
|
10284
|
+
console.log(
|
|
10285
|
+
chalk14.dim(
|
|
10286
|
+
` ${chalk14.green(`${staged.newFiles} new`)} / ${chalk14.yellow(`${staged.modifiedFiles} modified`)} file${totalChanges !== 1 ? "s" : ""}`
|
|
10287
|
+
)
|
|
10288
|
+
);
|
|
10185
10289
|
if (skillSearchResult.results.length > 0) {
|
|
10186
|
-
console.log(
|
|
10187
|
-
|
|
10290
|
+
console.log(
|
|
10291
|
+
chalk14.dim(
|
|
10292
|
+
` ${chalk14.cyan(`${skillSearchResult.results.length}`)} community skills available to install
|
|
10293
|
+
`
|
|
10294
|
+
)
|
|
10295
|
+
);
|
|
10188
10296
|
} else {
|
|
10189
10297
|
console.log("");
|
|
10190
10298
|
}
|
|
@@ -10220,8 +10328,12 @@ async function initCommand(options) {
|
|
|
10220
10328
|
}
|
|
10221
10329
|
const updatedFiles = collectSetupFiles(generatedSetup, targetAgent);
|
|
10222
10330
|
const restaged = stageFiles(updatedFiles, process.cwd());
|
|
10223
|
-
console.log(
|
|
10224
|
-
|
|
10331
|
+
console.log(
|
|
10332
|
+
chalk14.dim(
|
|
10333
|
+
` ${chalk14.green(`${restaged.newFiles} new`)} / ${chalk14.yellow(`${restaged.modifiedFiles} modified`)} file${restaged.newFiles + restaged.modifiedFiles !== 1 ? "s" : ""}
|
|
10334
|
+
`
|
|
10335
|
+
)
|
|
10336
|
+
);
|
|
10225
10337
|
printSetupSummary(generatedSetup);
|
|
10226
10338
|
const { openReview: openRev } = await Promise.resolve().then(() => (init_review(), review_exports));
|
|
10227
10339
|
await openRev("terminal", restaged.stagedFiles);
|
|
@@ -10247,7 +10359,8 @@ async function initCommand(options) {
|
|
|
10247
10359
|
const agentRefs = [];
|
|
10248
10360
|
if (claude) agentRefs.push("See `CLAUDE.md` for Claude Code configuration.");
|
|
10249
10361
|
if (cursor) agentRefs.push("See `.cursor/rules/` for Cursor rules.");
|
|
10250
|
-
if (agentRefs.length === 0)
|
|
10362
|
+
if (agentRefs.length === 0)
|
|
10363
|
+
agentRefs.push("See CLAUDE.md and .cursor/rules/ for agent configurations.");
|
|
10251
10364
|
const stubContent = `# AGENTS.md
|
|
10252
10365
|
|
|
10253
10366
|
This project uses AI coding agents configured by [Caliber](https://github.com/caliber-ai-org/ai-setup).
|
|
@@ -10294,24 +10407,39 @@ ${agentRefs.join(" ")}
|
|
|
10294
10407
|
if (afterScore.score < baselineScore.score) {
|
|
10295
10408
|
trackInitScoreRegression(baselineScore.score, afterScore.score);
|
|
10296
10409
|
console.log("");
|
|
10297
|
-
console.log(
|
|
10410
|
+
console.log(
|
|
10411
|
+
chalk14.yellow(
|
|
10412
|
+
` Score would drop from ${baselineScore.score} to ${afterScore.score} \u2014 reverting changes.`
|
|
10413
|
+
)
|
|
10414
|
+
);
|
|
10298
10415
|
try {
|
|
10299
10416
|
const { restored, removed } = undoSetup();
|
|
10300
10417
|
if (restored.length > 0 || removed.length > 0) {
|
|
10301
|
-
console.log(
|
|
10418
|
+
console.log(
|
|
10419
|
+
chalk14.dim(
|
|
10420
|
+
` Reverted ${restored.length + removed.length} file${restored.length + removed.length === 1 ? "" : "s"} from backup.`
|
|
10421
|
+
)
|
|
10422
|
+
);
|
|
10302
10423
|
}
|
|
10303
10424
|
} catch {
|
|
10304
10425
|
}
|
|
10305
|
-
console.log(
|
|
10426
|
+
console.log(
|
|
10427
|
+
chalk14.dim(" Run ") + chalk14.hex("#83D1EB")(`${bin} init --force`) + chalk14.dim(" to override.\n")
|
|
10428
|
+
);
|
|
10306
10429
|
return;
|
|
10307
10430
|
}
|
|
10308
10431
|
if (report) {
|
|
10309
10432
|
report.markStep("Post-write scoring");
|
|
10310
|
-
report.addSection(
|
|
10433
|
+
report.addSection(
|
|
10434
|
+
"Scoring: Post-Write",
|
|
10435
|
+
`**Score**: ${afterScore.score}/100 (delta: ${afterScore.score - baselineScore.score >= 0 ? "+" : ""}${afterScore.score - baselineScore.score})
|
|
10311
10436
|
|
|
10312
10437
|
| Check | Passed | Points | Max |
|
|
10313
10438
|
|-------|--------|--------|-----|
|
|
10314
|
-
` + afterScore.checks.map(
|
|
10439
|
+
` + afterScore.checks.map(
|
|
10440
|
+
(c) => `| ${c.name} | ${c.passed ? "Yes" : "No"} | ${c.earnedPoints} | ${c.maxPoints} |`
|
|
10441
|
+
).join("\n")
|
|
10442
|
+
);
|
|
10315
10443
|
}
|
|
10316
10444
|
recordScore(afterScore, "init");
|
|
10317
10445
|
trackInitCompleted("full-generation", afterScore.score);
|
|
@@ -10319,7 +10447,10 @@ ${agentRefs.join(" ")}
|
|
|
10319
10447
|
if (options.verbose) {
|
|
10320
10448
|
log(options.verbose, `Final score: ${afterScore.score}/100`);
|
|
10321
10449
|
for (const c of afterScore.checks.filter((ch) => !ch.passed)) {
|
|
10322
|
-
log(
|
|
10450
|
+
log(
|
|
10451
|
+
options.verbose,
|
|
10452
|
+
` Still failing: ${c.name} (${c.earnedPoints}/${c.maxPoints})${c.suggestion ? ` \u2014 ${c.suggestion}` : ""}`
|
|
10453
|
+
);
|
|
10323
10454
|
}
|
|
10324
10455
|
}
|
|
10325
10456
|
let communitySkillsInstalled = 0;
|
|
@@ -10336,14 +10467,20 @@ ${agentRefs.join(" ")}
|
|
|
10336
10467
|
const done = chalk14.green("\u2713");
|
|
10337
10468
|
console.log(chalk14.bold.green("\n Caliber is set up!\n"));
|
|
10338
10469
|
console.log(chalk14.bold(" What's configured:\n"));
|
|
10339
|
-
console.log(
|
|
10470
|
+
console.log(
|
|
10471
|
+
` ${done} Continuous sync ${chalk14.dim("pre-commit hook keeps all agent configs in sync")}`
|
|
10472
|
+
);
|
|
10340
10473
|
console.log(` ${done} Config generated ${chalk14.dim(`score: ${afterScore.score}/100`)}`);
|
|
10341
|
-
console.log(
|
|
10474
|
+
console.log(
|
|
10475
|
+
` ${done} Agent skills ${chalk14.dim("/setup-caliber for new team members")}`
|
|
10476
|
+
);
|
|
10342
10477
|
if (hasLearnableAgent) {
|
|
10343
10478
|
console.log(` ${done} Session learning ${chalk14.dim("learns from your corrections")}`);
|
|
10344
10479
|
}
|
|
10345
10480
|
if (communitySkillsInstalled > 0) {
|
|
10346
|
-
console.log(
|
|
10481
|
+
console.log(
|
|
10482
|
+
` ${done} Community skills ${chalk14.dim(`${communitySkillsInstalled} installed for your stack`)}`
|
|
10483
|
+
);
|
|
10347
10484
|
}
|
|
10348
10485
|
console.log(chalk14.bold("\n What happens next:\n"));
|
|
10349
10486
|
console.log(chalk14.dim(" Every commit syncs your agent configs automatically."));
|
|
@@ -10360,8 +10497,10 @@ ${agentRefs.join(" ")}
|
|
|
10360
10497
|
report.markStep("Finished");
|
|
10361
10498
|
const reportPath = path28.join(process.cwd(), ".caliber", "debug-report.md");
|
|
10362
10499
|
report.write(reportPath);
|
|
10363
|
-
console.log(
|
|
10364
|
-
`))
|
|
10500
|
+
console.log(
|
|
10501
|
+
chalk14.dim(` Debug report written to ${path28.relative(process.cwd(), reportPath)}
|
|
10502
|
+
`)
|
|
10503
|
+
);
|
|
10365
10504
|
}
|
|
10366
10505
|
}
|
|
10367
10506
|
|
|
@@ -10697,18 +10836,27 @@ async function scoreCommand(options) {
|
|
|
10697
10836
|
const separator = chalk18.gray(" " + "\u2500".repeat(53));
|
|
10698
10837
|
console.log(separator);
|
|
10699
10838
|
const bin = resolveCaliber();
|
|
10700
|
-
|
|
10839
|
+
const failing = result.checks.filter((c) => !c.passed && c.maxPoints > 0).sort((a, b) => b.maxPoints - b.earnedPoints - (a.maxPoints - a.earnedPoints));
|
|
10840
|
+
if (result.score < 70 && failing.length > 0) {
|
|
10841
|
+
const topFix = failing[0];
|
|
10842
|
+
const pts = topFix.maxPoints - topFix.earnedPoints;
|
|
10701
10843
|
console.log(
|
|
10702
|
-
chalk18.gray("
|
|
10844
|
+
chalk18.gray(" Biggest gain: ") + chalk18.yellow(`+${pts} pts`) + chalk18.gray(` from "${topFix.name}"`) + (topFix.suggestion ? chalk18.gray(` \u2014 ${topFix.suggestion}`) : "")
|
|
10703
10845
|
);
|
|
10704
|
-
} else if (result.score < 70) {
|
|
10705
10846
|
console.log(
|
|
10706
|
-
chalk18.gray(" Run ") + chalk18.hex("#83D1EB")(`${bin} init`) + chalk18.gray(" to
|
|
10847
|
+
chalk18.gray(" Run ") + chalk18.hex("#83D1EB")(`${bin} init`) + chalk18.gray(" to auto-fix these.")
|
|
10707
10848
|
);
|
|
10708
|
-
} else {
|
|
10849
|
+
} else if (failing.length > 0) {
|
|
10709
10850
|
console.log(
|
|
10710
|
-
chalk18.green(" Looking good!") + chalk18.gray(
|
|
10851
|
+
chalk18.green(" Looking good!") + chalk18.gray(
|
|
10852
|
+
` ${failing.length} check${failing.length === 1 ? "" : "s"} can still be improved.`
|
|
10853
|
+
)
|
|
10711
10854
|
);
|
|
10855
|
+
console.log(
|
|
10856
|
+
chalk18.gray(" Run ") + chalk18.hex("#83D1EB")(`${bin} init`) + chalk18.gray(" to improve, or ") + chalk18.hex("#83D1EB")(`${bin} regenerate`) + chalk18.gray(" to rebuild from scratch.")
|
|
10857
|
+
);
|
|
10858
|
+
} else {
|
|
10859
|
+
console.log(chalk18.green(" Perfect score! Your agent configs are fully optimized."));
|
|
10712
10860
|
}
|
|
10713
10861
|
console.log("");
|
|
10714
10862
|
}
|
package/package.json
CHANGED