@caliber-ai/cli 0.7.0 → 0.8.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 CHANGED
@@ -75,8 +75,8 @@ if (dsn) {
75
75
 
76
76
  // src/cli.ts
77
77
  import { Command } from "commander";
78
- import fs19 from "fs";
79
- import path16 from "path";
78
+ import fs20 from "fs";
79
+ import path17 from "path";
80
80
  import { fileURLToPath as fileURLToPath3 } from "url";
81
81
 
82
82
  // src/commands/init.ts
@@ -935,9 +935,9 @@ async function getValidToken() {
935
935
  }
936
936
  return refreshed;
937
937
  }
938
- async function apiRequest(path18, options = {}) {
938
+ async function apiRequest(path19, options = {}) {
939
939
  let token = await getValidToken();
940
- let resp = await fetch(`${API_URL}${path18}`, {
940
+ let resp = await fetch(`${API_URL}${path19}`, {
941
941
  method: options.method || "GET",
942
942
  headers: {
943
943
  "Content-Type": "application/json",
@@ -951,7 +951,7 @@ async function apiRequest(path18, options = {}) {
951
951
  throw new Error("Session expired. Run `caliber login` to re-authenticate.");
952
952
  }
953
953
  token = refreshed;
954
- resp = await fetch(`${API_URL}${path18}`, {
954
+ resp = await fetch(`${API_URL}${path19}`, {
955
955
  method: options.method || "GET",
956
956
  headers: {
957
957
  "Content-Type": "application/json",
@@ -967,9 +967,9 @@ async function apiRequest(path18, options = {}) {
967
967
  const json = await resp.json();
968
968
  return json.data;
969
969
  }
970
- async function apiStream(path18, body, onChunk, onComplete, onError, onStatus) {
970
+ async function apiStream(path19, body, onChunk, onComplete, onError, onStatus) {
971
971
  let token = await getValidToken();
972
- let resp = await fetch(`${API_URL}${path18}`, {
972
+ let resp = await fetch(`${API_URL}${path19}`, {
973
973
  method: "POST",
974
974
  headers: {
975
975
  "Content-Type": "application/json",
@@ -983,7 +983,7 @@ async function apiStream(path18, body, onChunk, onComplete, onError, onStatus) {
983
983
  throw new Error("Session expired. Run `caliber login` to re-authenticate.");
984
984
  }
985
985
  token = refreshed;
986
- resp = await fetch(`${API_URL}${path18}`, {
986
+ resp = await fetch(`${API_URL}${path19}`, {
987
987
  method: "POST",
988
988
  headers: {
989
989
  "Content-Type": "application/json",
@@ -2544,6 +2544,8 @@ async function diffCommand(options) {
2544
2544
  }
2545
2545
 
2546
2546
  // src/commands/refresh.ts
2547
+ import fs19 from "fs";
2548
+ import path16 from "path";
2547
2549
  import chalk11 from "chalk";
2548
2550
  import ora9 from "ora";
2549
2551
 
@@ -2661,6 +2663,92 @@ function writeRefreshDocs(docs) {
2661
2663
  function log(quiet, ...args) {
2662
2664
  if (!quiet) console.log(...args);
2663
2665
  }
2666
+ function discoverGitRepos(parentDir) {
2667
+ const repos = [];
2668
+ try {
2669
+ const entries = fs19.readdirSync(parentDir, { withFileTypes: true });
2670
+ for (const entry of entries) {
2671
+ if (!entry.isDirectory() || entry.name.startsWith(".")) continue;
2672
+ const childPath = path16.join(parentDir, entry.name);
2673
+ if (fs19.existsSync(path16.join(childPath, ".git"))) {
2674
+ repos.push(childPath);
2675
+ }
2676
+ }
2677
+ } catch {
2678
+ }
2679
+ return repos.sort();
2680
+ }
2681
+ async function refreshSingleRepo(repoDir, options) {
2682
+ const quiet = !!options.quiet;
2683
+ const prefix = options.label ? `${chalk11.bold(options.label)} ` : "";
2684
+ const state = readState();
2685
+ const lastSha = state?.lastRefreshSha ?? null;
2686
+ const diff = collectDiff(lastSha);
2687
+ const currentSha = getCurrentHeadSha();
2688
+ if (!diff.hasChanges) {
2689
+ if (currentSha) {
2690
+ writeState({ lastRefreshSha: currentSha, lastRefreshTimestamp: (/* @__PURE__ */ new Date()).toISOString() });
2691
+ }
2692
+ log(quiet, chalk11.dim(`${prefix}No changes since last refresh.`));
2693
+ return;
2694
+ }
2695
+ const spinner = quiet ? null : ora9(`${prefix}Analyzing changes...`).start();
2696
+ const existingDocs = readExistingConfigs(repoDir);
2697
+ const fingerprint = collectFingerprint(repoDir);
2698
+ const projectContext = {
2699
+ languages: fingerprint.languages,
2700
+ frameworks: fingerprint.frameworks,
2701
+ packageName: fingerprint.packageName
2702
+ };
2703
+ const response = await apiRequest("/api/setups/refresh", {
2704
+ method: "POST",
2705
+ body: {
2706
+ diff: {
2707
+ committed: diff.committedDiff,
2708
+ staged: diff.stagedDiff,
2709
+ unstaged: diff.unstagedDiff,
2710
+ changedFiles: diff.changedFiles,
2711
+ summary: diff.summary
2712
+ },
2713
+ existingDocs,
2714
+ projectContext
2715
+ }
2716
+ });
2717
+ if (!response.docsUpdated || response.docsUpdated.length === 0) {
2718
+ spinner?.succeed(`${prefix}No doc updates needed`);
2719
+ if (currentSha) {
2720
+ writeState({ lastRefreshSha: currentSha, lastRefreshTimestamp: (/* @__PURE__ */ new Date()).toISOString() });
2721
+ }
2722
+ return;
2723
+ }
2724
+ if (options.dryRun) {
2725
+ spinner?.info(`${prefix}Dry run \u2014 would update:`);
2726
+ for (const doc of response.docsUpdated) {
2727
+ console.log(` ${chalk11.yellow("~")} ${doc}`);
2728
+ }
2729
+ if (response.changesSummary) {
2730
+ console.log(chalk11.dim(`
2731
+ ${response.changesSummary}`));
2732
+ }
2733
+ return;
2734
+ }
2735
+ const written = writeRefreshDocs(response.updatedDocs);
2736
+ spinner?.succeed(`${prefix}Updated ${written.length} doc${written.length === 1 ? "" : "s"}`);
2737
+ for (const file of written) {
2738
+ log(quiet, ` ${chalk11.green("\u2713")} ${file}`);
2739
+ }
2740
+ if (response.changesSummary) {
2741
+ log(quiet, chalk11.dim(`
2742
+ ${response.changesSummary}`));
2743
+ }
2744
+ if (currentSha) {
2745
+ writeState({ lastRefreshSha: currentSha, lastRefreshTimestamp: (/* @__PURE__ */ new Date()).toISOString() });
2746
+ }
2747
+ trackEvent("refresh_completed", {
2748
+ docs_updated: written.length,
2749
+ changed_files: diff.changedFiles.length
2750
+ });
2751
+ }
2664
2752
  async function refreshCommand(options) {
2665
2753
  const quiet = !!options.quiet;
2666
2754
  try {
@@ -2670,78 +2758,30 @@ async function refreshCommand(options) {
2670
2758
  console.log(chalk11.red("Not authenticated. Run `caliber login` first."));
2671
2759
  throw new Error("__exit__");
2672
2760
  }
2673
- if (!isGitRepo()) {
2674
- if (quiet) return;
2675
- console.log(chalk11.red("Not inside a git repository."));
2676
- throw new Error("__exit__");
2677
- }
2678
- const state = readState();
2679
- const lastSha = state?.lastRefreshSha ?? null;
2680
- const diff = collectDiff(lastSha);
2681
- const currentSha = getCurrentHeadSha();
2682
- if (!diff.hasChanges) {
2683
- if (currentSha) {
2684
- writeState({ lastRefreshSha: currentSha, lastRefreshTimestamp: (/* @__PURE__ */ new Date()).toISOString() });
2685
- }
2686
- log(quiet, chalk11.dim("No changes since last refresh."));
2761
+ if (isGitRepo()) {
2762
+ await refreshSingleRepo(process.cwd(), options);
2687
2763
  return;
2688
2764
  }
2689
- const spinner = quiet ? null : ora9("Analyzing changes...").start();
2690
- const existingDocs = readExistingConfigs(process.cwd());
2691
- const fingerprint = collectFingerprint(process.cwd());
2692
- const projectContext = {
2693
- languages: fingerprint.languages,
2694
- frameworks: fingerprint.frameworks,
2695
- packageName: fingerprint.packageName
2696
- };
2697
- const response = await apiRequest("/api/setups/refresh", {
2698
- method: "POST",
2699
- body: {
2700
- diff: {
2701
- committed: diff.committedDiff,
2702
- staged: diff.stagedDiff,
2703
- unstaged: diff.unstagedDiff,
2704
- changedFiles: diff.changedFiles,
2705
- summary: diff.summary
2706
- },
2707
- existingDocs,
2708
- projectContext
2709
- }
2710
- });
2711
- if (!response.docsUpdated || response.docsUpdated.length === 0) {
2712
- spinner?.succeed("No doc updates needed");
2713
- if (currentSha) {
2714
- writeState({ lastRefreshSha: currentSha, lastRefreshTimestamp: (/* @__PURE__ */ new Date()).toISOString() });
2715
- }
2716
- return;
2765
+ const repos = discoverGitRepos(process.cwd());
2766
+ if (repos.length === 0) {
2767
+ if (quiet) return;
2768
+ console.log(chalk11.red("Not inside a git repository and no git repos found in child directories."));
2769
+ throw new Error("__exit__");
2717
2770
  }
2718
- if (options.dryRun) {
2719
- spinner?.info("Dry run \u2014 would update:");
2720
- for (const doc of response.docsUpdated) {
2721
- console.log(` ${chalk11.yellow("~")} ${doc}`);
2722
- }
2723
- if (response.changesSummary) {
2724
- console.log(chalk11.dim(`
2725
- ${response.changesSummary}`));
2771
+ log(quiet, chalk11.dim(`Found ${repos.length} git repo${repos.length === 1 ? "" : "s"}
2772
+ `));
2773
+ const originalDir = process.cwd();
2774
+ for (const repo of repos) {
2775
+ const repoName = path16.basename(repo);
2776
+ try {
2777
+ process.chdir(repo);
2778
+ await refreshSingleRepo(repo, { ...options, label: repoName });
2779
+ } catch (err) {
2780
+ if (err instanceof Error && err.message === "__exit__") continue;
2781
+ log(quiet, chalk11.yellow(`${repoName}: refresh failed \u2014 ${err instanceof Error ? err.message : "unknown error"}`));
2726
2782
  }
2727
- return;
2728
2783
  }
2729
- const written = writeRefreshDocs(response.updatedDocs);
2730
- spinner?.succeed(`Updated ${written.length} doc${written.length === 1 ? "" : "s"}`);
2731
- for (const file of written) {
2732
- log(quiet, ` ${chalk11.green("\u2713")} ${file}`);
2733
- }
2734
- if (response.changesSummary) {
2735
- log(quiet, chalk11.dim(`
2736
- ${response.changesSummary}`));
2737
- }
2738
- if (currentSha) {
2739
- writeState({ lastRefreshSha: currentSha, lastRefreshTimestamp: (/* @__PURE__ */ new Date()).toISOString() });
2740
- }
2741
- trackEvent("refresh_completed", {
2742
- docs_updated: written.length,
2743
- changed_files: diff.changedFiles.length
2744
- });
2784
+ process.chdir(originalDir);
2745
2785
  } catch (err) {
2746
2786
  if (err instanceof Error && err.message === "__exit__") throw err;
2747
2787
  if (quiet) return;
@@ -2781,9 +2821,9 @@ async function hooksStatusCommand() {
2781
2821
  }
2782
2822
 
2783
2823
  // src/cli.ts
2784
- var __dirname2 = path16.dirname(fileURLToPath3(import.meta.url));
2824
+ var __dirname2 = path17.dirname(fileURLToPath3(import.meta.url));
2785
2825
  var pkg3 = JSON.parse(
2786
- fs19.readFileSync(path16.resolve(__dirname2, "..", "package.json"), "utf-8")
2826
+ fs20.readFileSync(path17.resolve(__dirname2, "..", "package.json"), "utf-8")
2787
2827
  );
2788
2828
  var program = new Command();
2789
2829
  program.name("caliber").description("Configure your coding agent environment").version(pkg3.version);
@@ -2804,16 +2844,16 @@ hooks.command("remove").description("Remove auto-refresh SessionEnd hook").actio
2804
2844
  hooks.command("status").description("Check if auto-refresh hook is installed").action(hooksStatusCommand);
2805
2845
 
2806
2846
  // src/utils/version-check.ts
2807
- import fs20 from "fs";
2808
- import path17 from "path";
2847
+ import fs21 from "fs";
2848
+ import path18 from "path";
2809
2849
  import { fileURLToPath as fileURLToPath4 } from "url";
2810
2850
  import readline3 from "readline";
2811
2851
  import { execSync as execSync4 } from "child_process";
2812
2852
  import chalk13 from "chalk";
2813
2853
  import ora10 from "ora";
2814
- var __dirname_vc = path17.dirname(fileURLToPath4(import.meta.url));
2854
+ var __dirname_vc = path18.dirname(fileURLToPath4(import.meta.url));
2815
2855
  var pkg4 = JSON.parse(
2816
- fs20.readFileSync(path17.resolve(__dirname_vc, "..", "package.json"), "utf-8")
2856
+ fs21.readFileSync(path18.resolve(__dirname_vc, "..", "package.json"), "utf-8")
2817
2857
  );
2818
2858
  function promptYesNo(question) {
2819
2859
  const rl = readline3.createInterface({ input: process.stdin, output: process.stdout });