@rely-ai/caliber 1.12.7 → 1.12.9

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 +120 -64
  2. package/package.json +1 -1
package/dist/bin.js CHANGED
@@ -163,10 +163,57 @@ var init_constants = __esm({
163
163
  }
164
164
  });
165
165
 
166
+ // src/lib/lock.ts
167
+ var lock_exports = {};
168
+ __export(lock_exports, {
169
+ acquireLock: () => acquireLock,
170
+ isCaliberRunning: () => isCaliberRunning,
171
+ releaseLock: () => releaseLock
172
+ });
173
+ import fs27 from "fs";
174
+ import path21 from "path";
175
+ import os4 from "os";
176
+ function isCaliberRunning() {
177
+ try {
178
+ if (!fs27.existsSync(LOCK_FILE)) return false;
179
+ const raw = fs27.readFileSync(LOCK_FILE, "utf-8").trim();
180
+ const { pid, ts } = JSON.parse(raw);
181
+ if (Date.now() - ts > STALE_MS) return false;
182
+ try {
183
+ process.kill(pid, 0);
184
+ return true;
185
+ } catch {
186
+ return false;
187
+ }
188
+ } catch {
189
+ return false;
190
+ }
191
+ }
192
+ function acquireLock() {
193
+ try {
194
+ fs27.writeFileSync(LOCK_FILE, JSON.stringify({ pid: process.pid, ts: Date.now() }));
195
+ } catch {
196
+ }
197
+ }
198
+ function releaseLock() {
199
+ try {
200
+ if (fs27.existsSync(LOCK_FILE)) fs27.unlinkSync(LOCK_FILE);
201
+ } catch {
202
+ }
203
+ }
204
+ var LOCK_FILE, STALE_MS;
205
+ var init_lock = __esm({
206
+ "src/lib/lock.ts"() {
207
+ "use strict";
208
+ LOCK_FILE = path21.join(os4.tmpdir(), ".caliber.lock");
209
+ STALE_MS = 10 * 60 * 1e3;
210
+ }
211
+ });
212
+
166
213
  // src/cli.ts
167
214
  import { Command } from "commander";
168
- import fs30 from "fs";
169
- import path24 from "path";
215
+ import fs31 from "fs";
216
+ import path25 from "path";
170
217
  import { fileURLToPath } from "url";
171
218
 
172
219
  // src/commands/init.ts
@@ -1948,15 +1995,15 @@ init_config();
1948
1995
  // src/utils/dependencies.ts
1949
1996
  import { readFileSync } from "fs";
1950
1997
  import { join } from "path";
1951
- function readFileOrNull(path26) {
1998
+ function readFileOrNull(path27) {
1952
1999
  try {
1953
- return readFileSync(path26, "utf-8");
2000
+ return readFileSync(path27, "utf-8");
1954
2001
  } catch {
1955
2002
  return null;
1956
2003
  }
1957
2004
  }
1958
- function readJsonOrNull(path26) {
1959
- const content = readFileOrNull(path26);
2005
+ function readJsonOrNull(path27) {
2006
+ const content = readFileOrNull(path27);
1960
2007
  if (!content) return null;
1961
2008
  try {
1962
2009
  return JSON.parse(content);
@@ -3792,9 +3839,9 @@ function computeGrade(score) {
3792
3839
  // src/scoring/checks/coverage.ts
3793
3840
  import { readFileSync as readFileSync2, readdirSync } from "fs";
3794
3841
  import { join as join2 } from "path";
3795
- function readFileOrNull2(path26) {
3842
+ function readFileOrNull2(path27) {
3796
3843
  try {
3797
- return readFileSync2(path26, "utf-8");
3844
+ return readFileSync2(path27, "utf-8");
3798
3845
  } catch {
3799
3846
  return null;
3800
3847
  }
@@ -4095,9 +4142,9 @@ function checkExistence(dir) {
4095
4142
  // src/scoring/checks/quality.ts
4096
4143
  import { readFileSync as readFileSync4 } from "fs";
4097
4144
  import { join as join4 } from "path";
4098
- function readFileOrNull3(path26) {
4145
+ function readFileOrNull3(path27) {
4099
4146
  try {
4100
- return readFileSync4(path26, "utf-8");
4147
+ return readFileSync4(path27, "utf-8");
4101
4148
  } catch {
4102
4149
  return null;
4103
4150
  }
@@ -4250,15 +4297,15 @@ function checkQuality(dir) {
4250
4297
  // src/scoring/checks/accuracy.ts
4251
4298
  import { existsSync as existsSync5, readFileSync as readFileSync5, readdirSync as readdirSync3, statSync } from "fs";
4252
4299
  import { join as join5 } from "path";
4253
- function readFileOrNull4(path26) {
4300
+ function readFileOrNull4(path27) {
4254
4301
  try {
4255
- return readFileSync5(path26, "utf-8");
4302
+ return readFileSync5(path27, "utf-8");
4256
4303
  } catch {
4257
4304
  return null;
4258
4305
  }
4259
4306
  }
4260
- function readJsonOrNull2(path26) {
4261
- const content = readFileOrNull4(path26);
4307
+ function readJsonOrNull2(path27) {
4308
+ const content = readFileOrNull4(path27);
4262
4309
  if (!content) return null;
4263
4310
  try {
4264
4311
  return JSON.parse(content);
@@ -4442,9 +4489,9 @@ function checkAccuracy(dir) {
4442
4489
  // src/scoring/checks/freshness.ts
4443
4490
  import { existsSync as existsSync6, readFileSync as readFileSync6, statSync as statSync2 } from "fs";
4444
4491
  import { join as join6 } from "path";
4445
- function readFileOrNull5(path26) {
4492
+ function readFileOrNull5(path27) {
4446
4493
  try {
4447
- return readFileSync6(path26, "utf-8");
4494
+ return readFileSync6(path27, "utf-8");
4448
4495
  } catch {
4449
4496
  return null;
4450
4497
  }
@@ -4558,9 +4605,9 @@ function checkFreshness(dir) {
4558
4605
  import { existsSync as existsSync7, readFileSync as readFileSync7, readdirSync as readdirSync4 } from "fs";
4559
4606
  import { execSync as execSync8 } from "child_process";
4560
4607
  import { join as join7 } from "path";
4561
- function readFileOrNull6(path26) {
4608
+ function readFileOrNull6(path27) {
4562
4609
  try {
4563
- return readFileSync7(path26, "utf-8");
4610
+ return readFileSync7(path27, "utf-8");
4564
4611
  } catch {
4565
4612
  return null;
4566
4613
  }
@@ -6349,7 +6396,7 @@ async function refineLoop(currentSetup, _targetAgent, sessionHistory) {
6349
6396
  }
6350
6397
  function summarizeSetup(action, setup) {
6351
6398
  const descriptions = setup.fileDescriptions;
6352
- const files = descriptions ? Object.entries(descriptions).map(([path26, desc]) => ` ${path26}: ${desc}`).join("\n") : Object.keys(setup).filter((k) => k !== "targetAgent" && k !== "fileDescriptions").join(", ");
6399
+ const files = descriptions ? Object.entries(descriptions).map(([path27, desc]) => ` ${path27}: ${desc}`).join("\n") : Object.keys(setup).filter((k) => k !== "targetAgent" && k !== "fileDescriptions").join(", ");
6353
6400
  return `${action}. Files:
6354
6401
  ${files}`;
6355
6402
  }
@@ -6870,8 +6917,8 @@ async function scoreCommand(options) {
6870
6917
  }
6871
6918
 
6872
6919
  // src/commands/refresh.ts
6873
- import fs27 from "fs";
6874
- import path21 from "path";
6920
+ import fs28 from "fs";
6921
+ import path22 from "path";
6875
6922
  import chalk13 from "chalk";
6876
6923
  import ora5 from "ora";
6877
6924
 
@@ -7057,11 +7104,11 @@ function log2(quiet, ...args) {
7057
7104
  function discoverGitRepos(parentDir) {
7058
7105
  const repos = [];
7059
7106
  try {
7060
- const entries = fs27.readdirSync(parentDir, { withFileTypes: true });
7107
+ const entries = fs28.readdirSync(parentDir, { withFileTypes: true });
7061
7108
  for (const entry of entries) {
7062
7109
  if (!entry.isDirectory() || entry.name.startsWith(".")) continue;
7063
- const childPath = path21.join(parentDir, entry.name);
7064
- if (fs27.existsSync(path21.join(childPath, ".git"))) {
7110
+ const childPath = path22.join(parentDir, entry.name);
7111
+ if (fs28.existsSync(path22.join(childPath, ".git"))) {
7065
7112
  repos.push(childPath);
7066
7113
  }
7067
7114
  }
@@ -7136,6 +7183,10 @@ async function refreshSingleRepo(repoDir, options) {
7136
7183
  }
7137
7184
  async function refreshCommand(options) {
7138
7185
  const quiet = !!options.quiet;
7186
+ if (quiet) {
7187
+ const { isCaliberRunning: isCaliberRunning2 } = await Promise.resolve().then(() => (init_lock(), lock_exports));
7188
+ if (isCaliberRunning2()) return;
7189
+ }
7139
7190
  try {
7140
7191
  const config = loadConfig();
7141
7192
  if (!config) {
@@ -7158,7 +7209,7 @@ async function refreshCommand(options) {
7158
7209
  `));
7159
7210
  const originalDir = process.cwd();
7160
7211
  for (const repo of repos) {
7161
- const repoName = path21.basename(repo);
7212
+ const repoName = path22.basename(repo);
7162
7213
  try {
7163
7214
  process.chdir(repo);
7164
7215
  await refreshSingleRepo(repo, { ...options, label: repoName });
@@ -7413,8 +7464,8 @@ function readStdin() {
7413
7464
 
7414
7465
  // src/learner/storage.ts
7415
7466
  init_constants();
7416
- import fs28 from "fs";
7417
- import path22 from "path";
7467
+ import fs29 from "fs";
7468
+ import path23 from "path";
7418
7469
  var MAX_RESPONSE_LENGTH = 2e3;
7419
7470
  var DEFAULT_STATE = {
7420
7471
  sessionId: null,
@@ -7422,15 +7473,15 @@ var DEFAULT_STATE = {
7422
7473
  lastAnalysisTimestamp: null
7423
7474
  };
7424
7475
  function ensureLearningDir() {
7425
- if (!fs28.existsSync(LEARNING_DIR)) {
7426
- fs28.mkdirSync(LEARNING_DIR, { recursive: true });
7476
+ if (!fs29.existsSync(LEARNING_DIR)) {
7477
+ fs29.mkdirSync(LEARNING_DIR, { recursive: true });
7427
7478
  }
7428
7479
  }
7429
7480
  function sessionFilePath() {
7430
- return path22.join(LEARNING_DIR, LEARNING_SESSION_FILE);
7481
+ return path23.join(LEARNING_DIR, LEARNING_SESSION_FILE);
7431
7482
  }
7432
7483
  function stateFilePath() {
7433
- return path22.join(LEARNING_DIR, LEARNING_STATE_FILE);
7484
+ return path23.join(LEARNING_DIR, LEARNING_STATE_FILE);
7434
7485
  }
7435
7486
  function truncateResponse(response) {
7436
7487
  const str = JSON.stringify(response);
@@ -7441,50 +7492,50 @@ function appendEvent(event) {
7441
7492
  ensureLearningDir();
7442
7493
  const truncated = { ...event, tool_response: truncateResponse(event.tool_response) };
7443
7494
  const filePath = sessionFilePath();
7444
- fs28.appendFileSync(filePath, JSON.stringify(truncated) + "\n");
7495
+ fs29.appendFileSync(filePath, JSON.stringify(truncated) + "\n");
7445
7496
  const count = getEventCount();
7446
7497
  if (count > LEARNING_MAX_EVENTS) {
7447
- const lines = fs28.readFileSync(filePath, "utf-8").split("\n").filter(Boolean);
7498
+ const lines = fs29.readFileSync(filePath, "utf-8").split("\n").filter(Boolean);
7448
7499
  const kept = lines.slice(lines.length - LEARNING_MAX_EVENTS);
7449
- fs28.writeFileSync(filePath, kept.join("\n") + "\n");
7500
+ fs29.writeFileSync(filePath, kept.join("\n") + "\n");
7450
7501
  }
7451
7502
  }
7452
7503
  function readAllEvents() {
7453
7504
  const filePath = sessionFilePath();
7454
- if (!fs28.existsSync(filePath)) return [];
7455
- const lines = fs28.readFileSync(filePath, "utf-8").split("\n").filter(Boolean);
7505
+ if (!fs29.existsSync(filePath)) return [];
7506
+ const lines = fs29.readFileSync(filePath, "utf-8").split("\n").filter(Boolean);
7456
7507
  return lines.map((line) => JSON.parse(line));
7457
7508
  }
7458
7509
  function getEventCount() {
7459
7510
  const filePath = sessionFilePath();
7460
- if (!fs28.existsSync(filePath)) return 0;
7461
- const content = fs28.readFileSync(filePath, "utf-8");
7511
+ if (!fs29.existsSync(filePath)) return 0;
7512
+ const content = fs29.readFileSync(filePath, "utf-8");
7462
7513
  return content.split("\n").filter(Boolean).length;
7463
7514
  }
7464
7515
  function clearSession() {
7465
7516
  const filePath = sessionFilePath();
7466
- if (fs28.existsSync(filePath)) fs28.unlinkSync(filePath);
7517
+ if (fs29.existsSync(filePath)) fs29.unlinkSync(filePath);
7467
7518
  }
7468
7519
  function readState2() {
7469
7520
  const filePath = stateFilePath();
7470
- if (!fs28.existsSync(filePath)) return { ...DEFAULT_STATE };
7521
+ if (!fs29.existsSync(filePath)) return { ...DEFAULT_STATE };
7471
7522
  try {
7472
- return JSON.parse(fs28.readFileSync(filePath, "utf-8"));
7523
+ return JSON.parse(fs29.readFileSync(filePath, "utf-8"));
7473
7524
  } catch {
7474
7525
  return { ...DEFAULT_STATE };
7475
7526
  }
7476
7527
  }
7477
7528
  function writeState2(state) {
7478
7529
  ensureLearningDir();
7479
- fs28.writeFileSync(stateFilePath(), JSON.stringify(state, null, 2));
7530
+ fs29.writeFileSync(stateFilePath(), JSON.stringify(state, null, 2));
7480
7531
  }
7481
7532
  function resetState() {
7482
7533
  writeState2({ ...DEFAULT_STATE });
7483
7534
  }
7484
7535
 
7485
7536
  // src/learner/writer.ts
7486
- import fs29 from "fs";
7487
- import path23 from "path";
7537
+ import fs30 from "fs";
7538
+ import path24 from "path";
7488
7539
  var LEARNED_START = "<!-- caliber:learned -->";
7489
7540
  var LEARNED_END = "<!-- /caliber:learned -->";
7490
7541
  function writeLearnedContent(update) {
@@ -7504,8 +7555,8 @@ function writeLearnedContent(update) {
7504
7555
  function writeLearnedSection(content) {
7505
7556
  const claudeMdPath = "CLAUDE.md";
7506
7557
  let existing = "";
7507
- if (fs29.existsSync(claudeMdPath)) {
7508
- existing = fs29.readFileSync(claudeMdPath, "utf-8");
7558
+ if (fs30.existsSync(claudeMdPath)) {
7559
+ existing = fs30.readFileSync(claudeMdPath, "utf-8");
7509
7560
  }
7510
7561
  const section = `${LEARNED_START}
7511
7562
  ${content}
@@ -7519,15 +7570,15 @@ ${LEARNED_END}`;
7519
7570
  const separator = existing.endsWith("\n") || existing === "" ? "" : "\n";
7520
7571
  updated = existing + separator + "\n" + section + "\n";
7521
7572
  }
7522
- fs29.writeFileSync(claudeMdPath, updated);
7573
+ fs30.writeFileSync(claudeMdPath, updated);
7523
7574
  }
7524
7575
  function writeLearnedSkill(skill) {
7525
- const skillDir = path23.join(".claude", "skills", skill.name);
7526
- if (!fs29.existsSync(skillDir)) fs29.mkdirSync(skillDir, { recursive: true });
7527
- const skillPath = path23.join(skillDir, "SKILL.md");
7528
- if (!skill.isNew && fs29.existsSync(skillPath)) {
7529
- const existing = fs29.readFileSync(skillPath, "utf-8");
7530
- fs29.writeFileSync(skillPath, existing.trimEnd() + "\n\n" + skill.content);
7576
+ const skillDir = path24.join(".claude", "skills", skill.name);
7577
+ if (!fs30.existsSync(skillDir)) fs30.mkdirSync(skillDir, { recursive: true });
7578
+ const skillPath = path24.join(skillDir, "SKILL.md");
7579
+ if (!skill.isNew && fs30.existsSync(skillPath)) {
7580
+ const existing = fs30.readFileSync(skillPath, "utf-8");
7581
+ fs30.writeFileSync(skillPath, existing.trimEnd() + "\n\n" + skill.content);
7531
7582
  } else {
7532
7583
  const frontmatter = [
7533
7584
  "---",
@@ -7536,14 +7587,14 @@ function writeLearnedSkill(skill) {
7536
7587
  "---",
7537
7588
  ""
7538
7589
  ].join("\n");
7539
- fs29.writeFileSync(skillPath, frontmatter + skill.content);
7590
+ fs30.writeFileSync(skillPath, frontmatter + skill.content);
7540
7591
  }
7541
7592
  return skillPath;
7542
7593
  }
7543
7594
  function readLearnedSection() {
7544
7595
  const claudeMdPath = "CLAUDE.md";
7545
- if (!fs29.existsSync(claudeMdPath)) return null;
7546
- const content = fs29.readFileSync(claudeMdPath, "utf-8");
7596
+ if (!fs30.existsSync(claudeMdPath)) return null;
7597
+ const content = fs30.readFileSync(claudeMdPath, "utf-8");
7547
7598
  const startIdx = content.indexOf(LEARNED_START);
7548
7599
  const endIdx = content.indexOf(LEARNED_END);
7549
7600
  if (startIdx === -1 || endIdx === -1) return null;
@@ -7650,6 +7701,8 @@ async function learnObserveCommand(options) {
7650
7701
  }
7651
7702
  }
7652
7703
  async function learnFinalizeCommand() {
7704
+ const { isCaliberRunning: isCaliberRunning2 } = await Promise.resolve().then(() => (init_lock(), lock_exports));
7705
+ if (isCaliberRunning2()) return;
7653
7706
  try {
7654
7707
  const config = loadConfig();
7655
7708
  if (!config) {
@@ -7732,9 +7785,9 @@ Learned items in CLAUDE.md: ${chalk16.cyan(String(lineCount))}`);
7732
7785
  }
7733
7786
 
7734
7787
  // src/cli.ts
7735
- var __dirname = path24.dirname(fileURLToPath(import.meta.url));
7788
+ var __dirname = path25.dirname(fileURLToPath(import.meta.url));
7736
7789
  var pkg = JSON.parse(
7737
- fs30.readFileSync(path24.resolve(__dirname, "..", "package.json"), "utf-8")
7790
+ fs31.readFileSync(path25.resolve(__dirname, "..", "package.json"), "utf-8")
7738
7791
  );
7739
7792
  var program = new Command();
7740
7793
  var displayVersion = process.env.CALIBER_LOCAL ? `${pkg.version}-local` : pkg.version;
@@ -7808,22 +7861,22 @@ learn.command("remove").description("Remove learning hooks from .claude/settings
7808
7861
  learn.command("status").description("Show learning system status").action(tracked("learn:status", learnStatusCommand));
7809
7862
 
7810
7863
  // src/utils/version-check.ts
7811
- import fs31 from "fs";
7812
- import path25 from "path";
7864
+ import fs32 from "fs";
7865
+ import path26 from "path";
7813
7866
  import { fileURLToPath as fileURLToPath2 } from "url";
7814
7867
  import { execSync as execSync11 } from "child_process";
7815
7868
  import chalk17 from "chalk";
7816
7869
  import ora6 from "ora";
7817
7870
  import confirm from "@inquirer/confirm";
7818
- var __dirname_vc = path25.dirname(fileURLToPath2(import.meta.url));
7871
+ var __dirname_vc = path26.dirname(fileURLToPath2(import.meta.url));
7819
7872
  var pkg2 = JSON.parse(
7820
- fs31.readFileSync(path25.resolve(__dirname_vc, "..", "package.json"), "utf-8")
7873
+ fs32.readFileSync(path26.resolve(__dirname_vc, "..", "package.json"), "utf-8")
7821
7874
  );
7822
7875
  function getInstalledVersion() {
7823
7876
  try {
7824
7877
  const globalRoot = execSync11("npm root -g", { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
7825
- const pkgPath = path25.join(globalRoot, "@rely-ai", "caliber", "package.json");
7826
- return JSON.parse(fs31.readFileSync(pkgPath, "utf-8")).version;
7878
+ const pkgPath = path26.join(globalRoot, "@rely-ai", "caliber", "package.json");
7879
+ return JSON.parse(fs32.readFileSync(pkgPath, "utf-8")).version;
7827
7880
  } catch {
7828
7881
  return null;
7829
7882
  }
@@ -7907,6 +7960,8 @@ Restarting: caliber ${args.join(" ")}
7907
7960
  }
7908
7961
 
7909
7962
  // src/bin.ts
7963
+ init_lock();
7964
+ acquireLock();
7910
7965
  if (process.env.CALIBER_LOCAL) {
7911
7966
  process.env.CALIBER_SKIP_UPDATE_CHECK = "1";
7912
7967
  }
@@ -7918,6 +7973,7 @@ program.parseAsync().catch((err) => {
7918
7973
  }
7919
7974
  process.exitCode = 1;
7920
7975
  }).finally(async () => {
7976
+ releaseLock();
7921
7977
  await flushTelemetry();
7922
7978
  process.exit(Number(process.exitCode ?? 0));
7923
7979
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rely-ai/caliber",
3
- "version": "1.12.7",
3
+ "version": "1.12.9",
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": {