@rely-ai/caliber 1.15.3 → 1.17.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 +164 -14
- package/package.json +1 -1
package/dist/bin.js
CHANGED
|
@@ -503,47 +503,187 @@ var SKIP_PATTERNS = [
|
|
|
503
503
|
/\.generated\./,
|
|
504
504
|
/\.snap$/
|
|
505
505
|
];
|
|
506
|
+
var COMMENT_LINE_PATTERNS = {
|
|
507
|
+
"c-style": /^\s*\/\//,
|
|
508
|
+
// ts, js, go, rs, java, etc.
|
|
509
|
+
"hash": /^\s*#/,
|
|
510
|
+
// py, sh, yaml, tf, etc.
|
|
511
|
+
"html": /^\s*<!--.*-->\s*$/
|
|
512
|
+
};
|
|
513
|
+
var EXT_TO_COMMENT_STYLE = {
|
|
514
|
+
".ts": "c-style",
|
|
515
|
+
".tsx": "c-style",
|
|
516
|
+
".js": "c-style",
|
|
517
|
+
".jsx": "c-style",
|
|
518
|
+
".mjs": "c-style",
|
|
519
|
+
".cjs": "c-style",
|
|
520
|
+
".go": "c-style",
|
|
521
|
+
".rs": "c-style",
|
|
522
|
+
".java": "c-style",
|
|
523
|
+
".kt": "c-style",
|
|
524
|
+
".scala": "c-style",
|
|
525
|
+
".cs": "c-style",
|
|
526
|
+
".c": "c-style",
|
|
527
|
+
".cpp": "c-style",
|
|
528
|
+
".h": "c-style",
|
|
529
|
+
".hpp": "c-style",
|
|
530
|
+
".swift": "c-style",
|
|
531
|
+
".php": "c-style",
|
|
532
|
+
".py": "hash",
|
|
533
|
+
".pyw": "hash",
|
|
534
|
+
".rb": "hash",
|
|
535
|
+
".sh": "hash",
|
|
536
|
+
".bash": "hash",
|
|
537
|
+
".zsh": "hash",
|
|
538
|
+
".fish": "hash",
|
|
539
|
+
".r": "hash",
|
|
540
|
+
".tf": "hash",
|
|
541
|
+
".hcl": "hash",
|
|
542
|
+
".yaml": "hash",
|
|
543
|
+
".yml": "hash",
|
|
544
|
+
".toml": "hash",
|
|
545
|
+
".ini": "hash",
|
|
546
|
+
".cfg": "hash",
|
|
547
|
+
".env": "hash",
|
|
548
|
+
".html": "html",
|
|
549
|
+
".xml": "html",
|
|
550
|
+
".svg": "html",
|
|
551
|
+
".vue": "html",
|
|
552
|
+
".svelte": "html"
|
|
553
|
+
};
|
|
506
554
|
var TOKEN_BUDGET = 18e4;
|
|
507
555
|
var CHAR_BUDGET = TOKEN_BUDGET * 4;
|
|
556
|
+
function compressContent(content, ext) {
|
|
557
|
+
const commentStyle = EXT_TO_COMMENT_STYLE[ext];
|
|
558
|
+
const commentPattern = commentStyle ? COMMENT_LINE_PATTERNS[commentStyle] : null;
|
|
559
|
+
const lines = content.split("\n");
|
|
560
|
+
const result = [];
|
|
561
|
+
let prevBlank = false;
|
|
562
|
+
let inBlockComment = false;
|
|
563
|
+
for (const line of lines) {
|
|
564
|
+
const trimmed = line.trimEnd();
|
|
565
|
+
if (!inBlockComment && /^\s*\/\*/.test(trimmed) && !trimmed.includes("*/")) {
|
|
566
|
+
inBlockComment = true;
|
|
567
|
+
continue;
|
|
568
|
+
}
|
|
569
|
+
if (inBlockComment) {
|
|
570
|
+
if (trimmed.includes("*/")) inBlockComment = false;
|
|
571
|
+
continue;
|
|
572
|
+
}
|
|
573
|
+
if (/^\s*\/\*.*\*\/\s*$/.test(trimmed)) continue;
|
|
574
|
+
if (trimmed.length === 0) {
|
|
575
|
+
if (!prevBlank) result.push("");
|
|
576
|
+
prevBlank = true;
|
|
577
|
+
continue;
|
|
578
|
+
}
|
|
579
|
+
prevBlank = false;
|
|
580
|
+
if (commentPattern && commentPattern.test(trimmed)) continue;
|
|
581
|
+
const leadingMatch = line.match(/^(\s*)/);
|
|
582
|
+
if (leadingMatch) {
|
|
583
|
+
const spaces = leadingMatch[1].replace(/\t/g, " ").length;
|
|
584
|
+
const normalizedIndent = " ".repeat(Math.floor(spaces / 2) * 2);
|
|
585
|
+
result.push(normalizedIndent + line.trimStart().trimEnd());
|
|
586
|
+
} else {
|
|
587
|
+
result.push(trimmed);
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
while (result.length > 0 && result[result.length - 1] === "") result.pop();
|
|
591
|
+
return result.join("\n");
|
|
592
|
+
}
|
|
593
|
+
function structuralFingerprint(content, ext) {
|
|
594
|
+
const lines = content.split("\n").filter((l) => l.trim().length > 0);
|
|
595
|
+
const lineCount = lines.length;
|
|
596
|
+
const sizeBucket = Math.floor(lineCount / 10) * 10;
|
|
597
|
+
const firstLine = lines[0]?.trim().slice(0, 60) || "";
|
|
598
|
+
const imports = lines.filter((l) => /^\s*(import |from |require\(|use )/.test(l)).length;
|
|
599
|
+
const exports = lines.filter((l) => /^\s*export /.test(l)).length;
|
|
600
|
+
const functions = lines.filter((l) => /^\s*(function |def |func |fn |pub fn )/.test(l)).length;
|
|
601
|
+
return `${ext}:${sizeBucket}:${imports}:${exports}:${functions}:${firstLine}`;
|
|
602
|
+
}
|
|
603
|
+
function deduplicateFiles(files) {
|
|
604
|
+
const groups = /* @__PURE__ */ new Map();
|
|
605
|
+
for (const f of files) {
|
|
606
|
+
const fp = structuralFingerprint(f.content, f.ext);
|
|
607
|
+
const group = groups.get(fp) || [];
|
|
608
|
+
group.push({ path: f.path, content: f.content });
|
|
609
|
+
groups.set(fp, group);
|
|
610
|
+
}
|
|
611
|
+
const result = [];
|
|
612
|
+
for (const [, group] of groups) {
|
|
613
|
+
const representative = group[0];
|
|
614
|
+
result.push({
|
|
615
|
+
path: representative.path,
|
|
616
|
+
content: representative.content,
|
|
617
|
+
size: representative.content.length
|
|
618
|
+
});
|
|
619
|
+
if (group.length > 1) {
|
|
620
|
+
const similarPaths = group.slice(1).map((f) => f.path);
|
|
621
|
+
const summary = `(${similarPaths.length} similar file${similarPaths.length === 1 ? "" : "s"}: ${similarPaths.join(", ")})`;
|
|
622
|
+
result.push({
|
|
623
|
+
path: `[similar to ${representative.path}]`,
|
|
624
|
+
content: summary,
|
|
625
|
+
size: summary.length
|
|
626
|
+
});
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
return result;
|
|
630
|
+
}
|
|
508
631
|
function analyzeCode(dir) {
|
|
509
632
|
const allFiles = [];
|
|
510
633
|
walkDir(dir, "", 0, 10, allFiles);
|
|
511
634
|
sortByPriority(allFiles);
|
|
512
635
|
let totalChars = 0;
|
|
513
|
-
let includedChars = 0;
|
|
514
|
-
let truncated = false;
|
|
515
|
-
const files = [];
|
|
516
|
-
const fileSizes = /* @__PURE__ */ new Map();
|
|
517
636
|
for (const relPath of allFiles) {
|
|
518
637
|
try {
|
|
519
638
|
const stat = fs3.statSync(path3.join(dir, relPath));
|
|
520
|
-
fileSizes.set(relPath, stat.size);
|
|
521
639
|
totalChars += stat.size;
|
|
522
640
|
} catch {
|
|
523
641
|
}
|
|
524
642
|
}
|
|
643
|
+
const readFiles = [];
|
|
644
|
+
let compressedChars = 0;
|
|
525
645
|
for (const relPath of allFiles) {
|
|
526
646
|
const fullPath = path3.join(dir, relPath);
|
|
527
|
-
let
|
|
647
|
+
let rawContent;
|
|
528
648
|
try {
|
|
529
|
-
|
|
649
|
+
rawContent = fs3.readFileSync(fullPath, "utf-8");
|
|
530
650
|
} catch {
|
|
531
651
|
continue;
|
|
532
652
|
}
|
|
533
|
-
if (
|
|
534
|
-
const
|
|
653
|
+
if (rawContent.split("\n").length > 500) continue;
|
|
654
|
+
const ext = path3.extname(relPath).toLowerCase();
|
|
655
|
+
const compressed = compressContent(rawContent, ext);
|
|
656
|
+
compressedChars += compressed.length;
|
|
657
|
+
readFiles.push({
|
|
658
|
+
path: relPath,
|
|
659
|
+
content: compressed,
|
|
660
|
+
ext,
|
|
661
|
+
rawSize: rawContent.length
|
|
662
|
+
});
|
|
663
|
+
}
|
|
664
|
+
const deduped = deduplicateFiles(readFiles);
|
|
665
|
+
const dupGroups = deduped.filter((f) => f.path.startsWith("[similar")).length;
|
|
666
|
+
let includedChars = 0;
|
|
667
|
+
let truncated = false;
|
|
668
|
+
const files = [];
|
|
669
|
+
for (const file of deduped) {
|
|
670
|
+
const entrySize = file.path.length + file.content.length + 10;
|
|
535
671
|
if (includedChars + entrySize > CHAR_BUDGET) {
|
|
536
672
|
truncated = true;
|
|
537
673
|
continue;
|
|
538
674
|
}
|
|
539
|
-
files.push(
|
|
675
|
+
files.push(file);
|
|
540
676
|
includedChars += entrySize;
|
|
541
677
|
}
|
|
542
678
|
return {
|
|
543
679
|
files,
|
|
544
680
|
truncated,
|
|
545
681
|
totalProjectTokens: Math.ceil(totalChars / 4),
|
|
546
|
-
|
|
682
|
+
compressedTokens: Math.ceil(compressedChars / 4),
|
|
683
|
+
includedTokens: Math.ceil(includedChars / 4),
|
|
684
|
+
filesAnalyzed: readFiles.length,
|
|
685
|
+
filesIncluded: files.length,
|
|
686
|
+
duplicateGroups: dupGroups
|
|
547
687
|
};
|
|
548
688
|
}
|
|
549
689
|
function walkDir(base, rel, depth, maxDepth, files) {
|
|
@@ -6036,15 +6176,25 @@ async function initCommand(options) {
|
|
|
6036
6176
|
spinner.succeed("Project analyzed");
|
|
6037
6177
|
log(options.verbose, `Fingerprint: ${fingerprint.languages.length} languages, ${fingerprint.frameworks.length} frameworks, ${fingerprint.fileTree.length} files`);
|
|
6038
6178
|
if (options.verbose && fingerprint.codeAnalysis) {
|
|
6039
|
-
log(options.verbose, `Code analysis: ${fingerprint.codeAnalysis.
|
|
6179
|
+
log(options.verbose, `Code analysis: ${fingerprint.codeAnalysis.filesIncluded}/${fingerprint.codeAnalysis.filesAnalyzed} files, ~${fingerprint.codeAnalysis.includedTokens.toLocaleString()} tokens, ${fingerprint.codeAnalysis.duplicateGroups} dedup groups`);
|
|
6040
6180
|
}
|
|
6041
6181
|
trackInitProjectDiscovered(fingerprint.languages.length, fingerprint.frameworks.length, fingerprint.fileTree.length);
|
|
6042
6182
|
console.log(chalk8.dim(` Languages: ${fingerprint.languages.join(", ") || "none detected"}`));
|
|
6043
6183
|
console.log(chalk8.dim(` Files: ${fingerprint.fileTree.length} found`));
|
|
6044
6184
|
if (fingerprint.codeAnalysis) {
|
|
6045
6185
|
const ca = fingerprint.codeAnalysis;
|
|
6046
|
-
const
|
|
6047
|
-
|
|
6186
|
+
const compressionPct = ca.totalProjectTokens > 0 ? Math.round((1 - ca.compressedTokens / ca.totalProjectTokens) * 100) : 0;
|
|
6187
|
+
const parts = [`Context: ~${ca.includedTokens.toLocaleString()} tokens sent`];
|
|
6188
|
+
if (ca.truncated) {
|
|
6189
|
+
parts.push(`(${Math.round(ca.includedTokens / ca.totalProjectTokens * 100)}% of ${ca.totalProjectTokens.toLocaleString()} total)`);
|
|
6190
|
+
}
|
|
6191
|
+
if (compressionPct > 5) {
|
|
6192
|
+
parts.push(`compressed ${compressionPct}%`);
|
|
6193
|
+
}
|
|
6194
|
+
if (ca.duplicateGroups > 0) {
|
|
6195
|
+
parts.push(`${ca.duplicateGroups} duplicate group${ca.duplicateGroups === 1 ? "" : "s"} merged`);
|
|
6196
|
+
}
|
|
6197
|
+
console.log(chalk8.dim(` ${parts.join(" \xB7 ")}`));
|
|
6048
6198
|
}
|
|
6049
6199
|
console.log("");
|
|
6050
6200
|
if (report) {
|
package/package.json
CHANGED