@rely-ai/caliber 1.48.2 → 1.49.3
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 +370 -168
- package/package.json +1 -1
package/dist/bin.js
CHANGED
|
@@ -184,6 +184,7 @@ var init_config = __esm({
|
|
|
184
184
|
// src/lib/resolve-caliber.ts
|
|
185
185
|
var resolve_caliber_exports = {};
|
|
186
186
|
__export(resolve_caliber_exports, {
|
|
187
|
+
displayCaliberName: () => displayCaliberName,
|
|
187
188
|
isCaliberCommand: () => isCaliberCommand,
|
|
188
189
|
isNpxResolution: () => isNpxResolution,
|
|
189
190
|
pickExecutable: () => pickExecutable,
|
|
@@ -254,6 +255,9 @@ function isNpxResolution() {
|
|
|
254
255
|
if (r === "npx --yes @rely-ai/caliber") return true;
|
|
255
256
|
return NPX_RESOLUTION_RE.test(r);
|
|
256
257
|
}
|
|
258
|
+
function displayCaliberName() {
|
|
259
|
+
return isNpxResolution() ? "npx @rely-ai/caliber" : "caliber";
|
|
260
|
+
}
|
|
257
261
|
function resetResolvedCaliber() {
|
|
258
262
|
_resolved = null;
|
|
259
263
|
}
|
|
@@ -344,7 +348,7 @@ npx @rely-ai/caliber refresh
|
|
|
344
348
|
}
|
|
345
349
|
}
|
|
346
350
|
function getPreCommitBlock(platform = "claude") {
|
|
347
|
-
const bin =
|
|
351
|
+
const bin = displayCaliberName();
|
|
348
352
|
return `${BLOCK_START}
|
|
349
353
|
## Before Committing
|
|
350
354
|
|
|
@@ -369,7 +373,7 @@ ${getCaliberNotFoundFallback(platform, bin)}
|
|
|
369
373
|
${BLOCK_END}`;
|
|
370
374
|
}
|
|
371
375
|
function getCursorRuleContent() {
|
|
372
|
-
const bin =
|
|
376
|
+
const bin = displayCaliberName();
|
|
373
377
|
return `---
|
|
374
378
|
description: Run Caliber sync before git commits to keep agent configs up to date
|
|
375
379
|
alwaysApply: true
|
|
@@ -386,8 +390,20 @@ Valid \`${bin} refresh\` options: \`--quiet\` and \`--dry-run\` only. Do not pas
|
|
|
386
390
|
If \`${bin}\` is not found, read the setup-caliber skill from .cursor/skills/setup-caliber/SKILL.md and follow its instructions to install Caliber.
|
|
387
391
|
`;
|
|
388
392
|
}
|
|
393
|
+
function getSectionBody(content, headingRe) {
|
|
394
|
+
const match = content.match(headingRe);
|
|
395
|
+
if (!match || match.index === void 0) return null;
|
|
396
|
+
const start = match.index + match[0].length;
|
|
397
|
+
const tail = content.slice(start);
|
|
398
|
+
const nextHeadingMatch = tail.match(/^##\s/m);
|
|
399
|
+
const end = nextHeadingMatch?.index ?? tail.length;
|
|
400
|
+
return tail.slice(0, end);
|
|
401
|
+
}
|
|
389
402
|
function hasPreCommitBlock(content) {
|
|
390
|
-
|
|
403
|
+
if (content.includes(BLOCK_START)) return true;
|
|
404
|
+
const body = getSectionBody(content, PRECOMMIT_HEADING_RE);
|
|
405
|
+
if (body && /caliber/i.test(body)) return true;
|
|
406
|
+
return false;
|
|
391
407
|
}
|
|
392
408
|
function appendPreCommitBlock(content, platform = "claude") {
|
|
393
409
|
if (hasPreCommitBlock(content)) return content;
|
|
@@ -398,7 +414,10 @@ function getCursorPreCommitRule() {
|
|
|
398
414
|
return { filename: CURSOR_RULE_FILENAME, content: getCursorRuleContent() };
|
|
399
415
|
}
|
|
400
416
|
function hasLearningsBlock(content) {
|
|
401
|
-
|
|
417
|
+
if (content.includes(LEARNINGS_BLOCK_START)) return true;
|
|
418
|
+
const body = getSectionBody(content, LEARNINGS_HEADING_RE);
|
|
419
|
+
if (body && /CALIBER_LEARNINGS/.test(body)) return true;
|
|
420
|
+
return false;
|
|
402
421
|
}
|
|
403
422
|
function appendLearningsBlock(content) {
|
|
404
423
|
if (hasLearningsBlock(content)) return content;
|
|
@@ -420,7 +439,10 @@ Pin your choice (\`/model\` in Claude Code, or \`CALIBER_MODEL\` when using Cali
|
|
|
420
439
|
${MODEL_BLOCK_END}`;
|
|
421
440
|
}
|
|
422
441
|
function hasModelBlock(content) {
|
|
423
|
-
|
|
442
|
+
if (content.includes(MODEL_BLOCK_START)) return true;
|
|
443
|
+
const body = getSectionBody(content, MODEL_HEADING_RE);
|
|
444
|
+
if (body && /CALIBER_MODEL/.test(body)) return true;
|
|
445
|
+
return false;
|
|
424
446
|
}
|
|
425
447
|
function appendModelBlock(content) {
|
|
426
448
|
if (hasModelBlock(content)) return content;
|
|
@@ -443,7 +465,7 @@ git add ${MANAGED_DOC_PATHS} 2>/dev/null
|
|
|
443
465
|
}
|
|
444
466
|
}
|
|
445
467
|
function getSyncBlock(platform = "claude") {
|
|
446
|
-
const bin =
|
|
468
|
+
const bin = displayCaliberName();
|
|
447
469
|
return `${SYNC_BLOCK_START}
|
|
448
470
|
## Context Sync
|
|
449
471
|
|
|
@@ -453,7 +475,10 @@ ${getSyncSetupInstruction(platform)}
|
|
|
453
475
|
${SYNC_BLOCK_END}`;
|
|
454
476
|
}
|
|
455
477
|
function hasSyncBlock(content) {
|
|
456
|
-
|
|
478
|
+
if (content.includes(SYNC_BLOCK_START)) return true;
|
|
479
|
+
const body = getSectionBody(content, SYNC_HEADING_RE);
|
|
480
|
+
if (body && /caliber-ai-org\/ai-setup/.test(body)) return true;
|
|
481
|
+
return false;
|
|
457
482
|
}
|
|
458
483
|
function appendSyncBlock(content, platform = "claude") {
|
|
459
484
|
if (hasSyncBlock(content)) return content;
|
|
@@ -467,7 +492,7 @@ function appendManagedBlocks(content, platform = "claude") {
|
|
|
467
492
|
);
|
|
468
493
|
}
|
|
469
494
|
function getCursorSyncContent() {
|
|
470
|
-
const bin =
|
|
495
|
+
const bin = displayCaliberName();
|
|
471
496
|
return `---
|
|
472
497
|
description: This project uses Caliber for automatic AI agent context sync
|
|
473
498
|
alwaysApply: true
|
|
@@ -509,7 +534,7 @@ function stripManagedBlocks(content) {
|
|
|
509
534
|
}
|
|
510
535
|
return result.replace(/\n{3,}/g, "\n\n").trim() + "\n";
|
|
511
536
|
}
|
|
512
|
-
var BLOCK_START, BLOCK_END, MANAGED_DOC_PATHS, CURSOR_RULE_FILENAME, LEARNINGS_BLOCK_START, LEARNINGS_BLOCK_END, LEARNINGS_BLOCK, CURSOR_LEARNINGS_FILENAME, CURSOR_LEARNINGS_CONTENT, MODEL_BLOCK_START, MODEL_BLOCK_END, SYNC_BLOCK_START, SYNC_BLOCK_END, CURSOR_SYNC_FILENAME, CURSOR_SETUP_FILENAME, MANAGED_BLOCK_PAIRS;
|
|
537
|
+
var BLOCK_START, BLOCK_END, MANAGED_DOC_PATHS, CURSOR_RULE_FILENAME, PRECOMMIT_HEADING_RE, LEARNINGS_BLOCK_START, LEARNINGS_BLOCK_END, LEARNINGS_BLOCK, CURSOR_LEARNINGS_FILENAME, CURSOR_LEARNINGS_CONTENT, LEARNINGS_HEADING_RE, MODEL_BLOCK_START, MODEL_BLOCK_END, MODEL_HEADING_RE, SYNC_BLOCK_START, SYNC_BLOCK_END, SYNC_HEADING_RE, CURSOR_SYNC_FILENAME, CURSOR_SETUP_FILENAME, MANAGED_BLOCK_PAIRS;
|
|
513
538
|
var init_pre_commit_block = __esm({
|
|
514
539
|
"src/writers/pre-commit-block.ts"() {
|
|
515
540
|
"use strict";
|
|
@@ -519,6 +544,7 @@ var init_pre_commit_block = __esm({
|
|
|
519
544
|
BLOCK_END = "<!-- /caliber:managed:pre-commit -->";
|
|
520
545
|
MANAGED_DOC_PATHS = "CLAUDE.md .claude/ .cursor/ .cursorrules .github/copilot-instructions.md .github/instructions/ AGENTS.md CALIBER_LEARNINGS.md .agents/ .opencode/";
|
|
521
546
|
CURSOR_RULE_FILENAME = "caliber-pre-commit.mdc";
|
|
547
|
+
PRECOMMIT_HEADING_RE = /^##\s+Before Committing\s*$/m;
|
|
522
548
|
LEARNINGS_BLOCK_START = "<!-- caliber:managed:learnings -->";
|
|
523
549
|
LEARNINGS_BLOCK_END = "<!-- /caliber:managed:learnings -->";
|
|
524
550
|
LEARNINGS_BLOCK = `${LEARNINGS_BLOCK_START}
|
|
@@ -535,10 +561,13 @@ alwaysApply: true
|
|
|
535
561
|
Read \`CALIBER_LEARNINGS.md\` for patterns and anti-patterns learned from previous sessions.
|
|
536
562
|
These are auto-extracted from real tool usage \u2014 treat them as project-specific rules.
|
|
537
563
|
`;
|
|
564
|
+
LEARNINGS_HEADING_RE = /^##\s+Session Learnings\s*$/m;
|
|
538
565
|
MODEL_BLOCK_START = "<!-- caliber:managed:model-config -->";
|
|
539
566
|
MODEL_BLOCK_END = "<!-- /caliber:managed:model-config -->";
|
|
567
|
+
MODEL_HEADING_RE = /^##\s+Model Configuration\s*$/m;
|
|
540
568
|
SYNC_BLOCK_START = "<!-- caliber:managed:sync -->";
|
|
541
569
|
SYNC_BLOCK_END = "<!-- /caliber:managed:sync -->";
|
|
570
|
+
SYNC_HEADING_RE = /^##\s+Context Sync\s*$/m;
|
|
542
571
|
CURSOR_SYNC_FILENAME = "caliber-sync.mdc";
|
|
543
572
|
CURSOR_SETUP_FILENAME = "caliber-setup.mdc";
|
|
544
573
|
MANAGED_BLOCK_PAIRS = [
|
|
@@ -574,7 +603,7 @@ description: ${skill.description}
|
|
|
574
603
|
return frontmatter + skill.content;
|
|
575
604
|
}
|
|
576
605
|
function getFindSkillsContent() {
|
|
577
|
-
const bin =
|
|
606
|
+
const bin = displayCaliberName();
|
|
578
607
|
return `# Find Skills
|
|
579
608
|
|
|
580
609
|
Search the public skill registry for community-contributed skills
|
|
@@ -627,7 +656,7 @@ User: "I need to write tests for this Python ML pipeline"
|
|
|
627
656
|
`;
|
|
628
657
|
}
|
|
629
658
|
function getSaveLearningContent() {
|
|
630
|
-
const bin =
|
|
659
|
+
const bin = displayCaliberName();
|
|
631
660
|
return `# Save Learning
|
|
632
661
|
|
|
633
662
|
Save a user's instruction or preference as a persistent learning that
|
|
@@ -2583,10 +2612,19 @@ import os3 from "os";
|
|
|
2583
2612
|
// src/llm/seat-based-errors.ts
|
|
2584
2613
|
init_resolve_caliber();
|
|
2585
2614
|
var ERROR_PATTERNS = [
|
|
2586
|
-
{
|
|
2615
|
+
{
|
|
2616
|
+
pattern: /not logged in|not authenticated|login required|unauthorized/i,
|
|
2617
|
+
message: "Not logged in. Run the login command for your provider to re-authenticate."
|
|
2618
|
+
},
|
|
2587
2619
|
{ pattern: /rate limit|too many requests|429/i, message: "Rate limit exceeded. Retrying..." },
|
|
2588
|
-
{
|
|
2589
|
-
|
|
2620
|
+
{
|
|
2621
|
+
pattern: /usage limit|out of usage|budget.*limit|limit.*reached/i,
|
|
2622
|
+
message: () => `Usage limit reached. Run \`${displayCaliberName()} config\` to switch models (e.g. auto or composer-1.5).`
|
|
2623
|
+
},
|
|
2624
|
+
{
|
|
2625
|
+
pattern: /model.*not found|invalid model|model.*unavailable/i,
|
|
2626
|
+
message: () => `The requested model is not available. Run \`${displayCaliberName()} config\` to select a different model.`
|
|
2627
|
+
}
|
|
2590
2628
|
];
|
|
2591
2629
|
function parseSeatBasedError(stderr, exitCode) {
|
|
2592
2630
|
if (!stderr && exitCode === 0) return null;
|
|
@@ -2664,6 +2702,12 @@ function withCaliberSubprocessEnv(env) {
|
|
|
2664
2702
|
[CALIBER_SUBPROCESS_LEGACY_ENV]: "1"
|
|
2665
2703
|
};
|
|
2666
2704
|
}
|
|
2705
|
+
function isHookCascadeFromUserClaudeSession() {
|
|
2706
|
+
const inClaudeSession = process.env.CLAUDECODE === "1";
|
|
2707
|
+
const isCaliberSpawned = process.env[CALIBER_SUBPROCESS_ENV] === "1";
|
|
2708
|
+
const isInteractiveTty = process.stdin.isTTY === true;
|
|
2709
|
+
return inClaudeSession && !isCaliberSpawned && !isInteractiveTty;
|
|
2710
|
+
}
|
|
2667
2711
|
|
|
2668
2712
|
// src/llm/cursor-acp.ts
|
|
2669
2713
|
var IS_WINDOWS = process.platform === "win32";
|
|
@@ -3038,12 +3082,17 @@ function resolveClaudeBin() {
|
|
|
3038
3082
|
_claudeBin = "claude";
|
|
3039
3083
|
return _claudeBin;
|
|
3040
3084
|
}
|
|
3085
|
+
var ANTI_RECURSION_ENV_VARS = /* @__PURE__ */ new Set([
|
|
3086
|
+
"CLAUDECODE",
|
|
3087
|
+
"CLAUDE_CODE_SIMPLE",
|
|
3088
|
+
"CLAUDE_CODE_SESSION_ID",
|
|
3089
|
+
"CLAUDE_CODE_ENTRYPOINT",
|
|
3090
|
+
"CLAUDE_CODE_EXECPATH"
|
|
3091
|
+
]);
|
|
3041
3092
|
function cleanClaudeEnv() {
|
|
3042
3093
|
const env = { ...process.env };
|
|
3043
|
-
for (const key of
|
|
3044
|
-
|
|
3045
|
-
delete env[key];
|
|
3046
|
-
}
|
|
3094
|
+
for (const key of ANTI_RECURSION_ENV_VARS) {
|
|
3095
|
+
delete env[key];
|
|
3047
3096
|
}
|
|
3048
3097
|
return env;
|
|
3049
3098
|
}
|
|
@@ -3505,7 +3554,7 @@ async function handleModelNotAvailable(failedModel, provider, config) {
|
|
|
3505
3554
|
if (!process.stdin.isTTY) {
|
|
3506
3555
|
console.error(
|
|
3507
3556
|
chalk.red(
|
|
3508
|
-
`Model "${failedModel}" is not available. Run \`${
|
|
3557
|
+
`Model "${failedModel}" is not available. Run \`${displayCaliberName()} config\` to select a different model.`
|
|
3509
3558
|
)
|
|
3510
3559
|
);
|
|
3511
3560
|
return null;
|
|
@@ -3531,7 +3580,7 @@ async function handleModelNotAvailable(failedModel, provider, config) {
|
|
|
3531
3580
|
if (models.length === 0) {
|
|
3532
3581
|
console.log(
|
|
3533
3582
|
chalk.red(
|
|
3534
|
-
` No alternative models found. Run \`${
|
|
3583
|
+
` No alternative models found. Run \`${displayCaliberName()} config\` to configure manually.`
|
|
3535
3584
|
)
|
|
3536
3585
|
);
|
|
3537
3586
|
return null;
|
|
@@ -3623,7 +3672,7 @@ function getProvider() {
|
|
|
3623
3672
|
const config = loadConfig();
|
|
3624
3673
|
if (!config) {
|
|
3625
3674
|
throw new Error(
|
|
3626
|
-
`No LLM provider configured. Set ANTHROPIC_API_KEY, OPENAI_API_KEY, MINIMAX_API_KEY, or VERTEX_PROJECT_ID; or run \`${
|
|
3675
|
+
`No LLM provider configured. Set ANTHROPIC_API_KEY, OPENAI_API_KEY, MINIMAX_API_KEY, or VERTEX_PROJECT_ID; or run \`${displayCaliberName()} config\` and choose Cursor, Claude Code, or OpenCode; or set CALIBER_USE_CURSOR_SEAT=1 / CALIBER_USE_CLAUDE_CLI=1 / CALIBER_USE_OPENCODE=1.`
|
|
3627
3676
|
);
|
|
3628
3677
|
}
|
|
3629
3678
|
cachedConfig = config;
|
|
@@ -4816,8 +4865,11 @@ var notificationHook = createScriptHook({
|
|
|
4816
4865
|
var isNotificationHookInstalled = notificationHook.isInstalled;
|
|
4817
4866
|
var installNotificationHook = notificationHook.install;
|
|
4818
4867
|
var removeNotificationHook = notificationHook.remove;
|
|
4819
|
-
var
|
|
4820
|
-
var
|
|
4868
|
+
var HOOK_BLOCK_VERSION = "v2";
|
|
4869
|
+
var PRECOMMIT_START = `# caliber:pre-commit:${HOOK_BLOCK_VERSION}:start`;
|
|
4870
|
+
var PRECOMMIT_END = `# caliber:pre-commit:${HOOK_BLOCK_VERSION}:end`;
|
|
4871
|
+
var PRECOMMIT_ANY_VERSION_START_RE = /^#\s*caliber:pre-commit:(?:[a-zA-Z0-9_.-]+:)?start\s*$/m;
|
|
4872
|
+
var PRECOMMIT_ANY_VERSION_BLOCK_RE = /\n?#\s*caliber:pre-commit:(?:[a-zA-Z0-9_.-]+:)?start[\s\S]*?#\s*caliber:pre-commit:(?:[a-zA-Z0-9_.-]+:)?end\n?/g;
|
|
4821
4873
|
function tryWindowsDirectNodeInvocation(cmd) {
|
|
4822
4874
|
if (process.platform !== "win32") return null;
|
|
4823
4875
|
if (!/\.cmd$/i.test(cmd)) return null;
|
|
@@ -4875,7 +4927,7 @@ function getPrecommitBlock() {
|
|
|
4875
4927
|
if ${guard}; then
|
|
4876
4928
|
mkdir -p .caliber
|
|
4877
4929
|
echo "\\033[2mcaliber: refreshing docs...\\033[0m"
|
|
4878
|
-
${invoke} refresh --quiet 2>.caliber/refresh-hook.log ||
|
|
4930
|
+
${invoke} refresh --quiet 2>.caliber/refresh-hook.log || echo "\\033[33mcaliber: refresh skipped \u2014 see .caliber/refresh-hook.log\\033[0m" >&2
|
|
4879
4931
|
${invoke} learn finalize 2>>.caliber/refresh-hook.log || true
|
|
4880
4932
|
git diff --name-only -- CLAUDE.md .claude/ .cursor/ AGENTS.md CALIBER_LEARNINGS.md .github/ .agents/ .opencode/ 2>/dev/null | xargs git add 2>/dev/null || true
|
|
4881
4933
|
fi
|
|
@@ -4900,19 +4952,29 @@ function isPreCommitHookInstalled() {
|
|
|
4900
4952
|
const hookPath = getPreCommitPath();
|
|
4901
4953
|
if (!hookPath || !fs11.existsSync(hookPath)) return false;
|
|
4902
4954
|
const content = fs11.readFileSync(hookPath, "utf-8");
|
|
4903
|
-
return
|
|
4955
|
+
return PRECOMMIT_ANY_VERSION_START_RE.test(content);
|
|
4904
4956
|
}
|
|
4905
4957
|
function installPreCommitHook() {
|
|
4906
|
-
if (isPreCommitHookInstalled()) {
|
|
4907
|
-
return { installed: false, alreadyInstalled: true };
|
|
4908
|
-
}
|
|
4909
4958
|
const hookPath = getPreCommitPath();
|
|
4910
|
-
if (!hookPath)
|
|
4959
|
+
if (!hookPath) {
|
|
4960
|
+
return { installed: false, alreadyInstalled: false, upgraded: false };
|
|
4961
|
+
}
|
|
4911
4962
|
const hooksDir = path10.dirname(hookPath);
|
|
4912
4963
|
if (!fs11.existsSync(hooksDir)) fs11.mkdirSync(hooksDir, { recursive: true });
|
|
4913
|
-
|
|
4914
|
-
|
|
4915
|
-
|
|
4964
|
+
const exists = fs11.existsSync(hookPath);
|
|
4965
|
+
let content = exists ? fs11.readFileSync(hookPath, "utf-8") : "";
|
|
4966
|
+
if (PRECOMMIT_ANY_VERSION_START_RE.test(content)) {
|
|
4967
|
+
if (content.includes(PRECOMMIT_START)) {
|
|
4968
|
+
return { installed: false, alreadyInstalled: true, upgraded: false };
|
|
4969
|
+
}
|
|
4970
|
+
content = content.replace(PRECOMMIT_ANY_VERSION_BLOCK_RE, "\n").replace(/\n{3,}/g, "\n\n");
|
|
4971
|
+
if (!content.endsWith("\n")) content += "\n";
|
|
4972
|
+
content += "\n" + getPrecommitBlock() + "\n";
|
|
4973
|
+
fs11.writeFileSync(hookPath, content);
|
|
4974
|
+
fs11.chmodSync(hookPath, 493);
|
|
4975
|
+
return { installed: false, alreadyInstalled: false, upgraded: true };
|
|
4976
|
+
}
|
|
4977
|
+
if (exists) {
|
|
4916
4978
|
if (!content.endsWith("\n")) content += "\n";
|
|
4917
4979
|
content += "\n" + getPrecommitBlock() + "\n";
|
|
4918
4980
|
} else {
|
|
@@ -4920,7 +4982,7 @@ function installPreCommitHook() {
|
|
|
4920
4982
|
}
|
|
4921
4983
|
fs11.writeFileSync(hookPath, content);
|
|
4922
4984
|
fs11.chmodSync(hookPath, 493);
|
|
4923
|
-
return { installed: true, alreadyInstalled: false };
|
|
4985
|
+
return { installed: true, alreadyInstalled: false, upgraded: false };
|
|
4924
4986
|
}
|
|
4925
4987
|
function removePreCommitHook() {
|
|
4926
4988
|
const hookPath = getPreCommitPath();
|
|
@@ -4928,11 +4990,10 @@ function removePreCommitHook() {
|
|
|
4928
4990
|
return { removed: false, notFound: true };
|
|
4929
4991
|
}
|
|
4930
4992
|
let content = fs11.readFileSync(hookPath, "utf-8");
|
|
4931
|
-
if (!
|
|
4993
|
+
if (!PRECOMMIT_ANY_VERSION_START_RE.test(content)) {
|
|
4932
4994
|
return { removed: false, notFound: true };
|
|
4933
4995
|
}
|
|
4934
|
-
|
|
4935
|
-
content = content.replace(regex, "\n");
|
|
4996
|
+
content = content.replace(PRECOMMIT_ANY_VERSION_BLOCK_RE, "\n").replace(/\n{3,}/g, "\n\n");
|
|
4936
4997
|
if (content.trim() === "#!/bin/sh" || content.trim() === "") {
|
|
4937
4998
|
fs11.unlinkSync(hookPath);
|
|
4938
4999
|
} else {
|
|
@@ -5570,7 +5631,8 @@ var CORE_MAX_TOKENS = 16e3;
|
|
|
5570
5631
|
var GENERATION_MAX_TOKENS = 64e3;
|
|
5571
5632
|
var MODEL_MAX_OUTPUT_TOKENS = 128e3;
|
|
5572
5633
|
var MAX_RETRIES2 = 5;
|
|
5573
|
-
var DEFAULT_INACTIVITY_TIMEOUT_MS =
|
|
5634
|
+
var DEFAULT_INACTIVITY_TIMEOUT_MS = 3e5;
|
|
5635
|
+
var SOFT_INACTIVITY_WARN_MS = 6e4;
|
|
5574
5636
|
var DEFAULT_TOTAL_TIMEOUT_MS = 6e5;
|
|
5575
5637
|
function parseEnvTimeout(envVar, defaultMs, minMs = 5e3) {
|
|
5576
5638
|
const val = process.env[envVar];
|
|
@@ -5823,14 +5885,30 @@ async function streamGeneration(config) {
|
|
|
5823
5885
|
let charsReceived = 0;
|
|
5824
5886
|
let settled = false;
|
|
5825
5887
|
let inactivityTimer = null;
|
|
5888
|
+
let softWarnTimer = null;
|
|
5889
|
+
let softWarnFired = false;
|
|
5826
5890
|
function clearInactivityTimer() {
|
|
5827
5891
|
if (inactivityTimer) {
|
|
5828
5892
|
clearTimeout(inactivityTimer);
|
|
5829
5893
|
inactivityTimer = null;
|
|
5830
5894
|
}
|
|
5895
|
+
if (softWarnTimer) {
|
|
5896
|
+
clearTimeout(softWarnTimer);
|
|
5897
|
+
softWarnTimer = null;
|
|
5898
|
+
}
|
|
5831
5899
|
}
|
|
5832
5900
|
function resetInactivityTimer() {
|
|
5833
5901
|
if (inactivityTimer) clearTimeout(inactivityTimer);
|
|
5902
|
+
if (softWarnTimer) clearTimeout(softWarnTimer);
|
|
5903
|
+
if (config.callbacks && !softWarnFired && SOFT_INACTIVITY_WARN_MS < inactivityTimeoutMs) {
|
|
5904
|
+
softWarnTimer = setTimeout(() => {
|
|
5905
|
+
if (settled) return;
|
|
5906
|
+
softWarnFired = true;
|
|
5907
|
+
config.callbacks?.onStatus(
|
|
5908
|
+
"Model is taking longer than usual on this prompt \u2014 large repos may need more time. Set CALIBER_STREAM_INACTIVITY_TIMEOUT_MS to override."
|
|
5909
|
+
);
|
|
5910
|
+
}, SOFT_INACTIVITY_WARN_MS);
|
|
5911
|
+
}
|
|
5834
5912
|
inactivityTimer = setTimeout(() => {
|
|
5835
5913
|
if (settled) return;
|
|
5836
5914
|
settled = true;
|
|
@@ -7745,10 +7823,11 @@ function detectGitDrift(dir) {
|
|
|
7745
7823
|
}
|
|
7746
7824
|
const configFiles = ["CLAUDE.md", "AGENTS.md", ".cursorrules", ".cursor/rules"];
|
|
7747
7825
|
try {
|
|
7748
|
-
const headTimestamp = execSync12(
|
|
7749
|
-
|
|
7750
|
-
|
|
7751
|
-
|
|
7826
|
+
const headTimestamp = execSync12("git log -1 --format=%ct HEAD", {
|
|
7827
|
+
cwd: dir,
|
|
7828
|
+
encoding: "utf-8",
|
|
7829
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
7830
|
+
}).trim();
|
|
7752
7831
|
const headTime = parseInt(headTimestamp, 10) * 1e3;
|
|
7753
7832
|
for (const file of configFiles) {
|
|
7754
7833
|
const filePath = join5(dir, file);
|
|
@@ -7756,7 +7835,11 @@ function detectGitDrift(dir) {
|
|
|
7756
7835
|
try {
|
|
7757
7836
|
const mtime = statSync(filePath).mtime.getTime();
|
|
7758
7837
|
if (mtime > headTime) {
|
|
7759
|
-
return {
|
|
7838
|
+
return {
|
|
7839
|
+
commitsSinceConfigUpdate: 0,
|
|
7840
|
+
lastConfigCommit: "uncommitted (recently modified)",
|
|
7841
|
+
isGitRepo: true
|
|
7842
|
+
};
|
|
7760
7843
|
}
|
|
7761
7844
|
} catch {
|
|
7762
7845
|
}
|
|
@@ -7766,19 +7849,20 @@ function detectGitDrift(dir) {
|
|
|
7766
7849
|
let latestConfigCommitHash = null;
|
|
7767
7850
|
for (const file of configFiles) {
|
|
7768
7851
|
try {
|
|
7769
|
-
const hash = execSync12(
|
|
7770
|
-
|
|
7771
|
-
|
|
7772
|
-
|
|
7852
|
+
const hash = execSync12(`git log -1 --format=%H -- "${file}"`, {
|
|
7853
|
+
cwd: dir,
|
|
7854
|
+
encoding: "utf-8",
|
|
7855
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
7856
|
+
}).trim();
|
|
7773
7857
|
if (!hash) continue;
|
|
7774
7858
|
if (!latestConfigCommitHash) {
|
|
7775
7859
|
latestConfigCommitHash = hash;
|
|
7776
7860
|
} else {
|
|
7777
7861
|
try {
|
|
7778
|
-
execSync12(
|
|
7779
|
-
|
|
7780
|
-
|
|
7781
|
-
);
|
|
7862
|
+
execSync12(`git merge-base --is-ancestor ${latestConfigCommitHash} ${hash}`, {
|
|
7863
|
+
cwd: dir,
|
|
7864
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
7865
|
+
});
|
|
7782
7866
|
latestConfigCommitHash = hash;
|
|
7783
7867
|
} catch {
|
|
7784
7868
|
}
|
|
@@ -7790,22 +7874,28 @@ function detectGitDrift(dir) {
|
|
|
7790
7874
|
return { commitsSinceConfigUpdate: 0, lastConfigCommit: null, isGitRepo: true };
|
|
7791
7875
|
}
|
|
7792
7876
|
try {
|
|
7793
|
-
const countStr = execSync12(
|
|
7794
|
-
|
|
7795
|
-
|
|
7796
|
-
|
|
7877
|
+
const countStr = execSync12(`git rev-list --count ${latestConfigCommitHash}..HEAD`, {
|
|
7878
|
+
cwd: dir,
|
|
7879
|
+
encoding: "utf-8",
|
|
7880
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
7881
|
+
}).trim();
|
|
7797
7882
|
const commitsSince = parseInt(countStr, 10) || 0;
|
|
7798
|
-
const lastDate = execSync12(
|
|
7799
|
-
|
|
7800
|
-
|
|
7801
|
-
|
|
7883
|
+
const lastDate = execSync12(`git log -1 --format=%ci ${latestConfigCommitHash}`, {
|
|
7884
|
+
cwd: dir,
|
|
7885
|
+
encoding: "utf-8",
|
|
7886
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
7887
|
+
}).trim();
|
|
7802
7888
|
return {
|
|
7803
7889
|
commitsSinceConfigUpdate: commitsSince,
|
|
7804
7890
|
lastConfigCommit: lastDate,
|
|
7805
7891
|
isGitRepo: true
|
|
7806
7892
|
};
|
|
7807
7893
|
} catch {
|
|
7808
|
-
return {
|
|
7894
|
+
return {
|
|
7895
|
+
commitsSinceConfigUpdate: 0,
|
|
7896
|
+
lastConfigCommit: latestConfigCommitHash,
|
|
7897
|
+
isGitRepo: true
|
|
7898
|
+
};
|
|
7809
7899
|
}
|
|
7810
7900
|
}
|
|
7811
7901
|
function checkAccuracy(dir) {
|
|
@@ -7855,10 +7945,13 @@ function checkAccuracy(dir) {
|
|
|
7855
7945
|
earnedPoints: driftPoints,
|
|
7856
7946
|
passed: drift.commitsSinceConfigUpdate <= 15 || !drift.isGitRepo,
|
|
7857
7947
|
detail: !drift.isGitRepo ? "Not a git repository \u2014 skipping drift check" : !drift.lastConfigCommit ? "Config files not tracked in git" : drift.commitsSinceConfigUpdate === 0 ? "Config is up to date with latest commits" : `${drift.commitsSinceConfigUpdate} commit${drift.commitsSinceConfigUpdate === 1 ? "" : "s"} since last config update`,
|
|
7858
|
-
suggestion: drift.commitsSinceConfigUpdate > 15 ? `Code has had ${drift.commitsSinceConfigUpdate} commits since last config update \u2014 run \`${
|
|
7948
|
+
suggestion: drift.commitsSinceConfigUpdate > 15 ? `Code has had ${drift.commitsSinceConfigUpdate} commits since last config update \u2014 run \`${displayCaliberName()} refresh\` to sync` : void 0,
|
|
7859
7949
|
fix: drift.commitsSinceConfigUpdate > 15 ? {
|
|
7860
7950
|
action: "refresh_config",
|
|
7861
|
-
data: {
|
|
7951
|
+
data: {
|
|
7952
|
+
commitsSince: drift.commitsSinceConfigUpdate,
|
|
7953
|
+
lastConfigCommit: drift.lastConfigCommit
|
|
7954
|
+
},
|
|
7862
7955
|
instruction: `Config is ${drift.commitsSinceConfigUpdate} commits behind. Review recent changes and update config accordingly.`
|
|
7863
7956
|
} : void 0
|
|
7864
7957
|
});
|
|
@@ -7873,10 +7966,11 @@ import { join as join6 } from "path";
|
|
|
7873
7966
|
function getCommitsSinceConfigUpdate(dir) {
|
|
7874
7967
|
const configFiles = ["CLAUDE.md", "AGENTS.md", ".cursorrules"];
|
|
7875
7968
|
try {
|
|
7876
|
-
const headTimestamp = execSync13(
|
|
7877
|
-
|
|
7878
|
-
|
|
7879
|
-
|
|
7969
|
+
const headTimestamp = execSync13("git log -1 --format=%ct HEAD", {
|
|
7970
|
+
cwd: dir,
|
|
7971
|
+
encoding: "utf-8",
|
|
7972
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
7973
|
+
}).trim();
|
|
7880
7974
|
const headTime = parseInt(headTimestamp, 10) * 1e3;
|
|
7881
7975
|
for (const file of configFiles) {
|
|
7882
7976
|
const filePath = join6(dir, file);
|
|
@@ -7893,15 +7987,17 @@ function getCommitsSinceConfigUpdate(dir) {
|
|
|
7893
7987
|
}
|
|
7894
7988
|
for (const file of configFiles) {
|
|
7895
7989
|
try {
|
|
7896
|
-
const hash = execSync13(
|
|
7897
|
-
|
|
7898
|
-
|
|
7899
|
-
|
|
7990
|
+
const hash = execSync13(`git log -1 --format=%H -- "${file}"`, {
|
|
7991
|
+
cwd: dir,
|
|
7992
|
+
encoding: "utf-8",
|
|
7993
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
7994
|
+
}).trim();
|
|
7900
7995
|
if (hash) {
|
|
7901
|
-
const countStr = execSync13(
|
|
7902
|
-
|
|
7903
|
-
|
|
7904
|
-
|
|
7996
|
+
const countStr = execSync13(`git rev-list --count ${hash}..HEAD`, {
|
|
7997
|
+
cwd: dir,
|
|
7998
|
+
encoding: "utf-8",
|
|
7999
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
8000
|
+
}).trim();
|
|
7905
8001
|
return parseInt(countStr, 10) || 0;
|
|
7906
8002
|
}
|
|
7907
8003
|
} catch {
|
|
@@ -7930,7 +8026,7 @@ function checkFreshness(dir) {
|
|
|
7930
8026
|
earnedPoints: freshnessPoints,
|
|
7931
8027
|
passed: freshnessPoints >= 3,
|
|
7932
8028
|
detail: freshnessDetail,
|
|
7933
|
-
suggestion: commitsSince !== null && freshnessPoints < 3 ? `Config is ${commitsSince} commits behind \u2014 run \`${
|
|
8029
|
+
suggestion: commitsSince !== null && freshnessPoints < 3 ? `Config is ${commitsSince} commits behind \u2014 run \`${displayCaliberName()} refresh\` to update it` : void 0,
|
|
7934
8030
|
fix: commitsSince !== null && freshnessPoints < 3 ? {
|
|
7935
8031
|
action: "refresh_config",
|
|
7936
8032
|
data: { commitsSince },
|
|
@@ -8082,11 +8178,11 @@ function checkBonus(dir) {
|
|
|
8082
8178
|
earnedPoints: hasHooks ? POINTS_HOOKS : 0,
|
|
8083
8179
|
passed: hasHooks,
|
|
8084
8180
|
detail: hasHooks ? hookSources.join(", ") : "No hooks configured",
|
|
8085
|
-
suggestion: hasHooks ? void 0 : `Hooks auto-sync your agent config on every commit so it stays fresh. Run \`${
|
|
8181
|
+
suggestion: hasHooks ? void 0 : `Hooks auto-sync your agent config on every commit so it stays fresh. Run \`${displayCaliberName()} init\` to set up`,
|
|
8086
8182
|
fix: hasHooks ? void 0 : {
|
|
8087
8183
|
action: "install_hooks",
|
|
8088
8184
|
data: {},
|
|
8089
|
-
instruction: `Run ${
|
|
8185
|
+
instruction: `Run ${displayCaliberName()} init to add pre-commit refresh instructions to config files.`
|
|
8090
8186
|
}
|
|
8091
8187
|
});
|
|
8092
8188
|
const agentsMdExists = existsSync6(join7(dir, "AGENTS.md"));
|
|
@@ -8151,7 +8247,7 @@ function checkBonus(dir) {
|
|
|
8151
8247
|
earnedPoints: hasLearned ? POINTS_LEARNED_CONTENT : 0,
|
|
8152
8248
|
passed: hasLearned,
|
|
8153
8249
|
detail: hasLearned ? "Session learnings found in CALIBER_LEARNINGS.md" : "No learned content",
|
|
8154
|
-
suggestion: hasLearned ? void 0 : `Session learnings capture patterns from your coding sessions so the agent improves over time. Run \`${
|
|
8250
|
+
suggestion: hasLearned ? void 0 : `Session learnings capture patterns from your coding sessions so the agent improves over time. Run \`${displayCaliberName()} learn install\``
|
|
8155
8251
|
});
|
|
8156
8252
|
const configContent = (() => {
|
|
8157
8253
|
const parts = [];
|
|
@@ -8198,7 +8294,7 @@ function checkSources(dir) {
|
|
|
8198
8294
|
earnedPoints: hasSources ? POINTS_SOURCES_CONFIGURED : 0,
|
|
8199
8295
|
passed: hasSources,
|
|
8200
8296
|
detail: hasSources ? `${configSources.length} source${configSources.length === 1 ? "" : "s"} configured` : "No external sources configured",
|
|
8201
|
-
suggestion: hasSources ? void 0 : `Run \`${
|
|
8297
|
+
suggestion: hasSources ? void 0 : `Run \`${displayCaliberName()} sources add <path>\` to add related repos or docs`
|
|
8202
8298
|
});
|
|
8203
8299
|
if (hasSources) {
|
|
8204
8300
|
const claudeMd = readFileOrNull(join8(dir, "CLAUDE.md"));
|
|
@@ -8216,7 +8312,7 @@ function checkSources(dir) {
|
|
|
8216
8312
|
earnedPoints: referenced ? POINTS_SOURCES_REFERENCED : 0,
|
|
8217
8313
|
passed: referenced,
|
|
8218
8314
|
detail: referenced ? "At least one source is referenced in CLAUDE.md" : "No configured sources are mentioned in CLAUDE.md",
|
|
8219
|
-
suggestion: referenced ? void 0 : `Regenerate with \`${
|
|
8315
|
+
suggestion: referenced ? void 0 : `Regenerate with \`${displayCaliberName()} init\` to include source context in your config`
|
|
8220
8316
|
});
|
|
8221
8317
|
}
|
|
8222
8318
|
return checks;
|
|
@@ -8327,7 +8423,14 @@ var CATEGORY_LABELS = {
|
|
|
8327
8423
|
freshness: { icon: "\u{1F6E1}\uFE0F", label: "FRESHNESS & SAFETY" },
|
|
8328
8424
|
bonus: { icon: "\u2B50", label: "BONUS" }
|
|
8329
8425
|
};
|
|
8330
|
-
var CATEGORY_ORDER = [
|
|
8426
|
+
var CATEGORY_ORDER = [
|
|
8427
|
+
"existence",
|
|
8428
|
+
"quality",
|
|
8429
|
+
"grounding",
|
|
8430
|
+
"accuracy",
|
|
8431
|
+
"freshness",
|
|
8432
|
+
"bonus"
|
|
8433
|
+
];
|
|
8331
8434
|
function gradeColor(grade) {
|
|
8332
8435
|
switch (grade) {
|
|
8333
8436
|
case "A":
|
|
@@ -8396,7 +8499,9 @@ function displayScore(result) {
|
|
|
8396
8499
|
console.log("");
|
|
8397
8500
|
console.log(chalk3.gray(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
8398
8501
|
console.log("");
|
|
8399
|
-
console.log(
|
|
8502
|
+
console.log(
|
|
8503
|
+
` ${chalk3.bold("Agent Config Score")} ${gc(chalk3.bold(`${result.score} / ${result.maxScore}`))} Grade ${gc(chalk3.bold(result.grade))}`
|
|
8504
|
+
);
|
|
8400
8505
|
console.log(` ${progressBar(result.score, result.maxScore)}`);
|
|
8401
8506
|
console.log(chalk3.dim(` Target: ${agentLabel}`));
|
|
8402
8507
|
console.log("");
|
|
@@ -8419,7 +8524,11 @@ function displayScore(result) {
|
|
|
8419
8524
|
formatTopImprovements(result.checks);
|
|
8420
8525
|
}
|
|
8421
8526
|
function formatTopImprovements(checks) {
|
|
8422
|
-
const improvable = checks.filter((c) => c.earnedPoints < c.maxPoints).map((c) => ({
|
|
8527
|
+
const improvable = checks.filter((c) => c.earnedPoints < c.maxPoints).map((c) => ({
|
|
8528
|
+
name: c.name,
|
|
8529
|
+
potential: c.maxPoints - c.earnedPoints,
|
|
8530
|
+
suggestion: c.suggestion
|
|
8531
|
+
})).sort((a, b) => b.potential - a.potential).slice(0, 5);
|
|
8423
8532
|
if (improvable.length === 0) return;
|
|
8424
8533
|
console.log(chalk3.gray(" \u2500 TOP IMPROVEMENTS \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
8425
8534
|
console.log("");
|
|
@@ -8450,8 +8559,12 @@ function displayScoreSummary(result) {
|
|
|
8450
8559
|
}
|
|
8451
8560
|
const remaining = failing.length - shown.length;
|
|
8452
8561
|
const moreText = remaining > 0 ? ` (+${remaining} more)` : "";
|
|
8453
|
-
console.log(
|
|
8454
|
-
|
|
8562
|
+
console.log(
|
|
8563
|
+
chalk3.dim(
|
|
8564
|
+
`
|
|
8565
|
+
Run ${chalk3.hex("#83D1EB")(`${displayCaliberName()} score`)} for details.${moreText}`
|
|
8566
|
+
)
|
|
8567
|
+
);
|
|
8455
8568
|
}
|
|
8456
8569
|
console.log("");
|
|
8457
8570
|
}
|
|
@@ -8467,7 +8580,9 @@ function displayScoreDelta(before, after) {
|
|
|
8467
8580
|
console.log(
|
|
8468
8581
|
` Score: ${beforeGc(`${before.score}`)} ${chalk3.gray("\u2192")} ${afterGc(`${after.score}`)} ${deltaColor(deltaStr + " pts")} ${beforeGc(before.grade)} ${chalk3.gray("\u2192")} ${afterGc(after.grade)}`
|
|
8469
8582
|
);
|
|
8470
|
-
console.log(
|
|
8583
|
+
console.log(
|
|
8584
|
+
` ${progressBar(before.score, before.maxScore, 19)} ${chalk3.gray("\u2192")} ${progressBar(after.score, after.maxScore, 19)}`
|
|
8585
|
+
);
|
|
8471
8586
|
console.log("");
|
|
8472
8587
|
console.log(chalk3.gray(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
8473
8588
|
console.log("");
|
|
@@ -9149,7 +9264,7 @@ async function querySkills(query) {
|
|
|
9149
9264
|
console.log("");
|
|
9150
9265
|
console.log(
|
|
9151
9266
|
chalk5.dim(
|
|
9152
|
-
` Install with: ${
|
|
9267
|
+
` Install with: ${displayCaliberName()} skills --install ${available.map((r) => r.slug).join(",")}`
|
|
9153
9268
|
)
|
|
9154
9269
|
);
|
|
9155
9270
|
console.log("");
|
|
@@ -11137,7 +11252,7 @@ function log(verbose, ...args) {
|
|
|
11137
11252
|
async function initCommand(options) {
|
|
11138
11253
|
const brand = chalk14.hex("#EB9D83");
|
|
11139
11254
|
const title = chalk14.hex("#83D1EB");
|
|
11140
|
-
const bin =
|
|
11255
|
+
const bin = displayCaliberName();
|
|
11141
11256
|
const firstRun = isFirstRun(process.cwd());
|
|
11142
11257
|
if (firstRun) {
|
|
11143
11258
|
console.log(
|
|
@@ -11278,6 +11393,8 @@ async function initCommand(options) {
|
|
|
11278
11393
|
const hookResult = installPreCommitHook();
|
|
11279
11394
|
if (hookResult.installed) {
|
|
11280
11395
|
console.log(` ${chalk14.green("\u2713")} Pre-commit hook installed \u2014 configs sync on every commit`);
|
|
11396
|
+
} else if (hookResult.upgraded) {
|
|
11397
|
+
console.log(` ${chalk14.green("\u2713")} Pre-commit hook \u2014 upgraded to latest version`);
|
|
11281
11398
|
} else if (hookResult.alreadyInstalled) {
|
|
11282
11399
|
console.log(` ${chalk14.green("\u2713")} Pre-commit hook \u2014 active`);
|
|
11283
11400
|
}
|
|
@@ -11977,24 +12094,34 @@ async function statusCommand(options) {
|
|
|
11977
12094
|
const config = loadConfig();
|
|
11978
12095
|
const manifest = readManifest();
|
|
11979
12096
|
if (options.json) {
|
|
11980
|
-
console.log(
|
|
11981
|
-
|
|
11982
|
-
|
|
11983
|
-
|
|
11984
|
-
|
|
11985
|
-
|
|
12097
|
+
console.log(
|
|
12098
|
+
JSON.stringify(
|
|
12099
|
+
{
|
|
12100
|
+
configured: !!config,
|
|
12101
|
+
provider: config?.provider,
|
|
12102
|
+
model: config?.model,
|
|
12103
|
+
manifest
|
|
12104
|
+
},
|
|
12105
|
+
null,
|
|
12106
|
+
2
|
|
12107
|
+
)
|
|
12108
|
+
);
|
|
11986
12109
|
return;
|
|
11987
12110
|
}
|
|
11988
12111
|
console.log(chalk16.bold("\nCaliber Status\n"));
|
|
11989
12112
|
if (config) {
|
|
11990
12113
|
console.log(` LLM: ${chalk16.green(config.provider)} (${config.model})`);
|
|
11991
12114
|
} else {
|
|
11992
|
-
const bin =
|
|
11993
|
-
console.log(
|
|
12115
|
+
const bin = displayCaliberName();
|
|
12116
|
+
console.log(
|
|
12117
|
+
` LLM: ${chalk16.yellow("Not configured")} \u2014 run ${chalk16.hex("#83D1EB")(`${bin} config`)}`
|
|
12118
|
+
);
|
|
11994
12119
|
}
|
|
11995
12120
|
if (!manifest) {
|
|
11996
12121
|
console.log(` Config: ${chalk16.dim("No config applied")}`);
|
|
11997
|
-
console.log(
|
|
12122
|
+
console.log(
|
|
12123
|
+
chalk16.dim("\n Run ") + chalk16.hex("#83D1EB")(`${displayCaliberName()} init`) + chalk16.dim(" to get started.\n")
|
|
12124
|
+
);
|
|
11998
12125
|
return;
|
|
11999
12126
|
}
|
|
12000
12127
|
console.log(` Files managed: ${chalk16.cyan(manifest.entries.length.toString())}`);
|
|
@@ -12014,15 +12141,19 @@ init_review();
|
|
|
12014
12141
|
init_config();
|
|
12015
12142
|
init_resolve_caliber();
|
|
12016
12143
|
async function regenerateCommand(options) {
|
|
12017
|
-
const bin =
|
|
12144
|
+
const bin = displayCaliberName();
|
|
12018
12145
|
const config = loadConfig();
|
|
12019
12146
|
if (!config) {
|
|
12020
|
-
console.log(
|
|
12147
|
+
console.log(
|
|
12148
|
+
chalk17.red("No LLM provider configured. Run ") + chalk17.hex("#83D1EB")(`${bin} config`) + chalk17.red(" first.")
|
|
12149
|
+
);
|
|
12021
12150
|
throw new Error("__exit__");
|
|
12022
12151
|
}
|
|
12023
12152
|
const manifest = readManifest();
|
|
12024
12153
|
if (!manifest) {
|
|
12025
|
-
console.log(
|
|
12154
|
+
console.log(
|
|
12155
|
+
chalk17.yellow("No existing config found. Run ") + chalk17.hex("#83D1EB")(`${bin} init`) + chalk17.yellow(" first.")
|
|
12156
|
+
);
|
|
12026
12157
|
throw new Error("__exit__");
|
|
12027
12158
|
}
|
|
12028
12159
|
const targetAgent = readState()?.targetAgent ?? ["claude", "cursor"];
|
|
@@ -12037,27 +12168,24 @@ async function regenerateCommand(options) {
|
|
|
12037
12168
|
return;
|
|
12038
12169
|
}
|
|
12039
12170
|
const genSpinner = ora5("Regenerating config...").start();
|
|
12040
|
-
const genMessages = new SpinnerMessages(genSpinner, GENERATION_MESSAGES, {
|
|
12171
|
+
const genMessages = new SpinnerMessages(genSpinner, GENERATION_MESSAGES, {
|
|
12172
|
+
showElapsedTime: true
|
|
12173
|
+
});
|
|
12041
12174
|
genMessages.start();
|
|
12042
12175
|
let generatedSetup = null;
|
|
12043
12176
|
try {
|
|
12044
|
-
const result = await generateSetup(
|
|
12045
|
-
|
|
12046
|
-
|
|
12047
|
-
|
|
12048
|
-
{
|
|
12049
|
-
|
|
12050
|
-
|
|
12051
|
-
|
|
12052
|
-
|
|
12053
|
-
|
|
12054
|
-
},
|
|
12055
|
-
onError: (error) => {
|
|
12056
|
-
genMessages.stop();
|
|
12057
|
-
genSpinner.fail(`Generation error: ${error}`);
|
|
12058
|
-
}
|
|
12177
|
+
const result = await generateSetup(fingerprint, targetAgent, void 0, {
|
|
12178
|
+
onStatus: (status) => {
|
|
12179
|
+
genMessages.handleServerStatus(status);
|
|
12180
|
+
},
|
|
12181
|
+
onComplete: (setup) => {
|
|
12182
|
+
generatedSetup = setup;
|
|
12183
|
+
},
|
|
12184
|
+
onError: (error) => {
|
|
12185
|
+
genMessages.stop();
|
|
12186
|
+
genSpinner.fail(`Generation error: ${error}`);
|
|
12059
12187
|
}
|
|
12060
|
-
);
|
|
12188
|
+
});
|
|
12061
12189
|
if (!generatedSetup) generatedSetup = result.setup;
|
|
12062
12190
|
} catch (err) {
|
|
12063
12191
|
genMessages.stop();
|
|
@@ -12075,9 +12203,13 @@ async function regenerateCommand(options) {
|
|
|
12075
12203
|
const setupFiles = collectSetupFiles(generatedSetup, targetAgent);
|
|
12076
12204
|
const staged = stageFiles(setupFiles, process.cwd());
|
|
12077
12205
|
const totalChanges = staged.newFiles + staged.modifiedFiles;
|
|
12078
|
-
console.log(
|
|
12206
|
+
console.log(
|
|
12207
|
+
chalk17.dim(
|
|
12208
|
+
`
|
|
12079
12209
|
${chalk17.green(`${staged.newFiles} new`)} / ${chalk17.yellow(`${staged.modifiedFiles} modified`)} file${totalChanges !== 1 ? "s" : ""}
|
|
12080
|
-
`
|
|
12210
|
+
`
|
|
12211
|
+
)
|
|
12212
|
+
);
|
|
12081
12213
|
if (totalChanges === 0) {
|
|
12082
12214
|
console.log(chalk17.dim(" No changes needed \u2014 your configs are already up to date.\n"));
|
|
12083
12215
|
cleanupStaging();
|
|
@@ -12138,21 +12270,33 @@ async function regenerateCommand(options) {
|
|
|
12138
12270
|
const afterScore = computeLocalScore(process.cwd(), targetAgent);
|
|
12139
12271
|
if (afterScore.score < baselineScore.score) {
|
|
12140
12272
|
console.log("");
|
|
12141
|
-
console.log(
|
|
12273
|
+
console.log(
|
|
12274
|
+
chalk17.yellow(
|
|
12275
|
+
` Score would drop from ${baselineScore.score} to ${afterScore.score} \u2014 reverting changes.`
|
|
12276
|
+
)
|
|
12277
|
+
);
|
|
12142
12278
|
try {
|
|
12143
12279
|
const { restored, removed } = undoSetup();
|
|
12144
12280
|
if (restored.length > 0 || removed.length > 0) {
|
|
12145
|
-
console.log(
|
|
12281
|
+
console.log(
|
|
12282
|
+
chalk17.dim(
|
|
12283
|
+
` Reverted ${restored.length + removed.length} file${restored.length + removed.length === 1 ? "" : "s"} from backup.`
|
|
12284
|
+
)
|
|
12285
|
+
);
|
|
12146
12286
|
}
|
|
12147
12287
|
} catch {
|
|
12148
12288
|
}
|
|
12149
|
-
console.log(
|
|
12289
|
+
console.log(
|
|
12290
|
+
chalk17.dim(" Run ") + chalk17.hex("#83D1EB")(`${bin} init --force`) + chalk17.dim(" to override.\n")
|
|
12291
|
+
);
|
|
12150
12292
|
return;
|
|
12151
12293
|
}
|
|
12152
12294
|
displayScoreDelta(baselineScore, afterScore);
|
|
12153
12295
|
trackRegenerateCompleted(action, Date.now());
|
|
12154
12296
|
console.log(chalk17.bold.green(" Regeneration complete!"));
|
|
12155
|
-
console.log(
|
|
12297
|
+
console.log(
|
|
12298
|
+
chalk17.dim(" Run ") + chalk17.hex("#83D1EB")(`${bin} undo`) + chalk17.dim(" to revert changes.\n")
|
|
12299
|
+
);
|
|
12156
12300
|
}
|
|
12157
12301
|
|
|
12158
12302
|
// src/commands/score.ts
|
|
@@ -12267,7 +12411,7 @@ async function scoreCommand(options) {
|
|
|
12267
12411
|
displayScore(result);
|
|
12268
12412
|
const separator = chalk18.gray(" " + "\u2500".repeat(53));
|
|
12269
12413
|
console.log(separator);
|
|
12270
|
-
const bin =
|
|
12414
|
+
const bin = displayCaliberName();
|
|
12271
12415
|
const failing = result.checks.filter((c) => !c.passed && c.maxPoints > 0).sort((a, b) => b.maxPoints - b.earnedPoints - (a.maxPoints - a.earnedPoints));
|
|
12272
12416
|
if (result.score < 70 && failing.length > 0) {
|
|
12273
12417
|
const topFix = failing[0];
|
|
@@ -13204,6 +13348,7 @@ async function refreshSingleRepo(repoDir, options) {
|
|
|
13204
13348
|
async function refreshCommand(options) {
|
|
13205
13349
|
const quiet = !!options.quiet;
|
|
13206
13350
|
if (quiet && isCaliberSubprocess()) return;
|
|
13351
|
+
if (quiet && isHookCascadeFromUserClaudeSession()) return;
|
|
13207
13352
|
if (quiet) {
|
|
13208
13353
|
const { isCaliberRunning: isCaliberRunning2 } = await Promise.resolve().then(() => (init_lock(), lock_exports));
|
|
13209
13354
|
if (isCaliberRunning2()) return;
|
|
@@ -13228,7 +13373,7 @@ async function refreshCommand(options) {
|
|
|
13228
13373
|
if (!config) {
|
|
13229
13374
|
if (quiet) return;
|
|
13230
13375
|
console.log(
|
|
13231
|
-
chalk19.red("No LLM provider configured. Run ") + chalk19.hex("#83D1EB")(`${
|
|
13376
|
+
chalk19.red("No LLM provider configured. Run ") + chalk19.hex("#83D1EB")(`${displayCaliberName()} config`) + chalk19.red(" (e.g. choose Cursor) or set an API key.")
|
|
13232
13377
|
);
|
|
13233
13378
|
throw new Error("__exit__");
|
|
13234
13379
|
}
|
|
@@ -13336,7 +13481,9 @@ async function hooksCommand(options) {
|
|
|
13336
13481
|
if (options.install) {
|
|
13337
13482
|
for (const hook of HOOKS) {
|
|
13338
13483
|
const result = hook.install();
|
|
13339
|
-
if (result.
|
|
13484
|
+
if (result.upgraded) {
|
|
13485
|
+
console.log(chalk20.green(" \u2713") + ` ${hook.label} upgraded to latest version`);
|
|
13486
|
+
} else if (result.alreadyInstalled) {
|
|
13340
13487
|
console.log(chalk20.dim(` ${hook.label} already enabled.`));
|
|
13341
13488
|
} else {
|
|
13342
13489
|
console.log(chalk20.green(" \u2713") + ` ${hook.label} enabled`);
|
|
@@ -14253,6 +14400,7 @@ async function learnFinalizeCommand(options) {
|
|
|
14253
14400
|
const isAuto = options?.auto === true;
|
|
14254
14401
|
const isIncremental = options?.incremental === true;
|
|
14255
14402
|
if (isAuto && isCaliberSubprocess()) return;
|
|
14403
|
+
if (isAuto && isHookCascadeFromUserClaudeSession()) return;
|
|
14256
14404
|
if (!options?.force && !isAuto) {
|
|
14257
14405
|
const { isCaliberRunning: isCaliberRunning2 } = await Promise.resolve().then(() => (init_lock(), lock_exports));
|
|
14258
14406
|
if (isCaliberRunning2()) {
|
|
@@ -14276,7 +14424,7 @@ async function learnFinalizeCommand(options) {
|
|
|
14276
14424
|
if (isAuto) return;
|
|
14277
14425
|
console.log(
|
|
14278
14426
|
chalk23.yellow(
|
|
14279
|
-
`caliber: no LLM provider configured \u2014 run \`${
|
|
14427
|
+
`caliber: no LLM provider configured \u2014 run \`${displayCaliberName()} config\` first`
|
|
14280
14428
|
)
|
|
14281
14429
|
);
|
|
14282
14430
|
clearSession();
|
|
@@ -14442,7 +14590,7 @@ async function learnFinalizeCommand(options) {
|
|
|
14442
14590
|
if (staleLearnings.length > 0 && !isAuto) {
|
|
14443
14591
|
console.log(
|
|
14444
14592
|
chalk23.yellow(
|
|
14445
|
-
`caliber: ${staleLearnings.length} learning${staleLearnings.length === 1 ? "" : "s"} never activated \u2014 run \`${
|
|
14593
|
+
`caliber: ${staleLearnings.length} learning${staleLearnings.length === 1 ? "" : "s"} never activated \u2014 run \`${displayCaliberName()} learn list --verbose\` to review`
|
|
14446
14594
|
)
|
|
14447
14595
|
);
|
|
14448
14596
|
}
|
|
@@ -14499,7 +14647,7 @@ async function learnInstallCommand() {
|
|
|
14499
14647
|
if (!fs48.existsSync(".claude") && !fs48.existsSync(".cursor")) {
|
|
14500
14648
|
console.log(chalk23.yellow("No .claude/ or .cursor/ directory found."));
|
|
14501
14649
|
console.log(
|
|
14502
|
-
chalk23.dim(` Run \`${
|
|
14650
|
+
chalk23.dim(` Run \`${displayCaliberName()} init\` first, or create the directory manually.`)
|
|
14503
14651
|
);
|
|
14504
14652
|
return;
|
|
14505
14653
|
}
|
|
@@ -14547,7 +14695,7 @@ async function learnStatusCommand() {
|
|
|
14547
14695
|
}
|
|
14548
14696
|
if (!claudeInstalled && !cursorInstalled) {
|
|
14549
14697
|
console.log(
|
|
14550
|
-
chalk23.dim(` Run \`${
|
|
14698
|
+
chalk23.dim(` Run \`${displayCaliberName()} learn install\` to enable session learning.`)
|
|
14551
14699
|
);
|
|
14552
14700
|
}
|
|
14553
14701
|
console.log();
|
|
@@ -14603,7 +14751,9 @@ function getAllLearnings() {
|
|
|
14603
14751
|
async function learnListCommand(options) {
|
|
14604
14752
|
const items = getAllLearnings();
|
|
14605
14753
|
if (items.length === 0) {
|
|
14606
|
-
console.log(
|
|
14754
|
+
console.log(
|
|
14755
|
+
chalk23.dim(`No learnings yet. Run \`${displayCaliberName()} learn install\` to start.`)
|
|
14756
|
+
);
|
|
14607
14757
|
return;
|
|
14608
14758
|
}
|
|
14609
14759
|
const roiStats = options?.verbose ? readROIStats() : null;
|
|
@@ -14634,7 +14784,7 @@ async function learnDeleteCommand(indexStr) {
|
|
|
14634
14784
|
if (isNaN(index) || index < 1) {
|
|
14635
14785
|
console.log(
|
|
14636
14786
|
chalk23.red(
|
|
14637
|
-
`Invalid index: "${indexStr}". Use a number from \`${
|
|
14787
|
+
`Invalid index: "${indexStr}". Use a number from \`${displayCaliberName()} learn list\`.`
|
|
14638
14788
|
)
|
|
14639
14789
|
);
|
|
14640
14790
|
return;
|
|
@@ -14745,13 +14895,23 @@ function displayColdStart(score) {
|
|
|
14745
14895
|
const hooksInstalled = areLearningHooksInstalled() || areCursorLearningHooksInstalled();
|
|
14746
14896
|
if (!hooksInstalled) {
|
|
14747
14897
|
console.log(chalk24.yellow(" Learning hooks not installed."));
|
|
14748
|
-
console.log(
|
|
14749
|
-
|
|
14750
|
-
|
|
14898
|
+
console.log(
|
|
14899
|
+
chalk24.dim(" Session learning captures patterns from your AI coding sessions \u2014 what")
|
|
14900
|
+
);
|
|
14901
|
+
console.log(
|
|
14902
|
+
chalk24.dim(" fails, what works, corrections you make \u2014 so your agents improve over time.\n")
|
|
14903
|
+
);
|
|
14904
|
+
console.log(
|
|
14905
|
+
chalk24.dim(" Run ") + chalk24.cyan(`${displayCaliberName()} learn install`) + chalk24.dim(" to enable.")
|
|
14906
|
+
);
|
|
14751
14907
|
} else {
|
|
14752
14908
|
console.log(chalk24.dim(" Learning hooks are active. Use your AI agent and insights"));
|
|
14753
14909
|
console.log(chalk24.dim(" will appear automatically after each session.\n"));
|
|
14754
|
-
console.log(
|
|
14910
|
+
console.log(
|
|
14911
|
+
chalk24.dim(
|
|
14912
|
+
` Progress: 0/${MIN_SESSIONS_FULL} sessions \u2014 full insights unlock at ${MIN_SESSIONS_FULL}`
|
|
14913
|
+
)
|
|
14914
|
+
);
|
|
14755
14915
|
}
|
|
14756
14916
|
console.log(chalk24.dim(`
|
|
14757
14917
|
Config score: ${score.score}/100 (${score.grade})`));
|
|
@@ -14760,20 +14920,32 @@ function displayColdStart(score) {
|
|
|
14760
14920
|
function displayEarlyData(data, score) {
|
|
14761
14921
|
console.log(chalk24.bold("\n Agent Insights") + chalk24.yellow(" (early data)\n"));
|
|
14762
14922
|
const remaining = MIN_SESSIONS_FULL - data.totalSessions;
|
|
14763
|
-
console.log(
|
|
14764
|
-
|
|
14923
|
+
console.log(
|
|
14924
|
+
chalk24.dim(
|
|
14925
|
+
` ${data.totalSessions}/${MIN_SESSIONS_FULL} sessions tracked \u2014 ${remaining} more for full insights.
|
|
14926
|
+
`
|
|
14927
|
+
)
|
|
14928
|
+
);
|
|
14765
14929
|
console.log(` Sessions tracked: ${chalk24.cyan(String(data.totalSessions))}`);
|
|
14766
14930
|
console.log(` Learnings accumulated: ${chalk24.cyan(String(data.learningCount))}`);
|
|
14767
14931
|
if (data.totalWasteTokens > 0) {
|
|
14768
|
-
console.log(
|
|
14932
|
+
console.log(
|
|
14933
|
+
` Waste captured: ${chalk24.cyan(data.totalWasteTokens.toLocaleString())} tokens`
|
|
14934
|
+
);
|
|
14769
14935
|
}
|
|
14770
14936
|
if (data.failureRateImprovement !== null && data.failureRateImprovement > 0) {
|
|
14771
|
-
console.log(
|
|
14937
|
+
console.log(
|
|
14938
|
+
` Failure rate trend: ${chalk24.green(`${data.failureRateImprovement}% fewer`)} failures with learnings ${chalk24.dim("(early signal)")}`
|
|
14939
|
+
);
|
|
14772
14940
|
} else if (data.totalSessions > 0 && data.failureRateImprovement === null) {
|
|
14773
|
-
console.log(
|
|
14941
|
+
console.log(
|
|
14942
|
+
` Failure rate trend: ${chalk24.dim("collecting data (need 3+ sessions in each group)")}`
|
|
14943
|
+
);
|
|
14774
14944
|
}
|
|
14775
14945
|
if (data.taskSuccessRate !== null) {
|
|
14776
|
-
console.log(
|
|
14946
|
+
console.log(
|
|
14947
|
+
` Task success rate: ${chalk24.cyan(`${data.taskSuccessRate}%`)} ${chalk24.dim(`(${data.taskCount} tasks)`)}`
|
|
14948
|
+
);
|
|
14777
14949
|
}
|
|
14778
14950
|
console.log(` Config score: ${chalk24.cyan(`${score.score}/100`)} (${score.grade})`);
|
|
14779
14951
|
console.log("");
|
|
@@ -14783,32 +14955,48 @@ function displayFullInsights(data, score) {
|
|
|
14783
14955
|
console.log(chalk24.bold(" Agent Health"));
|
|
14784
14956
|
if (data.taskSuccessRate !== null) {
|
|
14785
14957
|
const color = data.taskSuccessRate >= 80 ? chalk24.green : data.taskSuccessRate >= 60 ? chalk24.yellow : chalk24.red;
|
|
14786
|
-
console.log(
|
|
14958
|
+
console.log(
|
|
14959
|
+
` Task success rate: ${color(`${data.taskSuccessRate}%`)} across ${data.taskCount} tasks`
|
|
14960
|
+
);
|
|
14787
14961
|
if (data.taskCorrectionCount > 0) {
|
|
14788
|
-
console.log(
|
|
14962
|
+
console.log(
|
|
14963
|
+
` Corrections needed: ${chalk24.yellow(String(data.taskCorrectionCount))} tasks required user correction`
|
|
14964
|
+
);
|
|
14789
14965
|
}
|
|
14790
14966
|
}
|
|
14791
14967
|
console.log(` Sessions tracked: ${chalk24.cyan(String(data.totalSessions))}`);
|
|
14792
14968
|
console.log(chalk24.bold("\n Learning Impact"));
|
|
14793
14969
|
console.log(` Learnings active: ${chalk24.cyan(String(data.learningCount))}`);
|
|
14794
14970
|
if (data.failureRateWith !== null && data.failureRateWithout !== null) {
|
|
14795
|
-
console.log(
|
|
14971
|
+
console.log(
|
|
14972
|
+
` Failure rate: ${chalk24.red(data.failureRateWithout.toFixed(1))}/session ${chalk24.dim("\u2192")} ${chalk24.green(data.failureRateWith.toFixed(1))}/session with learnings`
|
|
14973
|
+
);
|
|
14796
14974
|
if (data.failureRateImprovement !== null && data.failureRateImprovement > 0) {
|
|
14797
|
-
console.log(
|
|
14975
|
+
console.log(
|
|
14976
|
+
` Improvement: ${chalk24.green(`${data.failureRateImprovement}%`)} fewer failures`
|
|
14977
|
+
);
|
|
14798
14978
|
} else if (data.failureRateImprovement === null) {
|
|
14799
|
-
console.log(
|
|
14979
|
+
console.log(
|
|
14980
|
+
` Improvement: ${chalk24.dim("collecting data (need 3+ sessions in each group)")}`
|
|
14981
|
+
);
|
|
14800
14982
|
}
|
|
14801
14983
|
}
|
|
14802
14984
|
if (data.totalWasteTokens > 0 || data.estimatedSavingsTokens > 0) {
|
|
14803
14985
|
console.log(chalk24.bold("\n Efficiency"));
|
|
14804
14986
|
if (data.totalWasteTokens > 0) {
|
|
14805
|
-
console.log(
|
|
14987
|
+
console.log(
|
|
14988
|
+
` Waste captured: ${chalk24.cyan(data.totalWasteTokens.toLocaleString())} tokens`
|
|
14989
|
+
);
|
|
14806
14990
|
}
|
|
14807
14991
|
if (data.estimatedSavingsTokens > 0) {
|
|
14808
|
-
console.log(
|
|
14992
|
+
console.log(
|
|
14993
|
+
` Estimated savings: ~${chalk24.green(data.estimatedSavingsTokens.toLocaleString())} tokens`
|
|
14994
|
+
);
|
|
14809
14995
|
}
|
|
14810
14996
|
if (data.estimatedSavingsSeconds > 0) {
|
|
14811
|
-
console.log(
|
|
14997
|
+
console.log(
|
|
14998
|
+
` Time saved: ~${chalk24.green(formatDuration(data.estimatedSavingsSeconds))}`
|
|
14999
|
+
);
|
|
14812
15000
|
}
|
|
14813
15001
|
}
|
|
14814
15002
|
console.log(chalk24.bold("\n Config Quality"));
|
|
@@ -14819,7 +15007,9 @@ function displayFullInsights(data, score) {
|
|
|
14819
15007
|
const trendColor = trend.direction === "up" ? chalk24.green : trend.direction === "down" ? chalk24.red : chalk24.gray;
|
|
14820
15008
|
const arrow = trend.direction === "up" ? "\u2191" : trend.direction === "down" ? "\u2193" : "\u2192";
|
|
14821
15009
|
const sign = trend.delta > 0 ? "+" : "";
|
|
14822
|
-
console.log(
|
|
15010
|
+
console.log(
|
|
15011
|
+
` Trend: ${trendColor(`${arrow} ${sign}${trend.delta} pts`)} ${chalk24.dim(`over ${trend.entries} checks`)}`
|
|
15012
|
+
);
|
|
14823
15013
|
}
|
|
14824
15014
|
console.log("");
|
|
14825
15015
|
}
|
|
@@ -14829,12 +15019,18 @@ async function insightsCommand(options) {
|
|
|
14829
15019
|
const score = computeLocalScore(process.cwd(), readState()?.targetAgent);
|
|
14830
15020
|
trackInsightsViewed(data.totalSessions, data.learningCount);
|
|
14831
15021
|
if (options.json) {
|
|
14832
|
-
console.log(
|
|
14833
|
-
|
|
14834
|
-
|
|
14835
|
-
|
|
14836
|
-
|
|
14837
|
-
|
|
15022
|
+
console.log(
|
|
15023
|
+
JSON.stringify(
|
|
15024
|
+
{
|
|
15025
|
+
...data,
|
|
15026
|
+
tier: data.totalSessions === 0 ? "cold-start" : data.totalSessions < MIN_SESSIONS_FULL ? "early" : "full",
|
|
15027
|
+
configScore: score.score,
|
|
15028
|
+
configGrade: score.grade
|
|
15029
|
+
},
|
|
15030
|
+
null,
|
|
15031
|
+
2
|
|
15032
|
+
)
|
|
15033
|
+
);
|
|
14838
15034
|
return;
|
|
14839
15035
|
}
|
|
14840
15036
|
if (data.totalSessions === 0) {
|
|
@@ -14857,7 +15053,9 @@ async function sourcesListCommand() {
|
|
|
14857
15053
|
const workspaces = getDetectedWorkspaces(dir);
|
|
14858
15054
|
if (configSources.length === 0 && workspaces.length === 0) {
|
|
14859
15055
|
console.log(chalk25.dim("\n No sources configured.\n"));
|
|
14860
|
-
console.log(
|
|
15056
|
+
console.log(
|
|
15057
|
+
chalk25.dim(" Add a source: ") + chalk25.hex("#83D1EB")(`${displayCaliberName()} sources add <path>`)
|
|
15058
|
+
);
|
|
14861
15059
|
console.log(chalk25.dim(" Or add to .caliber/sources.json manually.\n"));
|
|
14862
15060
|
return;
|
|
14863
15061
|
}
|
|
@@ -14869,7 +15067,9 @@ async function sourcesListCommand() {
|
|
|
14869
15067
|
const status = exists ? chalk25.green("reachable") : chalk25.red("not found");
|
|
14870
15068
|
const hasSummary = source.path && fs49.existsSync(path40.join(path40.resolve(dir, source.path), ".caliber", "summary.json"));
|
|
14871
15069
|
console.log(` ${chalk25.bold(source.role || source.type)} ${chalk25.dim(sourcePath)}`);
|
|
14872
|
-
console.log(
|
|
15070
|
+
console.log(
|
|
15071
|
+
` Type: ${source.type} Status: ${status}${hasSummary ? " " + chalk25.cyan("has summary.json") : ""}`
|
|
15072
|
+
);
|
|
14873
15073
|
if (source.description) console.log(` ${chalk25.dim(source.description)}`);
|
|
14874
15074
|
console.log("");
|
|
14875
15075
|
}
|
|
@@ -14900,9 +15100,7 @@ async function sourcesAddCommand(sourcePath) {
|
|
|
14900
15100
|
throw new Error("__exit__");
|
|
14901
15101
|
}
|
|
14902
15102
|
const existing = loadSourcesConfig(dir);
|
|
14903
|
-
const alreadyConfigured = existing.some(
|
|
14904
|
-
(s) => s.path && path40.resolve(dir, s.path) === absPath
|
|
14905
|
-
);
|
|
15103
|
+
const alreadyConfigured = existing.some((s) => s.path && path40.resolve(dir, s.path) === absPath);
|
|
14906
15104
|
if (alreadyConfigured) {
|
|
14907
15105
|
console.log(chalk25.yellow(`
|
|
14908
15106
|
Already configured: ${sourcePath}
|
|
@@ -14928,9 +15126,7 @@ async function sourcesAddCommand(sourcePath) {
|
|
|
14928
15126
|
async function sourcesRemoveCommand(name) {
|
|
14929
15127
|
const dir = process.cwd();
|
|
14930
15128
|
const existing = loadSourcesConfig(dir);
|
|
14931
|
-
const idx = existing.findIndex(
|
|
14932
|
-
(s) => s.path?.includes(name) || s.role === name
|
|
14933
|
-
);
|
|
15129
|
+
const idx = existing.findIndex((s) => s.path?.includes(name) || s.role === name);
|
|
14934
15130
|
if (idx === -1) {
|
|
14935
15131
|
console.log(chalk25.red(`
|
|
14936
15132
|
Source not found: ${name}
|
|
@@ -14943,9 +15139,11 @@ async function sourcesRemoveCommand(name) {
|
|
|
14943
15139
|
}
|
|
14944
15140
|
const removed = existing.splice(idx, 1)[0];
|
|
14945
15141
|
writeSourcesConfig(dir, existing);
|
|
14946
|
-
console.log(
|
|
15142
|
+
console.log(
|
|
15143
|
+
chalk25.green(`
|
|
14947
15144
|
\u2713 Removed ${removed.path || removed.url} (${removed.role || removed.type})
|
|
14948
|
-
`)
|
|
15145
|
+
`)
|
|
15146
|
+
);
|
|
14949
15147
|
}
|
|
14950
15148
|
|
|
14951
15149
|
// src/commands/publish.ts
|
|
@@ -14959,7 +15157,9 @@ async function publishCommand() {
|
|
|
14959
15157
|
const dir = process.cwd();
|
|
14960
15158
|
const config = loadConfig();
|
|
14961
15159
|
if (!config) {
|
|
14962
|
-
console.log(
|
|
15160
|
+
console.log(
|
|
15161
|
+
chalk26.red("No LLM provider configured. Run ") + chalk26.hex("#83D1EB")(`${displayCaliberName()} config`) + chalk26.red(" first.")
|
|
15162
|
+
);
|
|
14963
15163
|
throw new Error("__exit__");
|
|
14964
15164
|
}
|
|
14965
15165
|
const spinner = ora7("Generating project summary...").start();
|
|
@@ -15002,7 +15202,9 @@ async function publishCommand() {
|
|
|
15002
15202
|
spinner.succeed("Project summary published");
|
|
15003
15203
|
console.log(` ${chalk26.green("\u2713")} ${path41.relative(dir, outputPath)}`);
|
|
15004
15204
|
console.log(chalk26.dim("\n Other projects can now reference this repo as a source."));
|
|
15005
|
-
console.log(
|
|
15205
|
+
console.log(
|
|
15206
|
+
chalk26.dim(" When they run `caliber init`, they'll read this summary automatically.\n")
|
|
15207
|
+
);
|
|
15006
15208
|
} catch (err) {
|
|
15007
15209
|
spinner.fail("Failed to generate summary");
|
|
15008
15210
|
if (err instanceof Error && err.message === "__exit__") throw err;
|
package/package.json
CHANGED