@4pm/cli 1.7.0 → 1.8.4

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/index.js +34 -19
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -29667,7 +29667,7 @@ async function checkAndUpdate(serverUrl, autoUpdate) {
29667
29667
  init_wrapper();
29668
29668
  import { randomUUID as randomUUID2 } from "crypto";
29669
29669
  import { basename as basename7, join as join28 } from "path";
29670
- import { existsSync as existsSync15, mkdirSync as mkdirSync7 } from "fs";
29670
+ import { existsSync as existsSync16, mkdirSync as mkdirSync7 } from "fs";
29671
29671
 
29672
29672
  // vendor/@4pm/utils/helpers.ts
29673
29673
  function backoffJitterMs(attempt, baseMs = 500, maxMs = 1e4) {
@@ -38638,7 +38638,7 @@ function handleMiscChannels(ctx, message, payload) {
38638
38638
  }
38639
38639
 
38640
38640
  // src/core/ws-client/handlers/project.ts
38641
- import { mkdirSync as mkdirSync6, rmSync as rmSync6 } from "fs";
38641
+ import { existsSync as existsSync13, mkdirSync as mkdirSync6, renameSync, rmSync as rmSync6 } from "fs";
38642
38642
  import { join as join20 } from "path";
38643
38643
 
38644
38644
  // src/core/scaffold.ts
@@ -38661,6 +38661,10 @@ async function provisionRepos(target, repos, emit, opts = {}) {
38661
38661
  for (const repo of repos) {
38662
38662
  if (repo.primary) {
38663
38663
  if (opts.clonePrimary && repo.url) {
38664
+ if (existsSync12(join19(target, ".git"))) {
38665
+ emit("git", `Primary repo already present \u2014 skipping clone.`);
38666
+ continue;
38667
+ }
38664
38668
  emit("git", `Cloning ${repo.url}\u2026`);
38665
38669
  await run9("git", ["clone", repo.url, target], { timeout: 12e4 });
38666
38670
  continue;
@@ -38676,6 +38680,10 @@ async function provisionRepos(target, repos, emit, opts = {}) {
38676
38680
  }
38677
38681
  const dir2 = join19(target, subDirName(repo));
38678
38682
  if (repo.url) {
38683
+ if (existsSync12(join19(dir2, ".git"))) {
38684
+ emit("git", `Sub-repo ${subDirName(repo)} already present \u2014 skipping clone.`);
38685
+ continue;
38686
+ }
38679
38687
  emit("git", `Cloning sub-repo ${repo.url}\u2026`);
38680
38688
  await run9("git", ["clone", repo.url, dir2], { timeout: 12e4 });
38681
38689
  } else {
@@ -38791,12 +38799,19 @@ function handleProjectChannels(ctx, message, payload) {
38791
38799
  switch (message.channel) {
38792
38800
  case WsChannels.PHYSIC_SYNC: {
38793
38801
  const sync = payload;
38794
- if (sync.oldName) {
38795
- const oldRoot = ctx.physicFolderPath(sync.oldName);
38802
+ const oldName = sync.oldName;
38803
+ const oldPath = oldName ? join20(ctx.profileDir, oldName) : null;
38804
+ const newPath = join20(ctx.profileDir, sync.newName);
38805
+ if (oldName) {
38806
+ const oldRoot = ctx.physicFolderPath(oldName);
38796
38807
  if (oldRoot) void uninstallCron(oldRoot).catch(() => void 0);
38797
38808
  }
38798
- if (sync.oldName) rmSync6(join20(ctx.profileDir, sync.oldName), { recursive: true, force: true });
38799
- mkdirSync6(join20(ctx.profileDir, sync.newName), { recursive: true });
38809
+ if (oldPath && oldName !== sync.newName && existsSync13(oldPath) && !existsSync13(newPath)) {
38810
+ renameSync(oldPath, newPath);
38811
+ } else {
38812
+ if (oldPath && oldName !== sync.newName && existsSync13(oldPath)) rmSync6(oldPath, { recursive: true, force: true });
38813
+ mkdirSync6(newPath, { recursive: true });
38814
+ }
38800
38815
  ctx.physicRoot = ctx.physicFolderPath(sync.newName);
38801
38816
  ctx.bus.setProject(sync.newName);
38802
38817
  ctx.bus.log(t("project.folderSynced", { name: sync.newName }));
@@ -39587,7 +39602,7 @@ async function buildGraph(root, mode) {
39587
39602
 
39588
39603
  // src/core/rag.ts
39589
39604
  import { readFile as readFile12, writeFile as writeFile10, statfs as statfs2, mkdir as mkdir10 } from "fs/promises";
39590
- import { existsSync as existsSync13 } from "fs";
39605
+ import { existsSync as existsSync14 } from "fs";
39591
39606
  import { execFile as execFile10, spawn as spawn9 } from "child_process";
39592
39607
  import { totalmem as totalmem2, cpus as cpus2 } from "os";
39593
39608
  import { join as join26 } from "path";
@@ -39680,7 +39695,7 @@ async function ragStatus(root) {
39680
39695
  const modelPresent = modelName.length > 0;
39681
39696
  return {
39682
39697
  installed: fastembed && sqliteVec && modelPresent,
39683
- installing: existsSync13(join26(root, RAG_REL, ".installing")),
39698
+ installing: existsSync14(join26(root, RAG_REL, ".installing")),
39684
39699
  python: { found: py.found, version: py.version },
39685
39700
  deps: { pip, fastembed, sqliteVec },
39686
39701
  model: { present: modelPresent, name: modelName },
@@ -39691,7 +39706,7 @@ async function ragStatus(root) {
39691
39706
  };
39692
39707
  }
39693
39708
  async function readIndexMeta(root) {
39694
- const indexing = existsSync13(join26(root, RAG_REL, ".indexing"));
39709
+ const indexing = existsSync14(join26(root, RAG_REL, ".indexing"));
39695
39710
  try {
39696
39711
  const m = JSON.parse(await readFile12(join26(root, RAG_REL, ".index.json"), "utf8"));
39697
39712
  return {
@@ -39766,8 +39781,8 @@ async function ensureEngine(root) {
39766
39781
  async function ragReindex(root) {
39767
39782
  const py = await detectPython();
39768
39783
  if (!py.found) return { ok: false, started: false, error: "python3 not found" };
39769
- if (!existsSync13(join26(root, RAG_REL, ".installed"))) return { ok: false, started: false, error: "RAG is not installed" };
39770
- if (existsSync13(join26(root, RAG_REL, ".indexing"))) return { ok: true, started: true };
39784
+ if (!existsSync14(join26(root, RAG_REL, ".installed"))) return { ok: false, started: false, error: "RAG is not installed" };
39785
+ if (existsSync14(join26(root, RAG_REL, ".indexing"))) return { ok: true, started: true };
39771
39786
  await ensureEngine(root);
39772
39787
  const script = `
39773
39788
  set +e
@@ -39787,7 +39802,7 @@ rm -f "${RAG_REL}/.indexing"
39787
39802
  async function ragQuery(root, queryText, k = 8) {
39788
39803
  const py = await detectPython();
39789
39804
  if (!py.found) return { results: [], error: "python3 not found" };
39790
- if (!existsSync13(join26(root, RAG_REL, "index.db"))) return { results: [], error: "no index \u2014 reindex first" };
39805
+ if (!existsSync14(join26(root, RAG_REL, "index.db"))) return { results: [], error: "no index \u2014 reindex first" };
39791
39806
  await ensureEngine(root);
39792
39807
  try {
39793
39808
  const { stdout } = await run10(
@@ -39807,7 +39822,7 @@ async function ragInstall(root, model) {
39807
39822
  }
39808
39823
  const py = await detectPython();
39809
39824
  if (!py.found) return { ok: false, started: false, error: "python3 not found on the worker" };
39810
- if (existsSync13(join26(root, RAG_REL, ".installing"))) return { ok: true, started: true };
39825
+ if (existsSync14(join26(root, RAG_REL, ".installing"))) return { ok: true, started: true };
39811
39826
  try {
39812
39827
  await mkdir10(join26(root, RAG_REL), { recursive: true });
39813
39828
  } catch {
@@ -39836,7 +39851,7 @@ rm -f "${RAG_REL}/.installing"
39836
39851
  }
39837
39852
 
39838
39853
  // src/core/config-sync.ts
39839
- import { existsSync as existsSync14, readFileSync as readFileSync15 } from "fs";
39854
+ import { existsSync as existsSync15, readFileSync as readFileSync15 } from "fs";
39840
39855
  import { join as join27 } from "path";
39841
39856
  var SERVER_MANAGED_KEYS = [
39842
39857
  "physicPath",
@@ -39855,7 +39870,7 @@ var SERVER_MANAGED_KEYS = [
39855
39870
  ];
39856
39871
  function readConfigText(profileDir2) {
39857
39872
  const path = join27(profileDir2, "config.json");
39858
- if (existsSync14(path)) {
39873
+ if (existsSync15(path)) {
39859
39874
  try {
39860
39875
  return readFileSync15(path, "utf8");
39861
39876
  } catch {
@@ -40708,7 +40723,7 @@ var WsClient = class {
40708
40723
  /** Create the physic folder at an absolute path if missing (best-effort). */
40709
40724
  ensurePhysicFolderPath(folder) {
40710
40725
  try {
40711
- if (!existsSync15(folder)) {
40726
+ if (!existsSync16(folder)) {
40712
40727
  mkdirSync7(folder, { recursive: true });
40713
40728
  this.bus.log(t("project.createdFolder", { folder }));
40714
40729
  }
@@ -40738,7 +40753,7 @@ var WsClient = class {
40738
40753
  projects: [],
40739
40754
  version: CLI_VERSION,
40740
40755
  physicPath,
40741
- physicPathExists: physicPath ? existsSync15(physicPath) : void 0,
40756
+ physicPathExists: physicPath ? existsSync16(physicPath) : void 0,
40742
40757
  // Real coarse state (ADR-0152): !paused and a recent tick (was hard-coded false).
40743
40758
  autonomousRunning: physicPath ? isAutonomousRunning(physicPath) : false,
40744
40759
  // The machine-user AI-run limit (0 = unlimited) + profile count so a dispatch can resolve the
@@ -47057,7 +47072,7 @@ var import_react21 = __toESM(require_react(), 1);
47057
47072
  var import_react26 = __toESM(require_react(), 1);
47058
47073
 
47059
47074
  // src/core/input-history.ts
47060
- import { existsSync as existsSync17, readFileSync as readFileSync18, writeFileSync as writeFileSync10 } from "fs";
47075
+ import { existsSync as existsSync18, readFileSync as readFileSync18, writeFileSync as writeFileSync10 } from "fs";
47061
47076
  import { join as join31 } from "path";
47062
47077
  var MAX_HISTORY = 200;
47063
47078
  function historyPath(profileDir2) {
@@ -47065,7 +47080,7 @@ function historyPath(profileDir2) {
47065
47080
  }
47066
47081
  function loadInputHistory(profileDir2) {
47067
47082
  const path = historyPath(profileDir2);
47068
- if (!existsSync17(path)) return [];
47083
+ if (!existsSync18(path)) return [];
47069
47084
  try {
47070
47085
  const data = JSON.parse(readFileSync18(path, "utf8"));
47071
47086
  return Array.isArray(data) ? data.filter((x) => typeof x === "string") : [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@4pm/cli",
3
- "version": "1.7.0",
3
+ "version": "1.8.4",
4
4
  "private": false,
5
5
  "description": "4PM CLI — drives Claude/Codex CLIs on AI worker machines (Node + TypeScript)",
6
6
  "license": "LicenseRef-4PM-Source-Available",