@rely-ai/caliber 1.17.0 → 1.18.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 +340 -174
- package/package.json +1 -1
package/dist/bin.js
CHANGED
|
@@ -396,6 +396,7 @@ function readExistingConfigs(dir) {
|
|
|
396
396
|
// src/fingerprint/code-analysis.ts
|
|
397
397
|
import fs3 from "fs";
|
|
398
398
|
import path3 from "path";
|
|
399
|
+
import { execSync as execSync2 } from "child_process";
|
|
399
400
|
var IGNORE_DIRS2 = /* @__PURE__ */ new Set([
|
|
400
401
|
"node_modules",
|
|
401
402
|
".git",
|
|
@@ -503,59 +504,78 @@ var SKIP_PATTERNS = [
|
|
|
503
504
|
/\.generated\./,
|
|
504
505
|
/\.snap$/
|
|
505
506
|
];
|
|
506
|
-
var
|
|
507
|
-
"c
|
|
508
|
-
|
|
509
|
-
"
|
|
510
|
-
// py, sh, yaml, tf, etc.
|
|
511
|
-
"html": /^\s*<!--.*-->\s*$/
|
|
507
|
+
var COMMENT_LINE = {
|
|
508
|
+
"c": /^\s*\/\//,
|
|
509
|
+
"h": /^\s*#/,
|
|
510
|
+
"x": /^\s*<!--.*-->\s*$/
|
|
512
511
|
};
|
|
513
|
-
var
|
|
514
|
-
".ts": "c
|
|
515
|
-
".tsx": "c
|
|
516
|
-
".js": "c
|
|
517
|
-
".jsx": "c
|
|
518
|
-
".mjs": "c
|
|
519
|
-
".cjs": "c
|
|
520
|
-
".go": "c
|
|
521
|
-
".rs": "c
|
|
522
|
-
".java": "c
|
|
523
|
-
".kt": "c
|
|
524
|
-
".scala": "c
|
|
525
|
-
".cs": "c
|
|
526
|
-
".c": "c
|
|
527
|
-
".cpp": "c
|
|
528
|
-
".h": "c
|
|
529
|
-
".hpp": "c
|
|
530
|
-
".swift": "c
|
|
531
|
-
".php": "c
|
|
532
|
-
".py": "
|
|
533
|
-
".pyw": "
|
|
534
|
-
".rb": "
|
|
535
|
-
".sh": "
|
|
536
|
-
".bash": "
|
|
537
|
-
".zsh": "
|
|
538
|
-
".fish": "
|
|
539
|
-
".r": "
|
|
540
|
-
".tf": "
|
|
541
|
-
".hcl": "
|
|
542
|
-
".yaml": "
|
|
543
|
-
".yml": "
|
|
544
|
-
".toml": "
|
|
545
|
-
".ini": "
|
|
546
|
-
".cfg": "
|
|
547
|
-
".env": "
|
|
548
|
-
".html": "
|
|
549
|
-
".xml": "
|
|
550
|
-
".
|
|
551
|
-
".
|
|
552
|
-
".svelte": "html"
|
|
512
|
+
var EXT_COMMENT = {
|
|
513
|
+
".ts": "c",
|
|
514
|
+
".tsx": "c",
|
|
515
|
+
".js": "c",
|
|
516
|
+
".jsx": "c",
|
|
517
|
+
".mjs": "c",
|
|
518
|
+
".cjs": "c",
|
|
519
|
+
".go": "c",
|
|
520
|
+
".rs": "c",
|
|
521
|
+
".java": "c",
|
|
522
|
+
".kt": "c",
|
|
523
|
+
".scala": "c",
|
|
524
|
+
".cs": "c",
|
|
525
|
+
".c": "c",
|
|
526
|
+
".cpp": "c",
|
|
527
|
+
".h": "c",
|
|
528
|
+
".hpp": "c",
|
|
529
|
+
".swift": "c",
|
|
530
|
+
".php": "c",
|
|
531
|
+
".py": "h",
|
|
532
|
+
".pyw": "h",
|
|
533
|
+
".rb": "h",
|
|
534
|
+
".sh": "h",
|
|
535
|
+
".bash": "h",
|
|
536
|
+
".zsh": "h",
|
|
537
|
+
".fish": "h",
|
|
538
|
+
".r": "h",
|
|
539
|
+
".tf": "h",
|
|
540
|
+
".hcl": "h",
|
|
541
|
+
".yaml": "h",
|
|
542
|
+
".yml": "h",
|
|
543
|
+
".toml": "h",
|
|
544
|
+
".ini": "h",
|
|
545
|
+
".cfg": "h",
|
|
546
|
+
".env": "h",
|
|
547
|
+
".html": "x",
|
|
548
|
+
".xml": "x",
|
|
549
|
+
".vue": "x",
|
|
550
|
+
".svelte": "x"
|
|
553
551
|
};
|
|
552
|
+
var SOURCE_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
553
|
+
".ts",
|
|
554
|
+
".tsx",
|
|
555
|
+
".js",
|
|
556
|
+
".jsx",
|
|
557
|
+
".mjs",
|
|
558
|
+
".cjs",
|
|
559
|
+
".py",
|
|
560
|
+
".pyw",
|
|
561
|
+
".go",
|
|
562
|
+
".rs",
|
|
563
|
+
".rb",
|
|
564
|
+
".java",
|
|
565
|
+
".kt",
|
|
566
|
+
".scala",
|
|
567
|
+
".cs",
|
|
568
|
+
".c",
|
|
569
|
+
".cpp",
|
|
570
|
+
".h",
|
|
571
|
+
".hpp",
|
|
572
|
+
".swift",
|
|
573
|
+
".php"
|
|
574
|
+
]);
|
|
554
575
|
var TOKEN_BUDGET = 18e4;
|
|
555
576
|
var CHAR_BUDGET = TOKEN_BUDGET * 4;
|
|
556
577
|
function compressContent(content, ext) {
|
|
557
|
-
const
|
|
558
|
-
const commentPattern = commentStyle ? COMMENT_LINE_PATTERNS[commentStyle] : null;
|
|
578
|
+
const cp = EXT_COMMENT[ext] ? COMMENT_LINE[EXT_COMMENT[ext]] : null;
|
|
559
579
|
const lines = content.split("\n");
|
|
560
580
|
const result = [];
|
|
561
581
|
let prevBlank = false;
|
|
@@ -577,12 +597,11 @@ function compressContent(content, ext) {
|
|
|
577
597
|
continue;
|
|
578
598
|
}
|
|
579
599
|
prevBlank = false;
|
|
580
|
-
if (
|
|
581
|
-
const
|
|
582
|
-
if (
|
|
583
|
-
const spaces =
|
|
584
|
-
|
|
585
|
-
result.push(normalizedIndent + line.trimStart().trimEnd());
|
|
600
|
+
if (cp && cp.test(trimmed)) continue;
|
|
601
|
+
const leading = line.match(/^(\s*)/);
|
|
602
|
+
if (leading) {
|
|
603
|
+
const spaces = leading[1].replace(/\t/g, " ").length;
|
|
604
|
+
result.push(" ".repeat(Math.floor(spaces / 2) * 2) + line.trimStart().trimEnd());
|
|
586
605
|
} else {
|
|
587
606
|
result.push(trimmed);
|
|
588
607
|
}
|
|
@@ -590,99 +609,254 @@ function compressContent(content, ext) {
|
|
|
590
609
|
while (result.length > 0 && result[result.length - 1] === "") result.pop();
|
|
591
610
|
return result.join("\n");
|
|
592
611
|
}
|
|
593
|
-
function
|
|
594
|
-
|
|
595
|
-
const
|
|
596
|
-
const
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
}
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
612
|
+
function extractSkeleton(content, ext) {
|
|
613
|
+
if (!SOURCE_EXTENSIONS.has(ext)) return content;
|
|
614
|
+
const lines = content.split("\n");
|
|
615
|
+
const result = [];
|
|
616
|
+
let braceDepth = 0;
|
|
617
|
+
let inSignature = false;
|
|
618
|
+
let skipBody = false;
|
|
619
|
+
if ([".py", ".pyw", ".rb"].includes(ext)) {
|
|
620
|
+
return extractSkeletonIndentBased(lines, ext);
|
|
621
|
+
}
|
|
622
|
+
for (let i = 0; i < lines.length; i++) {
|
|
623
|
+
const line = lines[i];
|
|
624
|
+
const trimmed = line.trim();
|
|
625
|
+
if (/^\s*(import |from |require\(|use |package |module )/.test(line)) {
|
|
626
|
+
result.push(line);
|
|
627
|
+
continue;
|
|
628
|
+
}
|
|
629
|
+
if (/^\s*(export\s+)?(interface|type|enum)\s/.test(trimmed)) {
|
|
630
|
+
result.push(line);
|
|
631
|
+
let depth = 0;
|
|
632
|
+
for (let j = i; j < lines.length; j++) {
|
|
633
|
+
if (j > i) result.push(lines[j]);
|
|
634
|
+
depth += (lines[j].match(/{/g) || []).length;
|
|
635
|
+
depth -= (lines[j].match(/}/g) || []).length;
|
|
636
|
+
if (depth <= 0 && j > i) {
|
|
637
|
+
i = j;
|
|
638
|
+
break;
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
continue;
|
|
642
|
+
}
|
|
643
|
+
const isFnOrClass = /^\s*(export\s+)?(default\s+)?(async\s+)?(function|class|const\s+\w+\s*=\s*(async\s*)?\(|pub\s+fn|fn|func)\s/.test(trimmed) || /^\s*(def|func|fn|pub fn|pub async fn)\s/.test(trimmed);
|
|
644
|
+
if (isFnOrClass && braceDepth === 0) {
|
|
645
|
+
result.push(line);
|
|
646
|
+
const opens = (line.match(/{/g) || []).length;
|
|
647
|
+
const closes = (line.match(/}/g) || []).length;
|
|
648
|
+
if (opens > closes) {
|
|
649
|
+
skipBody = true;
|
|
650
|
+
braceDepth = opens - closes;
|
|
651
|
+
result.push(" ".repeat(line.search(/\S/)) + " // ...");
|
|
652
|
+
}
|
|
653
|
+
continue;
|
|
654
|
+
}
|
|
655
|
+
if (skipBody) {
|
|
656
|
+
braceDepth += (line.match(/{/g) || []).length;
|
|
657
|
+
braceDepth -= (line.match(/}/g) || []).length;
|
|
658
|
+
if (braceDepth <= 0) {
|
|
659
|
+
result.push(line);
|
|
660
|
+
skipBody = false;
|
|
661
|
+
braceDepth = 0;
|
|
662
|
+
}
|
|
663
|
+
continue;
|
|
664
|
+
}
|
|
665
|
+
if (braceDepth === 0) {
|
|
666
|
+
result.push(line);
|
|
667
|
+
}
|
|
610
668
|
}
|
|
669
|
+
return result.join("\n");
|
|
670
|
+
}
|
|
671
|
+
function extractSkeletonIndentBased(lines, ext) {
|
|
611
672
|
const result = [];
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
673
|
+
let skipIndent = -1;
|
|
674
|
+
for (const line of lines) {
|
|
675
|
+
const trimmed = line.trim();
|
|
676
|
+
if (trimmed.length === 0) continue;
|
|
677
|
+
const indent = line.search(/\S/);
|
|
678
|
+
if (/^(import |from )/.test(trimmed)) {
|
|
679
|
+
result.push(line);
|
|
680
|
+
skipIndent = -1;
|
|
681
|
+
continue;
|
|
682
|
+
}
|
|
683
|
+
if (/^(class |def |async def )/.test(trimmed)) {
|
|
684
|
+
result.push(line);
|
|
685
|
+
skipIndent = indent;
|
|
686
|
+
continue;
|
|
687
|
+
}
|
|
688
|
+
if (trimmed.startsWith("@")) {
|
|
689
|
+
result.push(line);
|
|
690
|
+
skipIndent = -1;
|
|
691
|
+
continue;
|
|
692
|
+
}
|
|
693
|
+
if (skipIndent >= 0 && indent > skipIndent) {
|
|
694
|
+
continue;
|
|
695
|
+
}
|
|
696
|
+
skipIndent = -1;
|
|
697
|
+
result.push(line);
|
|
698
|
+
}
|
|
699
|
+
return result.join("\n");
|
|
700
|
+
}
|
|
701
|
+
function extractImports(content, filePath) {
|
|
702
|
+
const imports = [];
|
|
703
|
+
const dir = path3.dirname(filePath);
|
|
704
|
+
for (const line of content.split("\n")) {
|
|
705
|
+
const trimmed = line.trim();
|
|
706
|
+
const jsMatch = trimmed.match(/(?:from|require\()\s*['"]([^'"]+)['"]/);
|
|
707
|
+
if (jsMatch && jsMatch[1].startsWith(".")) {
|
|
708
|
+
imports.push(path3.normalize(path3.join(dir, jsMatch[1])));
|
|
709
|
+
continue;
|
|
710
|
+
}
|
|
711
|
+
const pyMatch = trimmed.match(/^from\s+(\.[.\w]*)\s+import/);
|
|
712
|
+
if (pyMatch) {
|
|
713
|
+
const modulePath = pyMatch[1].replace(/\./g, "/");
|
|
714
|
+
imports.push(path3.normalize(path3.join(dir, modulePath)));
|
|
715
|
+
continue;
|
|
716
|
+
}
|
|
717
|
+
const goMatch = trimmed.match(/^\s*"([^"]+)"/);
|
|
718
|
+
if (goMatch && !goMatch[1].includes(".")) {
|
|
719
|
+
imports.push(goMatch[1]);
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
return imports;
|
|
723
|
+
}
|
|
724
|
+
function buildImportCounts(files) {
|
|
725
|
+
const counts = /* @__PURE__ */ new Map();
|
|
726
|
+
for (const [filePath, content] of files) {
|
|
727
|
+
const ext = path3.extname(filePath).toLowerCase();
|
|
728
|
+
if (!SOURCE_EXTENSIONS.has(ext)) continue;
|
|
729
|
+
const imports = extractImports(content, filePath);
|
|
730
|
+
for (const imp of imports) {
|
|
731
|
+
const candidates = [imp, imp + ".ts", imp + ".js", imp + ".tsx", imp + ".jsx", imp + "/index.ts", imp + "/index.js", imp + ".py"];
|
|
732
|
+
for (const candidate of candidates) {
|
|
733
|
+
const normalized = candidate.replace(/\\/g, "/");
|
|
734
|
+
if (files.has(normalized)) {
|
|
735
|
+
counts.set(normalized, (counts.get(normalized) || 0) + 1);
|
|
736
|
+
break;
|
|
737
|
+
}
|
|
738
|
+
}
|
|
627
739
|
}
|
|
628
740
|
}
|
|
629
|
-
return
|
|
741
|
+
return counts;
|
|
742
|
+
}
|
|
743
|
+
function getGitFrequency(dir) {
|
|
744
|
+
const freq = /* @__PURE__ */ new Map();
|
|
745
|
+
try {
|
|
746
|
+
const output = execSync2(
|
|
747
|
+
'git log --since="6 months ago" --format="" --name-only --diff-filter=ACMR 2>/dev/null | head -10000',
|
|
748
|
+
{ cwd: dir, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"], timeout: 5e3 }
|
|
749
|
+
);
|
|
750
|
+
for (const line of output.split("\n")) {
|
|
751
|
+
const trimmed = line.trim();
|
|
752
|
+
if (trimmed) freq.set(trimmed, (freq.get(trimmed) || 0) + 1);
|
|
753
|
+
}
|
|
754
|
+
} catch {
|
|
755
|
+
}
|
|
756
|
+
return freq;
|
|
757
|
+
}
|
|
758
|
+
function groupByDirectory(files) {
|
|
759
|
+
const groups = /* @__PURE__ */ new Map();
|
|
760
|
+
for (const f of files) {
|
|
761
|
+
const dir = path3.dirname(f.path);
|
|
762
|
+
const group = groups.get(dir) || [];
|
|
763
|
+
group.push(f);
|
|
764
|
+
groups.set(dir, group);
|
|
765
|
+
}
|
|
766
|
+
return groups;
|
|
767
|
+
}
|
|
768
|
+
function structuralFingerprint(content, ext) {
|
|
769
|
+
const lines = content.split("\n").filter((l) => l.trim().length > 0);
|
|
770
|
+
const bucket = Math.floor(lines.length / 10) * 10;
|
|
771
|
+
const first = (lines[0] || "").trim().slice(0, 50);
|
|
772
|
+
const imports = lines.filter((l) => /^\s*(import |from |require\(|use )/.test(l)).length;
|
|
773
|
+
const fns = lines.filter((l) => /^\s*(export\s+)?(async\s+)?(function |def |func |fn |pub fn |class )/.test(l)).length;
|
|
774
|
+
return `${ext}:${bucket}:${imports}:${fns}:${first}`;
|
|
630
775
|
}
|
|
631
776
|
function analyzeCode(dir) {
|
|
632
|
-
const
|
|
633
|
-
walkDir(dir, "", 0, 10,
|
|
634
|
-
sortByPriority(allFiles);
|
|
777
|
+
const allPaths = [];
|
|
778
|
+
walkDir(dir, "", 0, 10, allPaths);
|
|
635
779
|
let totalChars = 0;
|
|
636
|
-
for (const relPath of
|
|
780
|
+
for (const relPath of allPaths) {
|
|
637
781
|
try {
|
|
638
|
-
|
|
639
|
-
totalChars += stat.size;
|
|
782
|
+
totalChars += fs3.statSync(path3.join(dir, relPath)).size;
|
|
640
783
|
} catch {
|
|
641
784
|
}
|
|
642
785
|
}
|
|
643
|
-
const
|
|
644
|
-
|
|
645
|
-
for (const relPath of allFiles) {
|
|
646
|
-
const fullPath = path3.join(dir, relPath);
|
|
647
|
-
let rawContent;
|
|
786
|
+
const fileContents = /* @__PURE__ */ new Map();
|
|
787
|
+
for (const relPath of allPaths) {
|
|
648
788
|
try {
|
|
649
|
-
|
|
789
|
+
const content = fs3.readFileSync(path3.join(dir, relPath), "utf-8");
|
|
790
|
+
if (content.split("\n").length <= 500) fileContents.set(relPath, content);
|
|
650
791
|
} catch {
|
|
651
|
-
continue;
|
|
652
792
|
}
|
|
653
|
-
|
|
793
|
+
}
|
|
794
|
+
const importCounts = buildImportCounts(fileContents);
|
|
795
|
+
const gitFreq = getGitFrequency(dir);
|
|
796
|
+
const scored = [];
|
|
797
|
+
let compressedChars = 0;
|
|
798
|
+
for (const [relPath, rawContent] of fileContents) {
|
|
654
799
|
const ext = path3.extname(relPath).toLowerCase();
|
|
655
800
|
const compressed = compressContent(rawContent, ext);
|
|
801
|
+
const skeleton = extractSkeleton(compressed, ext);
|
|
656
802
|
compressedChars += compressed.length;
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
const
|
|
665
|
-
const
|
|
803
|
+
const priorityScore = filePriority(relPath);
|
|
804
|
+
const importScore = Math.min(importCounts.get(relPath) || 0, 20) * 2;
|
|
805
|
+
const gitScore = Math.min(gitFreq.get(relPath) || 0, 10) * 3;
|
|
806
|
+
const score = priorityScore + importScore + gitScore;
|
|
807
|
+
scored.push({ path: relPath, rawContent, compressed, skeleton, ext, score });
|
|
808
|
+
}
|
|
809
|
+
scored.sort((a, b) => b.score - a.score);
|
|
810
|
+
const dirGroups = groupByDirectory(scored);
|
|
811
|
+
const result = [];
|
|
666
812
|
let includedChars = 0;
|
|
667
|
-
let
|
|
668
|
-
const
|
|
669
|
-
|
|
670
|
-
const
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
813
|
+
let dupGroups = 0;
|
|
814
|
+
for (const [dirPath, group] of dirGroups) {
|
|
815
|
+
if (group.length === 0) continue;
|
|
816
|
+
const rep = group[0];
|
|
817
|
+
const repFP = structuralFingerprint(rep.compressed, rep.ext);
|
|
818
|
+
const similar = group.slice(1).filter((f) => structuralFingerprint(f.compressed, f.ext) === repFP);
|
|
819
|
+
const unique = group.slice(1).filter((f) => structuralFingerprint(f.compressed, f.ext) !== repFP);
|
|
820
|
+
const repEntry = { path: rep.path, content: rep.compressed, size: rep.compressed.length };
|
|
821
|
+
const repSize = rep.path.length + rep.compressed.length + 10;
|
|
822
|
+
if (includedChars + repSize <= CHAR_BUDGET) {
|
|
823
|
+
result.push(repEntry);
|
|
824
|
+
includedChars += repSize;
|
|
825
|
+
}
|
|
826
|
+
if (similar.length > 0) {
|
|
827
|
+
dupGroups++;
|
|
828
|
+
const names = similar.map((f) => path3.basename(f.path));
|
|
829
|
+
const summary = `(${similar.length} similar file${similar.length === 1 ? "" : "s"} in ${dirPath}/: ${names.join(", ")})`;
|
|
830
|
+
const summarySize = summary.length + 30;
|
|
831
|
+
if (includedChars + summarySize <= CHAR_BUDGET) {
|
|
832
|
+
result.push({ path: `[similar to ${rep.path}]`, content: summary, size: summary.length });
|
|
833
|
+
includedChars += summarySize;
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
for (const f of unique) {
|
|
837
|
+
const skeletonSize = f.path.length + f.skeleton.length + 10;
|
|
838
|
+
if (includedChars + skeletonSize <= CHAR_BUDGET) {
|
|
839
|
+
result.push({ path: f.path, content: f.skeleton, size: f.skeleton.length });
|
|
840
|
+
includedChars += skeletonSize;
|
|
841
|
+
}
|
|
674
842
|
}
|
|
675
|
-
|
|
676
|
-
|
|
843
|
+
}
|
|
844
|
+
const includedPaths = new Set(result.map((f) => f.path));
|
|
845
|
+
for (const f of scored) {
|
|
846
|
+
if (includedPaths.has(f.path)) continue;
|
|
847
|
+
const skeletonSize = f.path.length + f.skeleton.length + 10;
|
|
848
|
+
if (includedChars + skeletonSize > CHAR_BUDGET) continue;
|
|
849
|
+
result.push({ path: f.path, content: f.skeleton, size: f.skeleton.length });
|
|
850
|
+
includedChars += skeletonSize;
|
|
677
851
|
}
|
|
678
852
|
return {
|
|
679
|
-
files,
|
|
680
|
-
truncated,
|
|
853
|
+
files: result,
|
|
854
|
+
truncated: includedChars >= CHAR_BUDGET * 0.95,
|
|
681
855
|
totalProjectTokens: Math.ceil(totalChars / 4),
|
|
682
856
|
compressedTokens: Math.ceil(compressedChars / 4),
|
|
683
857
|
includedTokens: Math.ceil(includedChars / 4),
|
|
684
|
-
filesAnalyzed:
|
|
685
|
-
filesIncluded:
|
|
858
|
+
filesAnalyzed: fileContents.size,
|
|
859
|
+
filesIncluded: result.length,
|
|
686
860
|
duplicateGroups: dupGroups
|
|
687
861
|
};
|
|
688
862
|
}
|
|
@@ -711,8 +885,9 @@ function walkDir(base, rel, depth, maxDepth, files) {
|
|
|
711
885
|
}
|
|
712
886
|
}
|
|
713
887
|
}
|
|
714
|
-
function
|
|
715
|
-
const
|
|
888
|
+
function filePriority(filePath) {
|
|
889
|
+
const base = path3.basename(filePath);
|
|
890
|
+
const entryPoints = /* @__PURE__ */ new Set([
|
|
716
891
|
"index.ts",
|
|
717
892
|
"index.js",
|
|
718
893
|
"index.tsx",
|
|
@@ -729,22 +904,13 @@ function sortByPriority(files) {
|
|
|
729
904
|
"mod.rs",
|
|
730
905
|
"lib.rs"
|
|
731
906
|
]);
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
if (entryPointNames.has(base)) return 0;
|
|
740
|
-
if (configPattern.test(filePath)) return 1;
|
|
741
|
-
if (routePattern.test(filePath)) return 2;
|
|
742
|
-
if (schemaPattern.test(filePath)) return 3;
|
|
743
|
-
if (servicePattern.test(filePath)) return 4;
|
|
744
|
-
if (testPattern.test(filePath)) return 6;
|
|
745
|
-
return 5;
|
|
746
|
-
}
|
|
747
|
-
files.sort((a, b) => priority(a) - priority(b));
|
|
907
|
+
if (entryPoints.has(base)) return 40;
|
|
908
|
+
if (/\.(json|ya?ml|toml|ini|cfg|env)$|config\.|Makefile|Dockerfile/i.test(filePath)) return 35;
|
|
909
|
+
if (/(route|api|controller|endpoint|handler)/i.test(filePath)) return 30;
|
|
910
|
+
if (/(types|schema|models|entities|migration)/i.test(filePath)) return 25;
|
|
911
|
+
if (/(service|lib|utils|helper|middleware)/i.test(filePath)) return 20;
|
|
912
|
+
if (/(test|spec|__tests__|_test\.|\.test\.)/i.test(filePath)) return 5;
|
|
913
|
+
return 15;
|
|
748
914
|
}
|
|
749
915
|
|
|
750
916
|
// src/llm/index.ts
|
|
@@ -1026,7 +1192,7 @@ var OpenAICompatProvider = class {
|
|
|
1026
1192
|
};
|
|
1027
1193
|
|
|
1028
1194
|
// src/llm/cursor-acp.ts
|
|
1029
|
-
import { spawn, execSync as
|
|
1195
|
+
import { spawn, execSync as execSync3 } from "child_process";
|
|
1030
1196
|
import readline from "readline";
|
|
1031
1197
|
var ACP_AGENT_BIN = "agent";
|
|
1032
1198
|
var CursorAcpProvider = class {
|
|
@@ -1176,7 +1342,7 @@ ${msg.content}
|
|
|
1176
1342
|
};
|
|
1177
1343
|
function isCursorAgentAvailable() {
|
|
1178
1344
|
try {
|
|
1179
|
-
|
|
1345
|
+
execSync3(`which ${ACP_AGENT_BIN}`, { stdio: "ignore" });
|
|
1180
1346
|
return true;
|
|
1181
1347
|
} catch {
|
|
1182
1348
|
return false;
|
|
@@ -1184,7 +1350,7 @@ function isCursorAgentAvailable() {
|
|
|
1184
1350
|
}
|
|
1185
1351
|
|
|
1186
1352
|
// src/llm/claude-cli.ts
|
|
1187
|
-
import { spawn as spawn2, execSync as
|
|
1353
|
+
import { spawn as spawn2, execSync as execSync4 } from "child_process";
|
|
1188
1354
|
var CLAUDE_CLI_BIN = "claude";
|
|
1189
1355
|
var DEFAULT_TIMEOUT_MS = 10 * 60 * 1e3;
|
|
1190
1356
|
var ClaudeCliProvider = class {
|
|
@@ -1303,7 +1469,7 @@ ${msg.content}
|
|
|
1303
1469
|
function isClaudeCliAvailable() {
|
|
1304
1470
|
try {
|
|
1305
1471
|
const cmd = process.platform === "win32" ? `where ${CLAUDE_CLI_BIN}` : `which ${CLAUDE_CLI_BIN}`;
|
|
1306
|
-
|
|
1472
|
+
execSync4(cmd, { stdio: "ignore" });
|
|
1307
1473
|
return true;
|
|
1308
1474
|
} catch {
|
|
1309
1475
|
return false;
|
|
@@ -3037,10 +3203,10 @@ import select2 from "@inquirer/select";
|
|
|
3037
3203
|
import { createTwoFilesPatch } from "diff";
|
|
3038
3204
|
|
|
3039
3205
|
// src/utils/editor.ts
|
|
3040
|
-
import { execSync as
|
|
3206
|
+
import { execSync as execSync5, spawn as spawn3 } from "child_process";
|
|
3041
3207
|
function commandExists(cmd) {
|
|
3042
3208
|
try {
|
|
3043
|
-
|
|
3209
|
+
execSync5(`which ${cmd}`, { stdio: "ignore" });
|
|
3044
3210
|
return true;
|
|
3045
3211
|
} catch {
|
|
3046
3212
|
return false;
|
|
@@ -3340,11 +3506,11 @@ ${agentRefs.join(" ")}
|
|
|
3340
3506
|
// src/lib/hooks.ts
|
|
3341
3507
|
import fs17 from "fs";
|
|
3342
3508
|
import path12 from "path";
|
|
3343
|
-
import { execSync as
|
|
3509
|
+
import { execSync as execSync7 } from "child_process";
|
|
3344
3510
|
|
|
3345
3511
|
// src/lib/resolve-caliber.ts
|
|
3346
3512
|
import fs16 from "fs";
|
|
3347
|
-
import { execSync as
|
|
3513
|
+
import { execSync as execSync6 } from "child_process";
|
|
3348
3514
|
var _resolved = null;
|
|
3349
3515
|
function resolveCaliber() {
|
|
3350
3516
|
if (_resolved) return _resolved;
|
|
@@ -3354,7 +3520,7 @@ function resolveCaliber() {
|
|
|
3354
3520
|
return _resolved;
|
|
3355
3521
|
}
|
|
3356
3522
|
try {
|
|
3357
|
-
const found =
|
|
3523
|
+
const found = execSync6("which caliber", {
|
|
3358
3524
|
encoding: "utf-8",
|
|
3359
3525
|
stdio: ["pipe", "pipe", "pipe"]
|
|
3360
3526
|
}).trim();
|
|
@@ -3459,7 +3625,7 @@ ${PRECOMMIT_END}`;
|
|
|
3459
3625
|
}
|
|
3460
3626
|
function getGitHooksDir() {
|
|
3461
3627
|
try {
|
|
3462
|
-
const gitDir =
|
|
3628
|
+
const gitDir = execSync7("git rev-parse --git-dir", { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
|
|
3463
3629
|
return path12.join(gitDir, "hooks");
|
|
3464
3630
|
} catch {
|
|
3465
3631
|
return null;
|
|
@@ -3603,7 +3769,7 @@ function removeLearningHooks() {
|
|
|
3603
3769
|
init_constants();
|
|
3604
3770
|
import fs19 from "fs";
|
|
3605
3771
|
import path14 from "path";
|
|
3606
|
-
import { execSync as
|
|
3772
|
+
import { execSync as execSync8 } from "child_process";
|
|
3607
3773
|
var STATE_FILE = path14.join(CALIBER_DIR, ".caliber-state.json");
|
|
3608
3774
|
function normalizeTargetAgent(value) {
|
|
3609
3775
|
if (Array.isArray(value)) return value;
|
|
@@ -3631,7 +3797,7 @@ function writeState(state) {
|
|
|
3631
3797
|
}
|
|
3632
3798
|
function getCurrentHeadSha() {
|
|
3633
3799
|
try {
|
|
3634
|
-
return
|
|
3800
|
+
return execSync8("git rev-parse HEAD", {
|
|
3635
3801
|
encoding: "utf-8",
|
|
3636
3802
|
stdio: ["pipe", "pipe", "pipe"]
|
|
3637
3803
|
}).trim();
|
|
@@ -4554,7 +4720,7 @@ function checkGrounding(dir) {
|
|
|
4554
4720
|
|
|
4555
4721
|
// src/scoring/checks/accuracy.ts
|
|
4556
4722
|
import { existsSync as existsSync4, statSync as statSync2 } from "fs";
|
|
4557
|
-
import { execSync as
|
|
4723
|
+
import { execSync as execSync9 } from "child_process";
|
|
4558
4724
|
import { join as join5 } from "path";
|
|
4559
4725
|
function validateReferences(dir) {
|
|
4560
4726
|
const configContent = collectPrimaryConfigContent(dir);
|
|
@@ -4586,13 +4752,13 @@ function validateReferences(dir) {
|
|
|
4586
4752
|
}
|
|
4587
4753
|
function detectGitDrift(dir) {
|
|
4588
4754
|
try {
|
|
4589
|
-
|
|
4755
|
+
execSync9("git rev-parse --git-dir", { cwd: dir, stdio: ["pipe", "pipe", "pipe"] });
|
|
4590
4756
|
} catch {
|
|
4591
4757
|
return { commitsSinceConfigUpdate: 0, lastConfigCommit: null, isGitRepo: false };
|
|
4592
4758
|
}
|
|
4593
4759
|
const configFiles = ["CLAUDE.md", "AGENTS.md", ".cursorrules", ".cursor/rules"];
|
|
4594
4760
|
try {
|
|
4595
|
-
const headTimestamp =
|
|
4761
|
+
const headTimestamp = execSync9(
|
|
4596
4762
|
"git log -1 --format=%ct HEAD",
|
|
4597
4763
|
{ cwd: dir, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
4598
4764
|
).trim();
|
|
@@ -4613,7 +4779,7 @@ function detectGitDrift(dir) {
|
|
|
4613
4779
|
let latestConfigCommitHash = null;
|
|
4614
4780
|
for (const file of configFiles) {
|
|
4615
4781
|
try {
|
|
4616
|
-
const hash =
|
|
4782
|
+
const hash = execSync9(
|
|
4617
4783
|
`git log -1 --format=%H -- "${file}"`,
|
|
4618
4784
|
{ cwd: dir, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
4619
4785
|
).trim();
|
|
@@ -4622,7 +4788,7 @@ function detectGitDrift(dir) {
|
|
|
4622
4788
|
latestConfigCommitHash = hash;
|
|
4623
4789
|
} else {
|
|
4624
4790
|
try {
|
|
4625
|
-
|
|
4791
|
+
execSync9(
|
|
4626
4792
|
`git merge-base --is-ancestor ${latestConfigCommitHash} ${hash}`,
|
|
4627
4793
|
{ cwd: dir, stdio: ["pipe", "pipe", "pipe"] }
|
|
4628
4794
|
);
|
|
@@ -4637,12 +4803,12 @@ function detectGitDrift(dir) {
|
|
|
4637
4803
|
return { commitsSinceConfigUpdate: 0, lastConfigCommit: null, isGitRepo: true };
|
|
4638
4804
|
}
|
|
4639
4805
|
try {
|
|
4640
|
-
const countStr =
|
|
4806
|
+
const countStr = execSync9(
|
|
4641
4807
|
`git rev-list --count ${latestConfigCommitHash}..HEAD`,
|
|
4642
4808
|
{ cwd: dir, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
4643
4809
|
).trim();
|
|
4644
4810
|
const commitsSince = parseInt(countStr, 10) || 0;
|
|
4645
|
-
const lastDate =
|
|
4811
|
+
const lastDate = execSync9(
|
|
4646
4812
|
`git log -1 --format=%ci ${latestConfigCommitHash}`,
|
|
4647
4813
|
{ cwd: dir, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
4648
4814
|
).trim();
|
|
@@ -4714,12 +4880,12 @@ function checkAccuracy(dir) {
|
|
|
4714
4880
|
|
|
4715
4881
|
// src/scoring/checks/freshness.ts
|
|
4716
4882
|
import { existsSync as existsSync5, statSync as statSync3 } from "fs";
|
|
4717
|
-
import { execSync as
|
|
4883
|
+
import { execSync as execSync10 } from "child_process";
|
|
4718
4884
|
import { join as join6 } from "path";
|
|
4719
4885
|
function getCommitsSinceConfigUpdate(dir) {
|
|
4720
4886
|
const configFiles = ["CLAUDE.md", "AGENTS.md", ".cursorrules"];
|
|
4721
4887
|
try {
|
|
4722
|
-
const headTimestamp =
|
|
4888
|
+
const headTimestamp = execSync10(
|
|
4723
4889
|
"git log -1 --format=%ct HEAD",
|
|
4724
4890
|
{ cwd: dir, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
4725
4891
|
).trim();
|
|
@@ -4739,12 +4905,12 @@ function getCommitsSinceConfigUpdate(dir) {
|
|
|
4739
4905
|
}
|
|
4740
4906
|
for (const file of configFiles) {
|
|
4741
4907
|
try {
|
|
4742
|
-
const hash =
|
|
4908
|
+
const hash = execSync10(
|
|
4743
4909
|
`git log -1 --format=%H -- "${file}"`,
|
|
4744
4910
|
{ cwd: dir, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
4745
4911
|
).trim();
|
|
4746
4912
|
if (hash) {
|
|
4747
|
-
const countStr =
|
|
4913
|
+
const countStr = execSync10(
|
|
4748
4914
|
`git rev-list --count ${hash}..HEAD`,
|
|
4749
4915
|
{ cwd: dir, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
4750
4916
|
).trim();
|
|
@@ -4862,11 +5028,11 @@ function checkFreshness(dir) {
|
|
|
4862
5028
|
|
|
4863
5029
|
// src/scoring/checks/bonus.ts
|
|
4864
5030
|
import { existsSync as existsSync6, readdirSync as readdirSync3 } from "fs";
|
|
4865
|
-
import { execSync as
|
|
5031
|
+
import { execSync as execSync11 } from "child_process";
|
|
4866
5032
|
import { join as join7 } from "path";
|
|
4867
5033
|
function hasPreCommitHook(dir) {
|
|
4868
5034
|
try {
|
|
4869
|
-
const gitDir =
|
|
5035
|
+
const gitDir = execSync11("git rev-parse --git-dir", { cwd: dir, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
|
|
4870
5036
|
const hookPath = join7(gitDir, "hooks", "pre-commit");
|
|
4871
5037
|
const content = readFileOrNull2(hookPath);
|
|
4872
5038
|
return content ? content.includes("caliber") : false;
|
|
@@ -5334,7 +5500,7 @@ import fs22 from "fs";
|
|
|
5334
5500
|
import path17 from "path";
|
|
5335
5501
|
import os3 from "os";
|
|
5336
5502
|
import crypto3 from "crypto";
|
|
5337
|
-
import { execSync as
|
|
5503
|
+
import { execSync as execSync12 } from "child_process";
|
|
5338
5504
|
var CONFIG_DIR2 = path17.join(os3.homedir(), ".caliber");
|
|
5339
5505
|
var CONFIG_FILE2 = path17.join(CONFIG_DIR2, "config.json");
|
|
5340
5506
|
var runtimeDisabled = false;
|
|
@@ -5361,7 +5527,7 @@ function getMachineId() {
|
|
|
5361
5527
|
}
|
|
5362
5528
|
function getGitEmailHash() {
|
|
5363
5529
|
try {
|
|
5364
|
-
const email =
|
|
5530
|
+
const email = execSync12("git config user.email", { encoding: "utf-8" }).trim();
|
|
5365
5531
|
if (!email) return void 0;
|
|
5366
5532
|
return crypto3.createHash("sha256").update(email).digest("hex");
|
|
5367
5533
|
} catch {
|
|
@@ -7169,7 +7335,7 @@ import chalk13 from "chalk";
|
|
|
7169
7335
|
import ora5 from "ora";
|
|
7170
7336
|
|
|
7171
7337
|
// src/lib/git-diff.ts
|
|
7172
|
-
import { execSync as
|
|
7338
|
+
import { execSync as execSync13 } from "child_process";
|
|
7173
7339
|
var MAX_DIFF_BYTES = 1e5;
|
|
7174
7340
|
var DOC_PATTERNS = [
|
|
7175
7341
|
"CLAUDE.md",
|
|
@@ -7183,7 +7349,7 @@ function excludeArgs() {
|
|
|
7183
7349
|
}
|
|
7184
7350
|
function safeExec(cmd) {
|
|
7185
7351
|
try {
|
|
7186
|
-
return
|
|
7352
|
+
return execSync13(cmd, {
|
|
7187
7353
|
encoding: "utf-8",
|
|
7188
7354
|
stdio: ["pipe", "pipe", "pipe"],
|
|
7189
7355
|
maxBuffer: 10 * 1024 * 1024
|
|
@@ -8110,7 +8276,7 @@ learn.command("status").description("Show learning system status").action(tracke
|
|
|
8110
8276
|
import fs32 from "fs";
|
|
8111
8277
|
import path26 from "path";
|
|
8112
8278
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
8113
|
-
import { execSync as
|
|
8279
|
+
import { execSync as execSync14 } from "child_process";
|
|
8114
8280
|
import chalk17 from "chalk";
|
|
8115
8281
|
import ora6 from "ora";
|
|
8116
8282
|
import confirm2 from "@inquirer/confirm";
|
|
@@ -8120,7 +8286,7 @@ var pkg2 = JSON.parse(
|
|
|
8120
8286
|
);
|
|
8121
8287
|
function getInstalledVersion() {
|
|
8122
8288
|
try {
|
|
8123
|
-
const globalRoot =
|
|
8289
|
+
const globalRoot = execSync14("npm root -g", { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
|
|
8124
8290
|
const pkgPath = path26.join(globalRoot, "@rely-ai", "caliber", "package.json");
|
|
8125
8291
|
return JSON.parse(fs32.readFileSync(pkgPath, "utf-8")).version;
|
|
8126
8292
|
} catch {
|
|
@@ -8165,7 +8331,7 @@ Update available: ${current} -> ${latest}`)
|
|
|
8165
8331
|
}
|
|
8166
8332
|
const spinner = ora6("Updating caliber...").start();
|
|
8167
8333
|
try {
|
|
8168
|
-
|
|
8334
|
+
execSync14(`npm install -g @rely-ai/caliber@${latest}`, {
|
|
8169
8335
|
stdio: "pipe",
|
|
8170
8336
|
timeout: 12e4,
|
|
8171
8337
|
env: { ...process.env, npm_config_fund: "false", npm_config_audit: "false" }
|
|
@@ -8182,7 +8348,7 @@ Update available: ${current} -> ${latest}`)
|
|
|
8182
8348
|
console.log(chalk17.dim(`
|
|
8183
8349
|
Restarting: caliber ${args.join(" ")}
|
|
8184
8350
|
`));
|
|
8185
|
-
|
|
8351
|
+
execSync14(`caliber ${args.map((a) => JSON.stringify(a)).join(" ")}`, {
|
|
8186
8352
|
stdio: "inherit",
|
|
8187
8353
|
env: { ...process.env, CALIBER_SKIP_UPDATE_CHECK: "1" }
|
|
8188
8354
|
});
|
package/package.json
CHANGED