@rely-ai/caliber 1.12.18 → 1.13.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.js +124 -41
- package/package.json +1 -1
package/dist/bin.js
CHANGED
|
@@ -446,9 +446,9 @@ var CONFIG_FILE_NAMES = /* @__PURE__ */ new Set([
|
|
|
446
446
|
var CONFIG_GLOBS_DIRS = [
|
|
447
447
|
{ dir: ".github/workflows", pattern: /\.ya?ml$/ }
|
|
448
448
|
];
|
|
449
|
-
var TOTAL_BUDGET =
|
|
450
|
-
var CONFIG_BUDGET = Math.floor(TOTAL_BUDGET * 0.
|
|
451
|
-
var SOURCE_BUDGET = Math.floor(TOTAL_BUDGET * 0.
|
|
449
|
+
var TOTAL_BUDGET = 4e5;
|
|
450
|
+
var CONFIG_BUDGET = Math.floor(TOTAL_BUDGET * 0.15);
|
|
451
|
+
var SOURCE_BUDGET = Math.floor(TOTAL_BUDGET * 0.85);
|
|
452
452
|
function analyzeCode(dir) {
|
|
453
453
|
const sourceFiles = [];
|
|
454
454
|
const configFiles = [];
|
|
@@ -465,27 +465,56 @@ function analyzeCode(dir) {
|
|
|
465
465
|
let sourceChars = 0;
|
|
466
466
|
let truncated = false;
|
|
467
467
|
const fileSummaries = [];
|
|
468
|
+
const MAX_CONTENT_LINE_COUNT = 300;
|
|
469
|
+
const CONTENT_BUDGET = Math.floor(SOURCE_BUDGET * 0.75);
|
|
470
|
+
const SUMMARY_BUDGET = SOURCE_BUDGET - CONTENT_BUDGET;
|
|
468
471
|
for (const relPath of sourceFiles) {
|
|
469
472
|
const fullPath = path3.join(dir, relPath);
|
|
470
|
-
let
|
|
473
|
+
let fileContent;
|
|
471
474
|
try {
|
|
472
|
-
|
|
475
|
+
fileContent = fs3.readFileSync(fullPath, "utf-8");
|
|
473
476
|
} catch {
|
|
474
477
|
continue;
|
|
475
478
|
}
|
|
476
|
-
const lineCount =
|
|
477
|
-
if (lineCount >
|
|
479
|
+
const lineCount = fileContent.split("\n").length;
|
|
480
|
+
if (lineCount > MAX_CONTENT_LINE_COUNT) continue;
|
|
478
481
|
const ext = path3.extname(relPath);
|
|
479
482
|
const language = resolveLanguage(ext);
|
|
480
483
|
if (!language) continue;
|
|
481
|
-
const summary = language === "py" ? extractPython(relPath,
|
|
484
|
+
const summary = language === "py" ? extractPython(relPath, fileContent) : extractTypeScriptJavaScript(relPath, fileContent, language);
|
|
485
|
+
summary.content = fileContent;
|
|
486
|
+
const entrySize = estimateSummarySize(summary) + fileContent.length;
|
|
487
|
+
if (sourceChars + entrySize > CONTENT_BUDGET) {
|
|
488
|
+
truncated = true;
|
|
489
|
+
break;
|
|
490
|
+
}
|
|
491
|
+
fileSummaries.push(summary);
|
|
492
|
+
sourceChars += entrySize;
|
|
493
|
+
}
|
|
494
|
+
const processedPaths = new Set(fileSummaries.map((f) => f.path));
|
|
495
|
+
let summaryChars = 0;
|
|
496
|
+
for (const relPath of sourceFiles) {
|
|
497
|
+
if (processedPaths.has(relPath)) continue;
|
|
498
|
+
const fullPath = path3.join(dir, relPath);
|
|
499
|
+
let fileContent;
|
|
500
|
+
try {
|
|
501
|
+
fileContent = fs3.readFileSync(fullPath, "utf-8");
|
|
502
|
+
} catch {
|
|
503
|
+
continue;
|
|
504
|
+
}
|
|
505
|
+
const lineCount = fileContent.split("\n").length;
|
|
506
|
+
if (lineCount > 1e3) continue;
|
|
507
|
+
const ext = path3.extname(relPath);
|
|
508
|
+
const language = resolveLanguage(ext);
|
|
509
|
+
if (!language) continue;
|
|
510
|
+
const summary = language === "py" ? extractPython(relPath, fileContent) : extractTypeScriptJavaScript(relPath, fileContent, language);
|
|
482
511
|
const summarySize = estimateSummarySize(summary);
|
|
483
|
-
if (
|
|
512
|
+
if (summaryChars + summarySize > SUMMARY_BUDGET) {
|
|
484
513
|
truncated = true;
|
|
485
514
|
break;
|
|
486
515
|
}
|
|
487
516
|
fileSummaries.push(summary);
|
|
488
|
-
|
|
517
|
+
summaryChars += summarySize;
|
|
489
518
|
}
|
|
490
519
|
return { fileSummaries, configFiles: trimmedConfigs, truncated };
|
|
491
520
|
}
|
|
@@ -2436,15 +2465,16 @@ async function generateMonolithic(fingerprint, targetAgent, prompt, callbacks, f
|
|
|
2436
2465
|
return attemptGeneration();
|
|
2437
2466
|
}
|
|
2438
2467
|
var LIMITS = {
|
|
2439
|
-
FILE_TREE_ENTRIES:
|
|
2468
|
+
FILE_TREE_ENTRIES: 500,
|
|
2440
2469
|
EXISTING_CONFIG_CHARS: 8e3,
|
|
2441
2470
|
SKILLS_MAX: 10,
|
|
2442
2471
|
SKILL_CHARS: 3e3,
|
|
2443
2472
|
RULES_MAX: 10,
|
|
2444
|
-
CONFIG_FILES_MAX:
|
|
2445
|
-
CONFIG_FILE_CHARS:
|
|
2446
|
-
ROUTES_MAX:
|
|
2447
|
-
FILE_SUMMARIES_MAX:
|
|
2473
|
+
CONFIG_FILES_MAX: 20,
|
|
2474
|
+
CONFIG_FILE_CHARS: 5e3,
|
|
2475
|
+
ROUTES_MAX: 100,
|
|
2476
|
+
FILE_SUMMARIES_MAX: 200,
|
|
2477
|
+
FILE_CONTENT_CHARS: 8e3
|
|
2448
2478
|
};
|
|
2449
2479
|
function truncate(text, maxChars) {
|
|
2450
2480
|
if (text.length <= maxChars) return text;
|
|
@@ -2575,9 +2605,19 @@ ${truncate(cfg.content, LIMITS.CONFIG_FILE_CHARS)}`);
|
|
|
2575
2605
|
parts.push(`(${allRoutes.length - LIMITS.ROUTES_MAX} more routes omitted)`);
|
|
2576
2606
|
}
|
|
2577
2607
|
}
|
|
2578
|
-
|
|
2608
|
+
const filesWithContent = ca.fileSummaries.filter((f) => f.content);
|
|
2609
|
+
const filesWithoutContent = ca.fileSummaries.filter((f) => !f.content);
|
|
2610
|
+
if (filesWithContent.length > 0) {
|
|
2611
|
+
parts.push("\n--- Source Files (full content \u2014 use these to extract patterns for skills) ---");
|
|
2612
|
+
for (const f of filesWithContent.slice(0, LIMITS.FILE_SUMMARIES_MAX)) {
|
|
2613
|
+
parts.push(`
|
|
2614
|
+
[${f.path}] (${f.language})`);
|
|
2615
|
+
parts.push(truncate(f.content, LIMITS.FILE_CONTENT_CHARS));
|
|
2616
|
+
}
|
|
2617
|
+
}
|
|
2618
|
+
if (filesWithoutContent.length > 0) {
|
|
2579
2619
|
parts.push("\n--- Source File Summaries ---");
|
|
2580
|
-
for (const f of
|
|
2620
|
+
for (const f of filesWithoutContent.slice(0, LIMITS.FILE_SUMMARIES_MAX)) {
|
|
2581
2621
|
const sections = [`[${f.path}] (${f.language})`];
|
|
2582
2622
|
if (f.imports.length > 0) sections.push(` imports: ${f.imports.slice(0, 10).join("; ")}`);
|
|
2583
2623
|
if (f.exports.length > 0) sections.push(` exports: ${f.exports.slice(0, 10).join(", ")}`);
|
|
@@ -2586,9 +2626,9 @@ ${truncate(cfg.content, LIMITS.CONFIG_FILE_CHARS)}`);
|
|
|
2586
2626
|
if (f.types.length > 0) sections.push(` types: ${f.types.slice(0, 10).join(", ")}`);
|
|
2587
2627
|
parts.push(sections.join("\n"));
|
|
2588
2628
|
}
|
|
2589
|
-
if (
|
|
2629
|
+
if (filesWithoutContent.length > LIMITS.FILE_SUMMARIES_MAX) {
|
|
2590
2630
|
parts.push(`
|
|
2591
|
-
(${
|
|
2631
|
+
(${filesWithoutContent.length - LIMITS.FILE_SUMMARIES_MAX} more files omitted)`);
|
|
2592
2632
|
}
|
|
2593
2633
|
}
|
|
2594
2634
|
if (ca.truncated) {
|
|
@@ -2598,7 +2638,7 @@ ${truncate(cfg.content, LIMITS.CONFIG_FILE_CHARS)}`);
|
|
|
2598
2638
|
const allDeps = extractAllDeps(process.cwd());
|
|
2599
2639
|
if (allDeps.length > 0) {
|
|
2600
2640
|
parts.push(`
|
|
2601
|
-
|
|
2641
|
+
Project dependencies (${allDeps.length}):`);
|
|
2602
2642
|
parts.push(allDeps.join(", "));
|
|
2603
2643
|
}
|
|
2604
2644
|
if (prompt) parts.push(`
|
|
@@ -3755,7 +3795,7 @@ async function runInteractiveProviderSetup(options) {
|
|
|
3755
3795
|
}
|
|
3756
3796
|
|
|
3757
3797
|
// src/scoring/index.ts
|
|
3758
|
-
import { existsSync as
|
|
3798
|
+
import { existsSync as existsSync7 } from "fs";
|
|
3759
3799
|
import { join as join8 } from "path";
|
|
3760
3800
|
|
|
3761
3801
|
// src/scoring/checks/existence.ts
|
|
@@ -4104,12 +4144,25 @@ function collectProjectStructure(dir, maxDepth = 2) {
|
|
|
4104
4144
|
walk(dir, 0);
|
|
4105
4145
|
return { dirs, files };
|
|
4106
4146
|
}
|
|
4107
|
-
function
|
|
4147
|
+
function collectPrimaryConfigContent(dir) {
|
|
4108
4148
|
const parts = [];
|
|
4109
4149
|
for (const file of ["CLAUDE.md", ".cursorrules", "AGENTS.md"]) {
|
|
4110
4150
|
const content = readFileOrNull2(join3(dir, file));
|
|
4111
4151
|
if (content) parts.push(content);
|
|
4112
4152
|
}
|
|
4153
|
+
try {
|
|
4154
|
+
const rulesDir = join3(dir, ".cursor", "rules");
|
|
4155
|
+
const mdcFiles = readdirSync2(rulesDir).filter((f) => f.endsWith(".mdc"));
|
|
4156
|
+
for (const f of mdcFiles) {
|
|
4157
|
+
const content = readFileOrNull2(join3(rulesDir, f));
|
|
4158
|
+
if (content) parts.push(content);
|
|
4159
|
+
}
|
|
4160
|
+
} catch {
|
|
4161
|
+
}
|
|
4162
|
+
return parts.join("\n");
|
|
4163
|
+
}
|
|
4164
|
+
function collectAllConfigContent(dir) {
|
|
4165
|
+
const parts = [collectPrimaryConfigContent(dir)];
|
|
4113
4166
|
for (const skillsDir of [join3(dir, ".claude", "skills"), join3(dir, ".agents", "skills")]) {
|
|
4114
4167
|
try {
|
|
4115
4168
|
const entries = readdirSync2(skillsDir, { withFileTypes: true });
|
|
@@ -4125,15 +4178,6 @@ function collectAllConfigContent(dir) {
|
|
|
4125
4178
|
} catch {
|
|
4126
4179
|
}
|
|
4127
4180
|
}
|
|
4128
|
-
try {
|
|
4129
|
-
const rulesDir = join3(dir, ".cursor", "rules");
|
|
4130
|
-
const mdcFiles = readdirSync2(rulesDir).filter((f) => f.endsWith(".mdc"));
|
|
4131
|
-
for (const f of mdcFiles) {
|
|
4132
|
-
const content = readFileOrNull2(join3(rulesDir, f));
|
|
4133
|
-
if (content) parts.push(content);
|
|
4134
|
-
}
|
|
4135
|
-
} catch {
|
|
4136
|
-
}
|
|
4137
4181
|
return parts.join("\n");
|
|
4138
4182
|
}
|
|
4139
4183
|
function estimateTokens2(text) {
|
|
@@ -4249,7 +4293,7 @@ function checkQuality(dir) {
|
|
|
4249
4293
|
instruction: `Add code blocks with executable commands. Currently ${codeBlockCount}, need at least 3 for full points.`
|
|
4250
4294
|
} : void 0
|
|
4251
4295
|
});
|
|
4252
|
-
const totalContent =
|
|
4296
|
+
const totalContent = collectPrimaryConfigContent(dir);
|
|
4253
4297
|
const totalTokens = estimateTokens2(totalContent);
|
|
4254
4298
|
const tokenThreshold = TOKEN_BUDGET_THRESHOLDS.find((t) => totalTokens <= t.maxTokens);
|
|
4255
4299
|
const tokenPoints = totalContent.length === 0 ? POINTS_CONCISE_CONFIG : tokenThreshold?.points ?? 0;
|
|
@@ -4481,11 +4525,11 @@ function checkGrounding(dir) {
|
|
|
4481
4525
|
}
|
|
4482
4526
|
|
|
4483
4527
|
// src/scoring/checks/accuracy.ts
|
|
4484
|
-
import { existsSync as existsSync4 } from "fs";
|
|
4528
|
+
import { existsSync as existsSync4, statSync as statSync2 } from "fs";
|
|
4485
4529
|
import { execSync as execSync8 } from "child_process";
|
|
4486
4530
|
import { join as join5 } from "path";
|
|
4487
4531
|
function validateReferences(dir) {
|
|
4488
|
-
const configContent =
|
|
4532
|
+
const configContent = collectPrimaryConfigContent(dir);
|
|
4489
4533
|
if (!configContent) return { valid: [], invalid: [], total: 0 };
|
|
4490
4534
|
const refs = extractReferences(configContent);
|
|
4491
4535
|
const valid = [];
|
|
@@ -4519,6 +4563,25 @@ function detectGitDrift(dir) {
|
|
|
4519
4563
|
return { commitsSinceConfigUpdate: 0, lastConfigCommit: null, isGitRepo: false };
|
|
4520
4564
|
}
|
|
4521
4565
|
const configFiles = ["CLAUDE.md", "AGENTS.md", ".cursorrules", ".cursor/rules"];
|
|
4566
|
+
try {
|
|
4567
|
+
const headTimestamp = execSync8(
|
|
4568
|
+
"git log -1 --format=%ct HEAD",
|
|
4569
|
+
{ cwd: dir, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
4570
|
+
).trim();
|
|
4571
|
+
const headTime = parseInt(headTimestamp, 10) * 1e3;
|
|
4572
|
+
for (const file of configFiles) {
|
|
4573
|
+
const filePath = join5(dir, file);
|
|
4574
|
+
if (!existsSync4(filePath)) continue;
|
|
4575
|
+
try {
|
|
4576
|
+
const mtime = statSync2(filePath).mtime.getTime();
|
|
4577
|
+
if (mtime > headTime) {
|
|
4578
|
+
return { commitsSinceConfigUpdate: 0, lastConfigCommit: "uncommitted (recently modified)", isGitRepo: true };
|
|
4579
|
+
}
|
|
4580
|
+
} catch {
|
|
4581
|
+
}
|
|
4582
|
+
}
|
|
4583
|
+
} catch {
|
|
4584
|
+
}
|
|
4522
4585
|
let latestConfigCommitHash = null;
|
|
4523
4586
|
for (const file of configFiles) {
|
|
4524
4587
|
try {
|
|
@@ -4622,10 +4685,30 @@ function checkAccuracy(dir) {
|
|
|
4622
4685
|
}
|
|
4623
4686
|
|
|
4624
4687
|
// src/scoring/checks/freshness.ts
|
|
4688
|
+
import { existsSync as existsSync5, statSync as statSync3 } from "fs";
|
|
4625
4689
|
import { execSync as execSync9 } from "child_process";
|
|
4626
4690
|
import { join as join6 } from "path";
|
|
4627
4691
|
function getCommitsSinceConfigUpdate(dir) {
|
|
4628
4692
|
const configFiles = ["CLAUDE.md", "AGENTS.md", ".cursorrules"];
|
|
4693
|
+
try {
|
|
4694
|
+
const headTimestamp = execSync9(
|
|
4695
|
+
"git log -1 --format=%ct HEAD",
|
|
4696
|
+
{ cwd: dir, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
4697
|
+
).trim();
|
|
4698
|
+
const headTime = parseInt(headTimestamp, 10) * 1e3;
|
|
4699
|
+
for (const file of configFiles) {
|
|
4700
|
+
const filePath = join6(dir, file);
|
|
4701
|
+
if (!existsSync5(filePath)) continue;
|
|
4702
|
+
try {
|
|
4703
|
+
const mtime = statSync3(filePath).mtime.getTime();
|
|
4704
|
+
if (mtime > headTime) {
|
|
4705
|
+
return 0;
|
|
4706
|
+
}
|
|
4707
|
+
} catch {
|
|
4708
|
+
}
|
|
4709
|
+
}
|
|
4710
|
+
} catch {
|
|
4711
|
+
}
|
|
4629
4712
|
for (const file of configFiles) {
|
|
4630
4713
|
try {
|
|
4631
4714
|
const hash = execSync9(
|
|
@@ -4750,7 +4833,7 @@ function checkFreshness(dir) {
|
|
|
4750
4833
|
}
|
|
4751
4834
|
|
|
4752
4835
|
// src/scoring/checks/bonus.ts
|
|
4753
|
-
import { existsSync as
|
|
4836
|
+
import { existsSync as existsSync6, readdirSync as readdirSync3 } from "fs";
|
|
4754
4837
|
import { execSync as execSync10 } from "child_process";
|
|
4755
4838
|
import { join as join7 } from "path";
|
|
4756
4839
|
function hasPreCommitHook(dir) {
|
|
@@ -4800,7 +4883,7 @@ function checkBonus(dir) {
|
|
|
4800
4883
|
instruction: "Install caliber hooks for automatic config refresh on commits."
|
|
4801
4884
|
}
|
|
4802
4885
|
});
|
|
4803
|
-
const agentsMdExists =
|
|
4886
|
+
const agentsMdExists = existsSync6(join7(dir, "AGENTS.md"));
|
|
4804
4887
|
checks.push({
|
|
4805
4888
|
id: "agents_md_exists",
|
|
4806
4889
|
name: "AGENTS.md exists",
|
|
@@ -4898,9 +4981,9 @@ function filterChecksForTarget(checks, target) {
|
|
|
4898
4981
|
}
|
|
4899
4982
|
function detectTargetAgent(dir) {
|
|
4900
4983
|
const agents = [];
|
|
4901
|
-
if (
|
|
4902
|
-
if (
|
|
4903
|
-
if (
|
|
4984
|
+
if (existsSync7(join8(dir, "CLAUDE.md")) || existsSync7(join8(dir, ".claude", "skills"))) agents.push("claude");
|
|
4985
|
+
if (existsSync7(join8(dir, ".cursorrules")) || existsSync7(join8(dir, ".cursor", "rules"))) agents.push("cursor");
|
|
4986
|
+
if (existsSync7(join8(dir, ".codex")) || existsSync7(join8(dir, ".agents", "skills"))) agents.push("codex");
|
|
4904
4987
|
return agents.length > 0 ? agents : ["claude"];
|
|
4905
4988
|
}
|
|
4906
4989
|
function computeLocalScore(dir, targetAgent) {
|
|
@@ -5064,7 +5147,7 @@ function displayScoreDelta(before, after) {
|
|
|
5064
5147
|
import chalk7 from "chalk";
|
|
5065
5148
|
import ora from "ora";
|
|
5066
5149
|
import select4 from "@inquirer/select";
|
|
5067
|
-
import { mkdirSync, readFileSync as readFileSync4, readdirSync as readdirSync4, existsSync as
|
|
5150
|
+
import { mkdirSync, readFileSync as readFileSync4, readdirSync as readdirSync4, existsSync as existsSync8, writeFileSync } from "fs";
|
|
5068
5151
|
import { join as join9, dirname as dirname2 } from "path";
|
|
5069
5152
|
|
|
5070
5153
|
// src/scanner/index.ts
|
|
@@ -5565,7 +5648,7 @@ Already installed skills: ${Array.from(installed).join(", ")}`);
|
|
|
5565
5648
|
}
|
|
5566
5649
|
function extractTopDeps() {
|
|
5567
5650
|
const pkgPath = join9(process.cwd(), "package.json");
|
|
5568
|
-
if (!
|
|
5651
|
+
if (!existsSync8(pkgPath)) return [];
|
|
5569
5652
|
try {
|
|
5570
5653
|
const pkg3 = JSON.parse(readFileSync4(pkgPath, "utf-8"));
|
|
5571
5654
|
const deps = Object.keys(pkg3.dependencies ?? {});
|
package/package.json
CHANGED