@rely-ai/caliber 1.12.17 → 1.13.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.
Files changed (2) hide show
  1. package/dist/bin.js +75 -26
  2. 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 = 5e4;
450
- var CONFIG_BUDGET = Math.floor(TOTAL_BUDGET * 0.3);
451
- var SOURCE_BUDGET = Math.floor(TOTAL_BUDGET * 0.7);
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 content;
473
+ let fileContent;
471
474
  try {
472
- content = fs3.readFileSync(fullPath, "utf-8");
475
+ fileContent = fs3.readFileSync(fullPath, "utf-8");
473
476
  } catch {
474
477
  continue;
475
478
  }
476
- const lineCount = content.split("\n").length;
477
- if (lineCount > 500) continue;
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, content) : extractTypeScriptJavaScript(relPath, content, language);
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 (sourceChars + summarySize > SOURCE_BUDGET) {
512
+ if (summaryChars + summarySize > SUMMARY_BUDGET) {
484
513
  truncated = true;
485
514
  break;
486
515
  }
487
516
  fileSummaries.push(summary);
488
- sourceChars += summarySize;
517
+ summaryChars += summarySize;
489
518
  }
490
519
  return { fileSummaries, configFiles: trimmedConfigs, truncated };
491
520
  }
@@ -1701,8 +1730,9 @@ Skills serve two purposes:
1701
1730
 
1702
1731
  Derive skill topics from actual code in the project. Look at existing files for the patterns being used, then create skills that replicate those patterns for new work.
1703
1732
 
1704
- Skill topic description MUST include WHAT it does + WHEN to use it with specific trigger phrases.
1705
- Example: "Creates a new API endpoint following the project's route pattern. Use when user says 'add endpoint', 'new route', 'create API', or adds files to src/routes/."
1733
+ Skill topic description MUST follow this formula: [What it does] + [When to use it] + [Key capabilities].
1734
+ Include specific trigger phrases users would actually say. Also include negative triggers to prevent over-triggering.
1735
+ Example: "Creates a new API endpoint following the project's route pattern. Handles request validation, error responses, and DB queries. Use when user says 'add endpoint', 'new route', 'create API', or adds files to src/routes/. Do NOT use for modifying existing routes."
1706
1736
 
1707
1737
  The "fileDescriptions" object MUST include a one-liner for every file that will be created or modified.
1708
1738
  The "deletions" array should list files that should be removed (e.g. stale configs). Omit if empty.
@@ -1747,19 +1777,27 @@ Purpose: Skills codify repeating patterns from the codebase so every developer a
1747
1777
 
1748
1778
  Structure:
1749
1779
  1. A heading with the skill name
1750
- 2. "## Instructions" \u2014 clear, numbered steps derived from actual patterns in the codebase. Include exact file paths, naming conventions, imports, and boilerplate from existing code.
1751
- 3. "## Examples" \u2014 at least one example showing: User says \u2192 Actions taken \u2192 Result. The example should mirror how existing code in the project is structured.
1752
- 4. "## Troubleshooting" (optional) \u2014 common errors and fixes
1780
+ 2. "## Critical" (if applicable) \u2014 put the most important rules and constraints FIRST. Things the agent must never skip, validation that must happen before any action, or project-specific constraints.
1781
+ 3. "## Instructions" \u2014 clear, numbered steps derived from actual patterns in the codebase. Each step MUST:
1782
+ - Include exact file paths, naming conventions, imports, and boilerplate from existing code
1783
+ - Have a validation gate: "Verify X before proceeding to the next step"
1784
+ - Specify dependencies: "This step uses the output from Step N"
1785
+ 4. "## Examples" \u2014 at least one example showing: User says \u2192 Actions taken \u2192 Result. The example should mirror how existing code in the project is structured.
1786
+ 5. "## Common Issues" (required) \u2014 specific error messages and their fixes. Not "check your config" but "If you see 'Connection refused on port 5432': 1. Verify postgres is running: docker ps | grep postgres 2. Check .env has correct DATABASE_URL"
1753
1787
 
1754
1788
  Rules:
1755
1789
  - Max 150 lines. Focus on actionable instructions, not documentation prose.
1756
1790
  - Study existing code in the project context to extract the real patterns being used. A skill for "create API route" should show the exact file structure, imports, error handling, and naming that existing routes use.
1791
+ - Be specific and actionable. GOOD: "Run \`pnpm test -- --filter=api\` to verify". BAD: "Validate the data before proceeding."
1792
+ - Never use ambiguous language. Instead of "handle errors properly", write "Wrap the DB call in try/catch. On failure, return { error: string, code: number } matching the ErrorResponse type in \`src/types.ts\`."
1757
1793
  - Reference actual commands, paths, and packages from the project context provided.
1758
1794
  - Do NOT include YAML frontmatter \u2014 it will be generated separately.
1759
1795
  - Be specific to THIS project \u2014 avoid generic advice. The skill should produce code that looks identical to what's already in the codebase.
1760
1796
 
1797
+ Description field formula: [What it does] + [When to use it with trigger phrases] + [Key capabilities]. Include negative triggers ("Do NOT use for X") to prevent over-triggering.
1798
+
1761
1799
  Return ONLY a JSON object:
1762
- {"name": "string (kebab-case)", "description": "string (what + when)", "content": "string (markdown body)"}`;
1800
+ {"name": "string (kebab-case)", "description": "string (what + when + capabilities + negative triggers)", "content": "string (markdown body)"}`;
1763
1801
  var REFINE_SYSTEM_PROMPT = `You are an expert at modifying coding agent configurations (Claude Code, Cursor, and Codex).
1764
1802
 
1765
1803
  You will receive the current AgentSetup JSON and a user request describing what to change.
@@ -2427,15 +2465,16 @@ async function generateMonolithic(fingerprint, targetAgent, prompt, callbacks, f
2427
2465
  return attemptGeneration();
2428
2466
  }
2429
2467
  var LIMITS = {
2430
- FILE_TREE_ENTRIES: 200,
2468
+ FILE_TREE_ENTRIES: 500,
2431
2469
  EXISTING_CONFIG_CHARS: 8e3,
2432
2470
  SKILLS_MAX: 10,
2433
2471
  SKILL_CHARS: 3e3,
2434
2472
  RULES_MAX: 10,
2435
- CONFIG_FILES_MAX: 15,
2436
- CONFIG_FILE_CHARS: 3e3,
2437
- ROUTES_MAX: 50,
2438
- FILE_SUMMARIES_MAX: 60
2473
+ CONFIG_FILES_MAX: 20,
2474
+ CONFIG_FILE_CHARS: 5e3,
2475
+ ROUTES_MAX: 100,
2476
+ FILE_SUMMARIES_MAX: 200,
2477
+ FILE_CONTENT_CHARS: 8e3
2439
2478
  };
2440
2479
  function truncate(text, maxChars) {
2441
2480
  if (text.length <= maxChars) return text;
@@ -2566,9 +2605,19 @@ ${truncate(cfg.content, LIMITS.CONFIG_FILE_CHARS)}`);
2566
2605
  parts.push(`(${allRoutes.length - LIMITS.ROUTES_MAX} more routes omitted)`);
2567
2606
  }
2568
2607
  }
2569
- if (ca.fileSummaries.length > 0) {
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) {
2570
2619
  parts.push("\n--- Source File Summaries ---");
2571
- for (const f of ca.fileSummaries.slice(0, LIMITS.FILE_SUMMARIES_MAX)) {
2620
+ for (const f of filesWithoutContent.slice(0, LIMITS.FILE_SUMMARIES_MAX)) {
2572
2621
  const sections = [`[${f.path}] (${f.language})`];
2573
2622
  if (f.imports.length > 0) sections.push(` imports: ${f.imports.slice(0, 10).join("; ")}`);
2574
2623
  if (f.exports.length > 0) sections.push(` exports: ${f.exports.slice(0, 10).join(", ")}`);
@@ -2577,9 +2626,9 @@ ${truncate(cfg.content, LIMITS.CONFIG_FILE_CHARS)}`);
2577
2626
  if (f.types.length > 0) sections.push(` types: ${f.types.slice(0, 10).join(", ")}`);
2578
2627
  parts.push(sections.join("\n"));
2579
2628
  }
2580
- if (ca.fileSummaries.length > LIMITS.FILE_SUMMARIES_MAX) {
2629
+ if (filesWithoutContent.length > LIMITS.FILE_SUMMARIES_MAX) {
2581
2630
  parts.push(`
2582
- (${ca.fileSummaries.length - LIMITS.FILE_SUMMARIES_MAX} more files omitted)`);
2631
+ (${filesWithoutContent.length - LIMITS.FILE_SUMMARIES_MAX} more files omitted)`);
2583
2632
  }
2584
2633
  }
2585
2634
  if (ca.truncated) {
@@ -2589,7 +2638,7 @@ ${truncate(cfg.content, LIMITS.CONFIG_FILE_CHARS)}`);
2589
2638
  const allDeps = extractAllDeps(process.cwd());
2590
2639
  if (allDeps.length > 0) {
2591
2640
  parts.push(`
2592
- DEPENDENCY COVERAGE \u2014 mention at least 85% of these ${allDeps.length} packages by name in CLAUDE.md or skills for full coverage points:`);
2641
+ Project dependencies (${allDeps.length}):`);
2593
2642
  parts.push(allDeps.join(", "));
2594
2643
  }
2595
2644
  if (prompt) parts.push(`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rely-ai/caliber",
3
- "version": "1.12.17",
3
+ "version": "1.13.0",
4
4
  "description": "Analyze your codebase and generate optimized AI agent configs (CLAUDE.md, .cursorrules, skills) — no API key needed",
5
5
  "type": "module",
6
6
  "bin": {