@4pm/cli 1.5.37 → 1.5.40

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 +255 -138
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -5713,14 +5713,14 @@ var require_react_development = __commonJS({
5713
5713
  var thenableResult = result;
5714
5714
  var wasAwaited = false;
5715
5715
  var thenable = {
5716
- then: function(resolve9, reject) {
5716
+ then: function(resolve10, reject) {
5717
5717
  wasAwaited = true;
5718
5718
  thenableResult.then(function(returnValue2) {
5719
5719
  popActScope(prevActScopeDepth);
5720
5720
  if (actScopeDepth === 0) {
5721
- recursivelyFlushAsyncActWork(returnValue2, resolve9, reject);
5721
+ recursivelyFlushAsyncActWork(returnValue2, resolve10, reject);
5722
5722
  } else {
5723
- resolve9(returnValue2);
5723
+ resolve10(returnValue2);
5724
5724
  }
5725
5725
  }, function(error2) {
5726
5726
  popActScope(prevActScopeDepth);
@@ -5750,20 +5750,20 @@ var require_react_development = __commonJS({
5750
5750
  ReactCurrentActQueue.current = null;
5751
5751
  }
5752
5752
  var _thenable = {
5753
- then: function(resolve9, reject) {
5753
+ then: function(resolve10, reject) {
5754
5754
  if (ReactCurrentActQueue.current === null) {
5755
5755
  ReactCurrentActQueue.current = [];
5756
- recursivelyFlushAsyncActWork(returnValue, resolve9, reject);
5756
+ recursivelyFlushAsyncActWork(returnValue, resolve10, reject);
5757
5757
  } else {
5758
- resolve9(returnValue);
5758
+ resolve10(returnValue);
5759
5759
  }
5760
5760
  }
5761
5761
  };
5762
5762
  return _thenable;
5763
5763
  } else {
5764
5764
  var _thenable2 = {
5765
- then: function(resolve9, reject) {
5766
- resolve9(returnValue);
5765
+ then: function(resolve10, reject) {
5766
+ resolve10(returnValue);
5767
5767
  }
5768
5768
  };
5769
5769
  return _thenable2;
@@ -5779,7 +5779,7 @@ var require_react_development = __commonJS({
5779
5779
  actScopeDepth = prevActScopeDepth;
5780
5780
  }
5781
5781
  }
5782
- function recursivelyFlushAsyncActWork(returnValue, resolve9, reject) {
5782
+ function recursivelyFlushAsyncActWork(returnValue, resolve10, reject) {
5783
5783
  {
5784
5784
  var queue = ReactCurrentActQueue.current;
5785
5785
  if (queue !== null) {
@@ -5788,16 +5788,16 @@ var require_react_development = __commonJS({
5788
5788
  enqueueTask(function() {
5789
5789
  if (queue.length === 0) {
5790
5790
  ReactCurrentActQueue.current = null;
5791
- resolve9(returnValue);
5791
+ resolve10(returnValue);
5792
5792
  } else {
5793
- recursivelyFlushAsyncActWork(returnValue, resolve9, reject);
5793
+ recursivelyFlushAsyncActWork(returnValue, resolve10, reject);
5794
5794
  }
5795
5795
  });
5796
5796
  } catch (error2) {
5797
5797
  reject(error2);
5798
5798
  }
5799
5799
  } else {
5800
- resolve9(returnValue);
5800
+ resolve10(returnValue);
5801
5801
  }
5802
5802
  }
5803
5803
  }
@@ -28560,8 +28560,22 @@ function normalizeLocale(value) {
28560
28560
 
28561
28561
  // vendor/@4pm/constants/project-template.ts
28562
28562
  var PROJECT_TEMPLATE = {
28563
- version: "1.0.1",
28563
+ version: "1.0.2",
28564
28564
  changelog: [
28565
+ {
28566
+ version: "1.0.2",
28567
+ date: "2026-09-16",
28568
+ summary: "AI_DONE.md changed to a Markdown table \u2014 catch-up entry for projects scaffolded before the conversion.",
28569
+ notes: [
28570
+ "AI_DONE.md's Done and Incidents sections are Markdown tables (| Timestamp | ID | Task description | Files | Notes | and | Timestamp | Note |), matching the other autonomous books.",
28571
+ "The conversion itself shipped with the baseline scaffold, but was never recorded as a template version, so the 1.0.1 changelog assumed AI_DONE was already tabular. Projects scaffolded before it still carry the old two-section prose layout even at 1.0.1; this entry lets them detect the drift and convert AI_DONE on the next Update."
28572
+ ],
28573
+ files: [
28574
+ "AI_DONE.md",
28575
+ ".claude/templates/AI_DONE.empty.md",
28576
+ ".claude/templates/AI_DONE.sample.md"
28577
+ ]
28578
+ },
28565
28579
  {
28566
28580
  version: "1.0.1",
28567
28581
  date: "2026-09-13",
@@ -29621,7 +29635,7 @@ async function checkAndUpdate(serverUrl, autoUpdate) {
29621
29635
  // src/core/ws-client.ts
29622
29636
  init_wrapper();
29623
29637
  import { randomUUID as randomUUID2 } from "crypto";
29624
- import { basename as basename6, join as join28 } from "path";
29638
+ import { basename as basename7, join as join28 } from "path";
29625
29639
  import { existsSync as existsSync15, mkdirSync as mkdirSync7 } from "fs";
29626
29640
 
29627
29641
  // vendor/@4pm/utils/helpers.ts
@@ -33978,6 +33992,16 @@ var fsMutateRequestSchema = external_exports.object({
33978
33992
  from: external_exports.string().max(1024).optional(),
33979
33993
  to: external_exports.string().max(1024).optional()
33980
33994
  });
33995
+ var FS_TRANSFER_MAX_BYTES = 10 * 1024 * 1024;
33996
+ var FS_TRANSFER_MAX_BASE64 = Math.ceil(FS_TRANSFER_MAX_BYTES * 4 / 3) + 16;
33997
+ var fsUploadRequestSchema = external_exports.object({
33998
+ /** Destination path relative to the physic-project root; a `..` escaping the root is rejected on the cli. */
33999
+ path: external_exports.string().min(1).max(1024),
34000
+ /** File bytes, base64-encoded (capped to the transfer limit). */
34001
+ contentBase64: external_exports.string().min(1).max(FS_TRANSFER_MAX_BASE64),
34002
+ /** Optional MIME type from the browser (informational). */
34003
+ contentType: external_exports.string().max(255).optional()
34004
+ });
33981
34005
  var taskApproveRequestSchema = external_exports.object({
33982
34006
  taskId: external_exports.string().min(1).max(64),
33983
34007
  approved: external_exports.boolean()
@@ -34578,6 +34602,12 @@ var WsChannels = {
34578
34602
  // server → cli (reply): create/rename/move/delete a file or folder in the project tree,
34579
34603
  // each op path-clamped to the physic root (machine-0059, ADR-0260, `project.files_write`).
34580
34604
  FS_MUTATE: "fs.mutate",
34605
+ // server → cli (reply): move file bytes between browser and worker as base64, root-clamped +
34606
+ // size-capped (machine-0061/0062, ADR-0278). `fs.upload` writes an uploaded/pasted file into the
34607
+ // tree (`project.files_write`); `fs.download` reads a file's raw bytes for the browser to save
34608
+ // (`project.read`). Binary transfer the text-only fs.read/fs.write can't carry.
34609
+ FS_UPLOAD: "fs.upload",
34610
+ FS_DOWNLOAD: "fs.download",
34581
34611
  GIT_DIFF: "git.diff",
34582
34612
  GIT_ENV: "git.env",
34583
34613
  // server → cli (reply): read/write the paired profile's config.json (machine-0025/0026,
@@ -34890,8 +34920,8 @@ function resolveInstallTimeoutMs(sec) {
34890
34920
  return sec && sec > 0 ? sec * 1e3 : TOOL_INSTALL_TIMEOUT_DEFAULT_MS;
34891
34921
  }
34892
34922
  function sleep(ms) {
34893
- return new Promise((resolve9) => {
34894
- const t2 = setTimeout(resolve9, ms);
34923
+ return new Promise((resolve10) => {
34924
+ const t2 = setTimeout(resolve10, ms);
34895
34925
  t2.unref?.();
34896
34926
  });
34897
34927
  }
@@ -34913,14 +34943,14 @@ function classifyToolFailure(code, out) {
34913
34943
  return { reason: "other", retryable: false };
34914
34944
  }
34915
34945
  function run(cmd, args, onLine, timeoutMs = 18e4) {
34916
- return new Promise((resolve9) => {
34946
+ return new Promise((resolve10) => {
34917
34947
  let out = "";
34918
34948
  let buf = "";
34919
34949
  let child = null;
34920
34950
  const done = (code) => {
34921
34951
  clearTimeout(timer);
34922
34952
  if (onLine && buf.trim()) onLine(buf.trim());
34923
- resolve9({ code, out });
34953
+ resolve10({ code, out });
34924
34954
  };
34925
34955
  const timer = setTimeout(() => {
34926
34956
  child?.kill();
@@ -35624,16 +35654,16 @@ async function fetchUsage(token) {
35624
35654
  }
35625
35655
  }
35626
35656
  function runUsageCli(dir2, aiCli2) {
35627
- return new Promise((resolve9) => {
35657
+ return new Promise((resolve10) => {
35628
35658
  let out = "";
35629
35659
  let child = null;
35630
35660
  const finish = () => {
35631
35661
  clearTimeout(timer);
35632
- resolve9(out);
35662
+ resolve10(out);
35633
35663
  };
35634
35664
  const timer = setTimeout(() => {
35635
35665
  child?.kill();
35636
- resolve9(out);
35666
+ resolve10(out);
35637
35667
  }, 3e4);
35638
35668
  timer.unref?.();
35639
35669
  try {
@@ -36194,7 +36224,7 @@ function parseModeratedAnswer(text) {
36194
36224
  return { body: text.trim() };
36195
36225
  }
36196
36226
  function runClaudeOnce(cmd, profile, prompt, extraEnv, imageDir) {
36197
- return new Promise((resolve9, reject) => {
36227
+ return new Promise((resolve10, reject) => {
36198
36228
  const isClaude = cmd.includes("claude");
36199
36229
  const args = [
36200
36230
  "-p",
@@ -36227,7 +36257,7 @@ function runClaudeOnce(cmd, profile, prompt, extraEnv, imageDir) {
36227
36257
  child.on("close", (code) => {
36228
36258
  clearTimeout(timer);
36229
36259
  out += parser.flush();
36230
- resolve9({ code: code ?? -1, out, err, usage: parser.usage() });
36260
+ resolve10({ code: code ?? -1, out, err, usage: parser.usage() });
36231
36261
  });
36232
36262
  child.stdin.write(prompt);
36233
36263
  child.stdin.end();
@@ -36361,10 +36391,10 @@ async function crontabList() {
36361
36391
  }
36362
36392
  }
36363
36393
  async function crontabSet(content) {
36364
- return new Promise((resolve9) => {
36394
+ return new Promise((resolve10) => {
36365
36395
  const child = spawn5("crontab", ["-"], { stdio: ["pipe", "ignore", "ignore"] });
36366
- child.on("error", () => resolve9(false));
36367
- child.on("close", (code) => resolve9(code === 0));
36396
+ child.on("error", () => resolve10(false));
36397
+ child.on("close", (code) => resolve10(code === 0));
36368
36398
  child.stdin.end(content.endsWith("\n") ? content : content + "\n");
36369
36399
  });
36370
36400
  }
@@ -36488,14 +36518,14 @@ function detectContainerized() {
36488
36518
  }
36489
36519
  }
36490
36520
  function canReach(host, port) {
36491
- return new Promise((resolve9) => {
36521
+ return new Promise((resolve10) => {
36492
36522
  const socket = connect({ host, port });
36493
36523
  let done = false;
36494
36524
  const finish = (ok) => {
36495
36525
  if (done) return;
36496
36526
  done = true;
36497
36527
  socket.destroy();
36498
- resolve9(ok);
36528
+ resolve10(ok);
36499
36529
  };
36500
36530
  socket.setTimeout(PROBE_TIMEOUT_MS);
36501
36531
  socket.once("connect", () => finish(true));
@@ -36667,7 +36697,7 @@ async function runCommand(dispatch, emit, opts) {
36667
36697
  });
36668
36698
  child.stdout?.on("data", (data) => batcher.push(data.toString("utf8")));
36669
36699
  child.stderr?.on("data", (data) => batcher.push(data.toString("utf8")));
36670
- await new Promise((resolve9) => {
36700
+ await new Promise((resolve10) => {
36671
36701
  child.on("close", (exitCode) => {
36672
36702
  clearTimers();
36673
36703
  batcher.flush();
@@ -36680,7 +36710,7 @@ async function runCommand(dispatch, emit, opts) {
36680
36710
  // server settles the command as failed and the web surfaces the note instead of spinning.
36681
36711
  exitCode: timedOut ? 124 : exitCode ?? -1
36682
36712
  });
36683
- resolve9();
36713
+ resolve10();
36684
36714
  });
36685
36715
  child.on("error", (err) => {
36686
36716
  clearTimers();
@@ -36692,7 +36722,7 @@ async function runCommand(dispatch, emit, opts) {
36692
36722
  done: true,
36693
36723
  exitCode: -1
36694
36724
  });
36695
- resolve9();
36725
+ resolve10();
36696
36726
  });
36697
36727
  });
36698
36728
  }
@@ -36714,15 +36744,15 @@ function isOutOfCredits(text) {
36714
36744
  );
36715
36745
  }
36716
36746
  function runAttempt(commandId, cmd, args, stdin, cwd2, env3, onChunk, timeoutMs) {
36717
- return new Promise((resolve9) => {
36747
+ return new Promise((resolve10) => {
36718
36748
  runCommand(
36719
36749
  { commandId, cmd, args, path: cwd2, env: env3 },
36720
36750
  (out) => {
36721
36751
  if (out.chunk) onChunk(out.chunk);
36722
- if (out.done) resolve9(out.exitCode ?? -1);
36752
+ if (out.done) resolve10(out.exitCode ?? -1);
36723
36753
  },
36724
36754
  { stdin, ...timeoutMs > 0 ? { timeoutMs } : {} }
36725
- ).catch(() => resolve9(-1));
36755
+ ).catch(() => resolve10(-1));
36726
36756
  });
36727
36757
  }
36728
36758
  async function runAiFailover(plan, commandId, cwd2, handlers, timeoutMs = 0) {
@@ -37220,7 +37250,7 @@ function buildPrompt2(input) {
37220
37250
  ].join("\n");
37221
37251
  }
37222
37252
  function runOnce(cmd, profile, prompt, cwd2, extraEnv) {
37223
- return new Promise((resolve9, reject) => {
37253
+ return new Promise((resolve10, reject) => {
37224
37254
  const args = ["-p", ...profile?.model ? ["--model", profile.model] : []];
37225
37255
  const env3 = {
37226
37256
  ...process.env,
@@ -37243,7 +37273,7 @@ function runOnce(cmd, profile, prompt, cwd2, extraEnv) {
37243
37273
  });
37244
37274
  child.on("close", (code) => {
37245
37275
  clearTimeout(timer);
37246
- resolve9({ code: code ?? -1, out, err });
37276
+ resolve10({ code: code ?? -1, out, err });
37247
37277
  });
37248
37278
  child.stdin.write(prompt);
37249
37279
  child.stdin.end();
@@ -37930,6 +37960,79 @@ async function mutateFs(root, req) {
37930
37960
  }
37931
37961
  }
37932
37962
 
37963
+ // src/core/fs-transfer.ts
37964
+ import { mkdir as mkdir4, readFile as readFile4, stat as stat2, writeFile as writeFile4 } from "fs/promises";
37965
+ import { basename as basename4, dirname as dirname5, extname, resolve as resolve5, sep as sep5 } from "path";
37966
+ function resolveInRoot3(root, relPath) {
37967
+ if (!root) return null;
37968
+ const base = resolve5(root);
37969
+ const target = resolve5(base, relPath || ".");
37970
+ return target === base || target.startsWith(base + sep5) ? target : null;
37971
+ }
37972
+ var MIME_BY_EXT = {
37973
+ ".png": "image/png",
37974
+ ".jpg": "image/jpeg",
37975
+ ".jpeg": "image/jpeg",
37976
+ ".gif": "image/gif",
37977
+ ".webp": "image/webp",
37978
+ ".svg": "image/svg+xml",
37979
+ ".bmp": "image/bmp",
37980
+ ".ico": "image/x-icon",
37981
+ ".pdf": "application/pdf",
37982
+ ".zip": "application/zip",
37983
+ ".json": "application/json",
37984
+ ".txt": "text/plain",
37985
+ ".md": "text/markdown",
37986
+ ".csv": "text/csv",
37987
+ ".html": "text/html",
37988
+ ".xml": "application/xml"
37989
+ };
37990
+ function guessMime(path) {
37991
+ return MIME_BY_EXT[extname(path).toLowerCase()] ?? "application/octet-stream";
37992
+ }
37993
+ async function uploadBinaryFile(root, relPath, contentBase64) {
37994
+ const target = resolveInRoot3(root, relPath);
37995
+ if (!target) {
37996
+ return { ok: false, path: relPath, bytes: 0, error: "path escapes the project root" };
37997
+ }
37998
+ let buf;
37999
+ try {
38000
+ buf = Buffer.from(contentBase64, "base64");
38001
+ } catch {
38002
+ return { ok: false, path: target, bytes: 0, error: "invalid base64 payload" };
38003
+ }
38004
+ if (buf.byteLength > FS_TRANSFER_MAX_BYTES) {
38005
+ return { ok: false, path: target, bytes: 0, error: `file too large (max ${FS_TRANSFER_MAX_BYTES} bytes)` };
38006
+ }
38007
+ try {
38008
+ await mkdir4(dirname5(target), { recursive: true });
38009
+ await writeFile4(target, buf);
38010
+ return { ok: true, path: target, bytes: buf.byteLength };
38011
+ } catch (err) {
38012
+ return { ok: false, path: target, bytes: 0, error: err instanceof Error ? err.message : String(err) };
38013
+ }
38014
+ }
38015
+ async function downloadBinaryFile(root, relPath) {
38016
+ const target = resolveInRoot3(root, relPath);
38017
+ if (!target) return { error: "path escapes the project root" };
38018
+ try {
38019
+ const info = await stat2(target);
38020
+ if (!info.isFile()) return { error: "not a file" };
38021
+ if (info.size > FS_TRANSFER_MAX_BYTES) {
38022
+ return { error: `file too large (max ${FS_TRANSFER_MAX_BYTES} bytes)` };
38023
+ }
38024
+ const buf = await readFile4(target);
38025
+ return {
38026
+ contentBase64: buf.toString("base64"),
38027
+ contentType: guessMime(target),
38028
+ name: basename4(target),
38029
+ size: buf.byteLength
38030
+ };
38031
+ } catch (err) {
38032
+ return { error: err instanceof Error ? err.message : String(err) };
38033
+ }
38034
+ }
38035
+
37933
38036
  // src/core/ws-client/handlers/fs.ts
37934
38037
  function handleFsChannels(ctx, message, payload) {
37935
38038
  switch (message.channel) {
@@ -37957,24 +38060,38 @@ function handleFsChannels(ctx, message, payload) {
37957
38060
  );
37958
38061
  return true;
37959
38062
  }
38063
+ case WsChannels.FS_UPLOAD: {
38064
+ const req = payload;
38065
+ void uploadBinaryFile(ctx.physicRoot, req.path, req.contentBase64).then(
38066
+ (reply) => ctx.send(WsChannels.FS_UPLOAD, reply, message.id)
38067
+ );
38068
+ return true;
38069
+ }
38070
+ case WsChannels.FS_DOWNLOAD: {
38071
+ const req = payload;
38072
+ void downloadBinaryFile(ctx.physicRoot, req.path).then(
38073
+ (reply) => ctx.send(WsChannels.FS_DOWNLOAD, reply, message.id)
38074
+ );
38075
+ return true;
38076
+ }
37960
38077
  default:
37961
38078
  return false;
37962
38079
  }
37963
38080
  }
37964
38081
 
37965
38082
  // src/core/git-diff.ts
37966
- import { readFile as readFile4 } from "fs/promises";
38083
+ import { readFile as readFile5 } from "fs/promises";
37967
38084
  import { execFile as execFile4 } from "child_process";
37968
- import { basename as basename4, dirname as dirname5, resolve as resolve5 } from "path";
38085
+ import { basename as basename5, dirname as dirname6, resolve as resolve6 } from "path";
37969
38086
  import { promisify as promisify4 } from "util";
37970
38087
  var run4 = promisify4(execFile4);
37971
38088
  async function gitDiff(path) {
37972
- const target = resolve5(path);
37973
- const dir2 = dirname5(target);
37974
- const base = basename4(target);
38089
+ const target = resolve6(path);
38090
+ const dir2 = dirname6(target);
38091
+ const base = basename5(target);
37975
38092
  let newContent = "";
37976
38093
  try {
37977
- newContent = await readFile4(target, "utf8");
38094
+ newContent = await readFile5(target, "utf8");
37978
38095
  } catch {
37979
38096
  }
37980
38097
  let oldContent = "";
@@ -38023,7 +38140,7 @@ ${stderr}`;
38023
38140
 
38024
38141
  // src/core/git-ssh-key.ts
38025
38142
  import { execFile as execFile6 } from "child_process";
38026
- import { readFile as readFile5, rm as rm2, mkdir as mkdir4 } from "fs/promises";
38143
+ import { readFile as readFile6, rm as rm2, mkdir as mkdir5 } from "fs/promises";
38027
38144
  import { join as join17 } from "path";
38028
38145
  import { promisify as promisify6 } from "util";
38029
38146
  var run6 = promisify6(execFile6);
@@ -38034,7 +38151,7 @@ function keyPaths(profileDir2) {
38034
38151
  }
38035
38152
  async function readPublicKey(pub) {
38036
38153
  try {
38037
- return (await readFile5(pub, "utf8")).trim();
38154
+ return (await readFile6(pub, "utf8")).trim();
38038
38155
  } catch {
38039
38156
  return null;
38040
38157
  }
@@ -38056,7 +38173,7 @@ async function configureGit(key) {
38056
38173
  }
38057
38174
  async function generate(profileDir2) {
38058
38175
  const { dir: dir2, key, pub } = keyPaths(profileDir2);
38059
- await mkdir4(dir2, { recursive: true });
38176
+ await mkdir5(dir2, { recursive: true });
38060
38177
  await rm2(key, { force: true });
38061
38178
  await rm2(pub, { force: true });
38062
38179
  await run6("ssh-keygen", ["-t", "ed25519", "-f", key, "-N", "", "-C", "4pm-deploy-key"], {
@@ -38092,16 +38209,16 @@ async function manageSshKey(op, profileDir2) {
38092
38209
  // src/core/git-history.ts
38093
38210
  import { readdir as readdir3 } from "fs/promises";
38094
38211
  import { execFile as execFile7 } from "child_process";
38095
- import { resolve as resolve6, sep as sep5 } from "path";
38212
+ import { resolve as resolve7, sep as sep6 } from "path";
38096
38213
  import { promisify as promisify7 } from "util";
38097
38214
  var run7 = promisify7(execFile7);
38098
38215
  var FS = "";
38099
38216
  var RS = "";
38100
38217
  function resolveRepo(root, repo) {
38101
38218
  if (!root) return null;
38102
- const base = resolve6(root);
38103
- const requested = resolve6(base, repo && repo.trim() ? repo : ".");
38104
- return requested === base || requested.startsWith(base + sep5) ? requested : base;
38219
+ const base = resolve7(root);
38220
+ const requested = resolve7(base, repo && repo.trim() ? repo : ".");
38221
+ return requested === base || requested.startsWith(base + sep6) ? requested : base;
38105
38222
  }
38106
38223
  async function git(cwd2, args) {
38107
38224
  try {
@@ -38117,13 +38234,13 @@ async function git(cwd2, args) {
38117
38234
  }
38118
38235
  async function gitRepos(root) {
38119
38236
  if (!root) return { repos: [] };
38120
- const base = resolve6(root);
38237
+ const base = resolve7(root);
38121
38238
  const found = /* @__PURE__ */ new Set();
38122
38239
  const repos = [];
38123
38240
  const add = async (dir2) => {
38124
38241
  const inside = await git(dir2, ["rev-parse", "--show-toplevel"]);
38125
38242
  const top = inside.trim();
38126
- if (!top || found.has(top) || !(top === base || top.startsWith(base + sep5))) return;
38243
+ if (!top || found.has(top) || !(top === base || top.startsWith(base + sep6))) return;
38127
38244
  found.add(top);
38128
38245
  const subdir = top === base ? "" : top.slice(base.length + 1);
38129
38246
  const remote = (await git(top, ["remote", "get-url", "origin"])).trim();
@@ -38134,13 +38251,13 @@ async function gitRepos(root) {
38134
38251
  const lvl1 = await readdir3(base, { withFileTypes: true });
38135
38252
  for (const d of lvl1) {
38136
38253
  if (!d.isDirectory() || d.name === ".git" || d.name === "node_modules") continue;
38137
- const p1 = resolve6(base, d.name);
38254
+ const p1 = resolve7(base, d.name);
38138
38255
  await add(p1);
38139
38256
  try {
38140
38257
  const lvl2 = await readdir3(p1, { withFileTypes: true });
38141
38258
  for (const d2 of lvl2) {
38142
38259
  if (!d2.isDirectory() || d2.name === ".git" || d2.name === "node_modules") continue;
38143
- await add(resolve6(p1, d2.name));
38260
+ await add(resolve7(p1, d2.name));
38144
38261
  }
38145
38262
  } catch {
38146
38263
  }
@@ -38443,10 +38560,10 @@ import { mkdirSync as mkdirSync6, rmSync as rmSync6 } from "fs";
38443
38560
  import { join as join20 } from "path";
38444
38561
 
38445
38562
  // src/core/scaffold.ts
38446
- import { cp, mkdir as mkdir5, writeFile as writeFile4 } from "fs/promises";
38563
+ import { cp, mkdir as mkdir6, writeFile as writeFile5 } from "fs/promises";
38447
38564
  import { existsSync as existsSync12 } from "fs";
38448
38565
  import { execFile as execFile9 } from "child_process";
38449
- import { dirname as dirname6, join as join19, resolve as resolve7 } from "path";
38566
+ import { dirname as dirname7, join as join19, resolve as resolve8 } from "path";
38450
38567
  import { fileURLToPath as fileURLToPath3 } from "url";
38451
38568
  import { promisify as promisify9 } from "util";
38452
38569
  var run9 = promisify9(execFile9);
@@ -38481,16 +38598,16 @@ async function provisionRepos(target, repos, emit, opts = {}) {
38481
38598
  await run9("git", ["clone", repo.url, dir2], { timeout: 12e4 });
38482
38599
  } else {
38483
38600
  emit("git", `Initializing sub-repo ${subDirName(repo)}\u2026`);
38484
- await mkdir5(dir2, { recursive: true });
38601
+ await mkdir6(dir2, { recursive: true });
38485
38602
  await run9("git", ["init"], { cwd: dir2, timeout: 2e4 });
38486
38603
  }
38487
38604
  }
38488
38605
  }
38489
38606
  function sampleDir() {
38490
38607
  if (process.env.SCAFFOLD_SAMPLE_DIR) return process.env.SCAFFOLD_SAMPLE_DIR;
38491
- const here = dirname6(fileURLToPath3(import.meta.url));
38492
- const bundled = resolve7(here, "project-sample");
38493
- for (const candidate of [bundled, resolve7(here, "../project-sample"), resolve7(here, "../../project-sample")]) {
38608
+ const here = dirname7(fileURLToPath3(import.meta.url));
38609
+ const bundled = resolve8(here, "project-sample");
38610
+ for (const candidate of [bundled, resolve8(here, "../project-sample"), resolve8(here, "../../project-sample")]) {
38494
38611
  if (existsSync12(candidate)) return candidate;
38495
38612
  }
38496
38613
  return bundled;
@@ -38502,14 +38619,14 @@ async function scaffoldProject(payload, profileDir2, onProgress) {
38502
38619
  onProgress?.({ projectId: payload.projectId, step, message });
38503
38620
  };
38504
38621
  try {
38505
- const root = process.env.SCAFFOLD_ROOT ? resolve7(process.env.SCAFFOLD_ROOT) : resolve7(profileDir2);
38622
+ const root = process.env.SCAFFOLD_ROOT ? resolve8(process.env.SCAFFOLD_ROOT) : resolve8(profileDir2);
38506
38623
  const target = join19(root, payload.projectName);
38507
- await mkdir5(target, { recursive: true });
38624
+ await mkdir6(target, { recursive: true });
38508
38625
  emit("copy", "Copying the sample template\u2026");
38509
38626
  await cp(sampleDir(), target, { recursive: true, force: false, errorOnExist: false });
38510
38627
  if (payload.spec) {
38511
38628
  emit("spec", "Writing project.spec.json\u2026");
38512
- await writeFile4(
38629
+ await writeFile5(
38513
38630
  join19(target, "project.spec.json"),
38514
38631
  JSON.stringify(payload.spec, null, 2),
38515
38632
  "utf8"
@@ -38528,15 +38645,15 @@ async function scaffoldProject(payload, profileDir2, onProgress) {
38528
38645
  }
38529
38646
  async function writeTemplateMarker(target) {
38530
38647
  const dir2 = join19(target, ".4pm");
38531
- await mkdir5(dir2, { recursive: true });
38648
+ await mkdir6(dir2, { recursive: true });
38532
38649
  const marker = { templateVersion: PROJECT_TEMPLATE.version, scaffoldedAt: (/* @__PURE__ */ new Date()).toISOString() };
38533
- await writeFile4(join19(dir2, ".4pm.json"), JSON.stringify(marker, null, 2) + "\n", "utf8");
38650
+ await writeFile5(join19(dir2, ".4pm.json"), JSON.stringify(marker, null, 2) + "\n", "utf8");
38534
38651
  }
38535
38652
  async function aiInit(target, spec, emit) {
38536
38653
  emit("ai-init", "AI init: subagents, README, CLAUDE.md\u2026");
38537
38654
  const subagents = Array.isArray(spec.subagents) ? spec.subagents : [];
38538
38655
  if (subagents.length > 0) {
38539
- await mkdir5(join19(target, ".claude", "agents"), { recursive: true });
38656
+ await mkdir6(join19(target, ".claude", "agents"), { recursive: true });
38540
38657
  for (const sa of subagents) {
38541
38658
  const name = (sa.name || "").trim().replace(/[^\w.-]+/g, "-").replace(/^-+|-+$/g, "");
38542
38659
  if (!name) continue;
@@ -38546,7 +38663,7 @@ name: ${name}
38546
38663
 
38547
38664
  ${(sa.description || "").trim()}
38548
38665
  `;
38549
- await writeFile4(join19(target, ".claude", "agents", `${name}.md`), body, "utf8");
38666
+ await writeFile5(join19(target, ".claude", "agents", `${name}.md`), body, "utf8");
38550
38667
  }
38551
38668
  }
38552
38669
  const specJson = JSON.stringify(spec);
@@ -38564,7 +38681,7 @@ ${specJson}`
38564
38681
  async function generateFile(path, prompt) {
38565
38682
  try {
38566
38683
  const text = await aiGenerate(prompt);
38567
- if (text.trim()) await writeFile4(path, text.trim() + "\n", "utf8");
38684
+ if (text.trim()) await writeFile5(path, text.trim() + "\n", "utf8");
38568
38685
  } catch {
38569
38686
  }
38570
38687
  }
@@ -38575,9 +38692,9 @@ async function addProject(payload, profileDir2, onProgress) {
38575
38692
  onProgress?.({ projectId: payload.projectId, step, message });
38576
38693
  };
38577
38694
  try {
38578
- const root = process.env.SCAFFOLD_ROOT ? resolve7(process.env.SCAFFOLD_ROOT) : resolve7(profileDir2);
38695
+ const root = process.env.SCAFFOLD_ROOT ? resolve8(process.env.SCAFFOLD_ROOT) : resolve8(profileDir2);
38579
38696
  const target = join19(root, payload.projectName);
38580
- await mkdir5(target, { recursive: true });
38697
+ await mkdir6(target, { recursive: true });
38581
38698
  const repos = payload.repos ?? [];
38582
38699
  if (repos.length > 0) await provisionRepos(target, repos, emit, { clonePrimary: true });
38583
38700
  onProgress?.({ projectId: payload.projectId, step: "done", message: "Project added.", done: true });
@@ -38672,7 +38789,7 @@ Extra focus from the author: ${req.prompt}` : "";
38672
38789
  ].join("\n");
38673
38790
  }
38674
38791
  function runOnce2(cmd, profile, prompt, cwd2, extraEnv) {
38675
- return new Promise((resolve9, reject) => {
38792
+ return new Promise((resolve10, reject) => {
38676
38793
  const args = ["-p", ...profile?.model ? ["--model", profile.model] : []];
38677
38794
  const env3 = {
38678
38795
  ...process.env,
@@ -38695,7 +38812,7 @@ function runOnce2(cmd, profile, prompt, cwd2, extraEnv) {
38695
38812
  });
38696
38813
  child.on("close", (code) => {
38697
38814
  clearTimeout(timer);
38698
- resolve9({ code: code ?? -1, out, err });
38815
+ resolve10({ code: code ?? -1, out, err });
38699
38816
  });
38700
38817
  child.stdin.write(prompt);
38701
38818
  child.stdin.end();
@@ -38874,7 +38991,7 @@ function handleToolsChannels(ctx, message, payload) {
38874
38991
  }
38875
38992
 
38876
38993
  // src/core/agents.ts
38877
- import { readFile as readFile6, writeFile as writeFile5, mkdir as mkdir6, readdir as readdir4, rm as rm3 } from "fs/promises";
38994
+ import { readFile as readFile7, writeFile as writeFile6, mkdir as mkdir7, readdir as readdir4, rm as rm3 } from "fs/promises";
38878
38995
  import { join as join21 } from "path";
38879
38996
  var AGENTS_REL = ".claude/agents";
38880
38997
  var SKILLS_REL = ".claude/skills";
@@ -38884,7 +39001,7 @@ function safeName(name) {
38884
39001
  }
38885
39002
  async function readText2(path, fallback = "") {
38886
39003
  try {
38887
- return await readFile6(path, "utf8");
39004
+ return await readFile7(path, "utf8");
38888
39005
  } catch {
38889
39006
  return fallback;
38890
39007
  }
@@ -38943,8 +39060,8 @@ async function writeAgent(root, req) {
38943
39060
  }
38944
39061
  if (req.content === void 0) return { ok: false, error: "content is required" };
38945
39062
  const path = itemPath(root, req.kind, n);
38946
- await mkdir6(join21(path, ".."), { recursive: true });
38947
- await writeFile5(path, req.content, "utf8");
39063
+ await mkdir7(join21(path, ".."), { recursive: true });
39064
+ await writeFile6(path, req.content, "utf8");
38948
39065
  return { ok: true };
38949
39066
  } catch (err) {
38950
39067
  return { ok: false, error: err instanceof Error ? err.message : String(err) };
@@ -38952,21 +39069,21 @@ async function writeAgent(root, req) {
38952
39069
  }
38953
39070
 
38954
39071
  // src/core/secrets.ts
38955
- import { readFile as readFile7, writeFile as writeFile6 } from "fs/promises";
39072
+ import { readFile as readFile8, writeFile as writeFile7 } from "fs/promises";
38956
39073
  import { join as join22 } from "path";
38957
39074
  var SECURITY_REL = "AI_SECURITY.md";
38958
39075
  var PLACEHOLDER_REL = "AI_PLACEHOLDER.md";
38959
39076
  var SECRETS_REL = "project.secrets.json";
38960
39077
  async function readText3(path, fallback = "") {
38961
39078
  try {
38962
- return await readFile7(path, "utf8");
39079
+ return await readFile8(path, "utf8");
38963
39080
  } catch {
38964
39081
  return fallback;
38965
39082
  }
38966
39083
  }
38967
39084
  async function readSecretsObject(root) {
38968
39085
  try {
38969
- const v = JSON.parse(await readFile7(join22(root, SECRETS_REL), "utf8"));
39086
+ const v = JSON.parse(await readFile8(join22(root, SECRETS_REL), "utf8"));
38970
39087
  return v && typeof v === "object" ? v : {};
38971
39088
  } catch {
38972
39089
  return {};
@@ -38999,14 +39116,14 @@ async function readSecrets(root) {
38999
39116
  async function writeSecrets(root, req) {
39000
39117
  try {
39001
39118
  if (req.kind === "security") {
39002
- await writeFile6(join22(root, SECURITY_REL), req.content, "utf8");
39119
+ await writeFile7(join22(root, SECURITY_REL), req.content, "utf8");
39003
39120
  } else if (req.kind === "placeholder") {
39004
- await writeFile6(join22(root, PLACEHOLDER_REL), req.content, "utf8");
39121
+ await writeFile7(join22(root, PLACEHOLDER_REL), req.content, "utf8");
39005
39122
  } else {
39006
39123
  const secrets = await readSecretsObject(root);
39007
39124
  if (req.kind === "secret") secrets[req.key] = req.value;
39008
39125
  else delete secrets[req.key];
39009
- await writeFile6(join22(root, SECRETS_REL), JSON.stringify(secrets, null, 2) + "\n", "utf8");
39126
+ await writeFile7(join22(root, SECRETS_REL), JSON.stringify(secrets, null, 2) + "\n", "utf8");
39010
39127
  }
39011
39128
  return { ok: true };
39012
39129
  } catch (err) {
@@ -39015,8 +39132,8 @@ async function writeSecrets(root, req) {
39015
39132
  }
39016
39133
 
39017
39134
  // src/core/agent-tools.ts
39018
- import { readFile as readFile8, writeFile as writeFile7, mkdir as mkdir7 } from "fs/promises";
39019
- import { dirname as dirname7, join as join23 } from "path";
39135
+ import { readFile as readFile9, writeFile as writeFile8, mkdir as mkdir8 } from "fs/promises";
39136
+ import { dirname as dirname8, join as join23 } from "path";
39020
39137
  var SHARED_REL = ".claude/settings.json";
39021
39138
  var LOCAL_REL = ".claude/settings.local.json";
39022
39139
  var SECRETS_DENY = "Read(./project.secrets.json)";
@@ -39026,7 +39143,7 @@ function fileFor(root, scope) {
39026
39143
  }
39027
39144
  async function readSettingsObject(path) {
39028
39145
  try {
39029
- const v = JSON.parse(await readFile8(path, "utf8"));
39146
+ const v = JSON.parse(await readFile9(path, "utf8"));
39030
39147
  return v && typeof v === "object" ? v : {};
39031
39148
  } catch {
39032
39149
  return {};
@@ -39049,8 +39166,8 @@ async function writeAgentTools(root, scope, permissions) {
39049
39166
  const next = normalizePermissions(permissions);
39050
39167
  if (scope === "shared" && !next.deny.includes(SECRETS_DENY)) next.deny = [...next.deny, SECRETS_DENY];
39051
39168
  obj.permissions = next;
39052
- await mkdir7(dirname7(path), { recursive: true });
39053
- await writeFile7(path, JSON.stringify(obj, null, 2) + "\n", "utf8");
39169
+ await mkdir8(dirname8(path), { recursive: true });
39170
+ await writeFile8(path, JSON.stringify(obj, null, 2) + "\n", "utf8");
39054
39171
  return { ok: true };
39055
39172
  } catch (err) {
39056
39173
  return { ok: false, error: err instanceof Error ? err.message : String(err) };
@@ -39059,8 +39176,8 @@ async function writeAgentTools(root, scope, permissions) {
39059
39176
 
39060
39177
  // src/core/packages.ts
39061
39178
  import { createHash as createHash4 } from "crypto";
39062
- import { readFile as readFile9, writeFile as writeFile8, mkdir as mkdir8, readdir as readdir5, rm as rm4, stat as stat2 } from "fs/promises";
39063
- import { dirname as dirname8, join as join24, relative } from "path";
39179
+ import { readFile as readFile10, writeFile as writeFile9, mkdir as mkdir9, readdir as readdir5, rm as rm4, stat as stat3 } from "fs/promises";
39180
+ import { dirname as dirname9, join as join24, relative } from "path";
39064
39181
  var AGENTS_REL2 = ".claude/agents";
39065
39182
  var SKILLS_REL2 = ".claude/skills";
39066
39183
  var MANIFEST_REL = ".claude/.4pm-packages.json";
@@ -39069,7 +39186,7 @@ function safeName2(name) {
39069
39186
  }
39070
39187
  async function readMaybe(path) {
39071
39188
  try {
39072
- return await readFile9(path);
39189
+ return await readFile10(path);
39073
39190
  } catch {
39074
39191
  return null;
39075
39192
  }
@@ -39124,7 +39241,7 @@ async function artifactSha256(root, kind, slug) {
39124
39241
  async function artifactExists(root, kind, slug) {
39125
39242
  const target = kind === "subagent" ? join24(root, AGENTS_REL2, `${slug}.md`) : join24(root, SKILLS_REL2, slug);
39126
39243
  try {
39127
- await stat2(target);
39244
+ await stat3(target);
39128
39245
  return true;
39129
39246
  } catch {
39130
39247
  return false;
@@ -39141,34 +39258,34 @@ async function readManifest(root) {
39141
39258
  }
39142
39259
  async function writeManifest(root, manifest) {
39143
39260
  const path = join24(root, MANIFEST_REL);
39144
- await mkdir8(dirname8(path), { recursive: true });
39145
- await writeFile8(path, JSON.stringify(manifest, null, 2), "utf8");
39261
+ await mkdir9(dirname9(path), { recursive: true });
39262
+ await writeFile9(path, JSON.stringify(manifest, null, 2), "utf8");
39146
39263
  }
39147
39264
  async function writeArtifactFiles(root, kind, slug, files) {
39148
39265
  const byPath = new Map(files.map((f) => [f.path, Buffer.from(f.contentBase64, "base64")]));
39149
39266
  if (kind === "subagent") {
39150
39267
  const agent = byPath.get("agent.md");
39151
39268
  if (agent) {
39152
- await mkdir8(join24(root, AGENTS_REL2), { recursive: true });
39153
- await writeFile8(join24(root, AGENTS_REL2, `${slug}.md`), agent);
39269
+ await mkdir9(join24(root, AGENTS_REL2), { recursive: true });
39270
+ await writeFile9(join24(root, AGENTS_REL2, `${slug}.md`), agent);
39154
39271
  }
39155
39272
  const short = byPath.get("short-memory.md");
39156
39273
  if (short) {
39157
- await mkdir8(join24(root, AGENTS_REL2, "short-memory"), { recursive: true });
39158
- await writeFile8(join24(root, AGENTS_REL2, "short-memory", `${slug}.md`), short);
39274
+ await mkdir9(join24(root, AGENTS_REL2, "short-memory"), { recursive: true });
39275
+ await writeFile9(join24(root, AGENTS_REL2, "short-memory", `${slug}.md`), short);
39159
39276
  }
39160
39277
  const long = byPath.get("long-memory.md");
39161
39278
  if (long) {
39162
- await mkdir8(join24(root, AGENTS_REL2, "long-memory"), { recursive: true });
39163
- await writeFile8(join24(root, AGENTS_REL2, "long-memory", `${slug}.md`), long);
39279
+ await mkdir9(join24(root, AGENTS_REL2, "long-memory"), { recursive: true });
39280
+ await writeFile9(join24(root, AGENTS_REL2, "long-memory", `${slug}.md`), long);
39164
39281
  }
39165
39282
  } else {
39166
39283
  const base = join24(root, SKILLS_REL2, slug);
39167
39284
  for (const [rel, buf] of byPath) {
39168
39285
  if (rel.includes("..") || rel.startsWith("/")) continue;
39169
39286
  const dest = join24(base, rel);
39170
- await mkdir8(dirname8(dest), { recursive: true });
39171
- await writeFile8(dest, buf);
39287
+ await mkdir9(dirname9(dest), { recursive: true });
39288
+ await writeFile9(dest, buf);
39172
39289
  }
39173
39290
  }
39174
39291
  }
@@ -39247,8 +39364,8 @@ async function removePackage(root, slug) {
39247
39364
  }
39248
39365
 
39249
39366
  // src/core/graph.ts
39250
- import { readFile as readFile10, readdir as readdir6 } from "fs/promises";
39251
- import { join as join25, relative as relative2, dirname as dirname9, resolve as resolve8, extname, basename as basename5 } from "path";
39367
+ import { readFile as readFile11, readdir as readdir6 } from "fs/promises";
39368
+ import { join as join25, relative as relative2, dirname as dirname10, resolve as resolve9, extname as extname2, basename as basename6 } from "path";
39252
39369
  var MAX_FILES = 2e3;
39253
39370
  var MAX_NODES = 3e3;
39254
39371
  var SKIP_DIRS = /* @__PURE__ */ new Set(["node_modules", ".git", "dist", "build", ".next", "out", "coverage", ".turbo"]);
@@ -39284,11 +39401,11 @@ function orphansOf(nodes, edges) {
39284
39401
  return nodes.filter((n) => !hasInbound.has(n.id)).map((n) => n.id);
39285
39402
  }
39286
39403
  async function buildDocs(root) {
39287
- const files = await walk(root, (p) => extname(p) === ".md");
39404
+ const files = await walk(root, (p) => extname2(p) === ".md");
39288
39405
  const ids = new Set(files.map((f) => relative2(root, f).split("\\").join("/")));
39289
39406
  const nodes = files.map((f) => {
39290
39407
  const rel = relative2(root, f).split("\\").join("/");
39291
- return { id: rel, label: basename5(rel), kind: "doc", file: rel };
39408
+ return { id: rel, label: basename6(rel), kind: "doc", file: rel };
39292
39409
  });
39293
39410
  const edges = [];
39294
39411
  const seen = /* @__PURE__ */ new Set();
@@ -39296,14 +39413,14 @@ async function buildDocs(root) {
39296
39413
  const rel = relative2(root, f).split("\\").join("/");
39297
39414
  let text = "";
39298
39415
  try {
39299
- text = await readFile10(f, "utf8");
39416
+ text = await readFile11(f, "utf8");
39300
39417
  } catch {
39301
39418
  continue;
39302
39419
  }
39303
39420
  for (const m of text.matchAll(/\[[^\]]*\]\(([^)]+)\)/g)) {
39304
39421
  const href = (m[1] ?? "").split("#")[0].trim();
39305
39422
  if (!href || !href.endsWith(".md") || href.startsWith("http")) continue;
39306
- const target = relative2(root, resolve8(dirname9(f), href)).split("\\").join("/");
39423
+ const target = relative2(root, resolve9(dirname10(f), href)).split("\\").join("/");
39307
39424
  if (ids.has(target) && target !== rel) {
39308
39425
  const key = `${rel}->${target}`;
39309
39426
  if (!seen.has(key)) {
@@ -39326,7 +39443,7 @@ var DEF_PATTERNS = [
39326
39443
  // Go
39327
39444
  ];
39328
39445
  async function buildCode(root) {
39329
- const files = await walk(root, (p) => CODE_EXT.has(extname(p)));
39446
+ const files = await walk(root, (p) => CODE_EXT.has(extname2(p)));
39330
39447
  const nodes = [];
39331
39448
  const nameToIds = /* @__PURE__ */ new Map();
39332
39449
  const fileDefs = /* @__PURE__ */ new Map();
@@ -39335,7 +39452,7 @@ async function buildCode(root) {
39335
39452
  const rel = relative2(root, f).split("\\").join("/");
39336
39453
  let text = "";
39337
39454
  try {
39338
- text = await readFile10(f, "utf8");
39455
+ text = await readFile11(f, "utf8");
39339
39456
  } catch {
39340
39457
  continue;
39341
39458
  }
@@ -39387,7 +39504,7 @@ async function buildGraph(root, mode) {
39387
39504
  }
39388
39505
 
39389
39506
  // src/core/rag.ts
39390
- import { readFile as readFile11, writeFile as writeFile9, statfs as statfs2, mkdir as mkdir9 } from "fs/promises";
39507
+ import { readFile as readFile12, writeFile as writeFile10, statfs as statfs2, mkdir as mkdir10 } from "fs/promises";
39391
39508
  import { existsSync as existsSync13 } from "fs";
39392
39509
  import { execFile as execFile10, spawn as spawn9 } from "child_process";
39393
39510
  import { totalmem as totalmem2, cpus as cpus2 } from "os";
@@ -39412,7 +39529,7 @@ async function detectPython() {
39412
39529
  }
39413
39530
  async function installLog(root) {
39414
39531
  try {
39415
- const text = await readFile11(join26(root, RAG_REL, "install.log"), "utf8");
39532
+ const text = await readFile12(join26(root, RAG_REL, "install.log"), "utf8");
39416
39533
  return text.split("\n").filter((l) => l.length > 0).slice(-200);
39417
39534
  } catch {
39418
39535
  return [];
@@ -39474,7 +39591,7 @@ async function ragStatus(root) {
39474
39591
  };
39475
39592
  let modelName = "";
39476
39593
  try {
39477
- modelName = (await readFile11(join26(root, RAG_REL, ".installed"), "utf8")).trim();
39594
+ modelName = (await readFile12(join26(root, RAG_REL, ".installed"), "utf8")).trim();
39478
39595
  } catch {
39479
39596
  modelName = "";
39480
39597
  }
@@ -39494,7 +39611,7 @@ async function ragStatus(root) {
39494
39611
  async function readIndexMeta(root) {
39495
39612
  const indexing = existsSync13(join26(root, RAG_REL, ".indexing"));
39496
39613
  try {
39497
- const m = JSON.parse(await readFile11(join26(root, RAG_REL, ".index.json"), "utf8"));
39614
+ const m = JSON.parse(await readFile12(join26(root, RAG_REL, ".index.json"), "utf8"));
39498
39615
  return {
39499
39616
  present: true,
39500
39617
  indexing,
@@ -39561,8 +39678,8 @@ if __name__ == "__main__":
39561
39678
  elif cmd == "query": query(sys.argv[2], int(sys.argv[3]) if len(sys.argv) > 3 else 8)
39562
39679
  `;
39563
39680
  async function ensureEngine(root) {
39564
- await mkdir9(join26(root, RAG_REL), { recursive: true }).catch(() => void 0);
39565
- await writeFile9(join26(root, RAG_REL, "rag_engine.py"), RAG_ENGINE_PY, "utf8");
39681
+ await mkdir10(join26(root, RAG_REL), { recursive: true }).catch(() => void 0);
39682
+ await writeFile10(join26(root, RAG_REL, "rag_engine.py"), RAG_ENGINE_PY, "utf8");
39566
39683
  }
39567
39684
  async function ragReindex(root) {
39568
39685
  const py = await detectPython();
@@ -39610,7 +39727,7 @@ async function ragInstall(root, model) {
39610
39727
  if (!py.found) return { ok: false, started: false, error: "python3 not found on the worker" };
39611
39728
  if (existsSync13(join26(root, RAG_REL, ".installing"))) return { ok: true, started: true };
39612
39729
  try {
39613
- await mkdir9(join26(root, RAG_REL), { recursive: true });
39730
+ await mkdir10(join26(root, RAG_REL), { recursive: true });
39614
39731
  } catch {
39615
39732
  }
39616
39733
  const script = `
@@ -40118,14 +40235,14 @@ var WsClient = class {
40118
40235
  */
40119
40236
  awaitConnected(timeoutMs) {
40120
40237
  if (this.sessionKey && this.bus.status === "connected") return Promise.resolve(true);
40121
- return new Promise((resolve9) => {
40238
+ return new Promise((resolve10) => {
40122
40239
  const waiter = () => {
40123
40240
  clearTimeout(timer);
40124
- resolve9(true);
40241
+ resolve10(true);
40125
40242
  };
40126
40243
  const timer = setTimeout(() => {
40127
40244
  this.connectWaiters = this.connectWaiters.filter((w) => w !== waiter);
40128
- resolve9(false);
40245
+ resolve10(false);
40129
40246
  }, timeoutMs);
40130
40247
  this.connectWaiters.push(waiter);
40131
40248
  });
@@ -40152,16 +40269,16 @@ var WsClient = class {
40152
40269
  this.forceReconnect = false;
40153
40270
  return Promise.resolve();
40154
40271
  }
40155
- return new Promise((resolve9) => {
40272
+ return new Promise((resolve10) => {
40156
40273
  const timer = setTimeout(() => {
40157
40274
  this.wakeReconnect = null;
40158
- resolve9();
40275
+ resolve10();
40159
40276
  }, ms);
40160
40277
  this.wakeReconnect = () => {
40161
40278
  clearTimeout(timer);
40162
40279
  this.wakeReconnect = null;
40163
40280
  this.forceReconnect = false;
40164
- resolve9();
40281
+ resolve10();
40165
40282
  };
40166
40283
  });
40167
40284
  }
@@ -40215,7 +40332,7 @@ var WsClient = class {
40215
40332
  * One WS session: token → connect → handshake → handle messages until close.
40216
40333
  */
40217
40334
  connectOnce() {
40218
- return new Promise((resolve9, reject) => {
40335
+ return new Promise((resolve10, reject) => {
40219
40336
  void (async () => {
40220
40337
  this.sessionEstablished = false;
40221
40338
  this.bus.setStatus("connecting");
@@ -40309,7 +40426,7 @@ var WsClient = class {
40309
40426
  if (code === CLOSE_DRAINING) {
40310
40427
  this.bus.log(t("error.serverDraining"));
40311
40428
  }
40312
- resolve9();
40429
+ resolve10();
40313
40430
  });
40314
40431
  socket.on("error", (err) => {
40315
40432
  this.clearHeartbeat();
@@ -40435,7 +40552,7 @@ var WsClient = class {
40435
40552
  * Used for quota.check before spawning an AI cli (ADR-0020).
40436
40553
  */
40437
40554
  request(channel, data) {
40438
- return new Promise((resolve9, reject) => {
40555
+ return new Promise((resolve10, reject) => {
40439
40556
  if (!this.socket || !this.sessionKey) {
40440
40557
  reject(new Error("Not connected to the server."));
40441
40558
  return;
@@ -40455,7 +40572,7 @@ var WsClient = class {
40455
40572
  }, 15e3);
40456
40573
  timer.unref?.();
40457
40574
  this.pending.set(envelope.id, {
40458
- resolve: (value) => resolve9(value),
40575
+ resolve: (value) => resolve10(value),
40459
40576
  timer
40460
40577
  });
40461
40578
  this.socket.send(JSON.stringify(envelope));
@@ -40581,7 +40698,7 @@ var WsClient = class {
40581
40698
  const working = getWorkingProfile(this.context.profileDir, aiCli2);
40582
40699
  const configured = claudeHomeDirs(config);
40583
40700
  const dirs = working ? [working, ...configured.filter((d) => d !== working)] : configured;
40584
- const profile = working ? basename6(working) : dirs[0] ? basename6(dirs[0]) : "default";
40701
+ const profile = working ? basename7(working) : dirs[0] ? basename7(dirs[0]) : "default";
40585
40702
  const api = await checkClaudeUsage(dirs, aiCli2);
40586
40703
  const snapshot = api ?? {
40587
40704
  plan: "?",
@@ -46490,8 +46607,8 @@ var Ink = class {
46490
46607
  }
46491
46608
  }
46492
46609
  async waitUntilExit() {
46493
- this.exitPromise ||= new Promise((resolve9, reject) => {
46494
- this.resolveExitPromise = resolve9;
46610
+ this.exitPromise ||= new Promise((resolve10, reject) => {
46611
+ this.resolveExitPromise = resolve10;
46495
46612
  this.rejectExitPromise = reject;
46496
46613
  });
46497
46614
  return this.exitPromise;
@@ -47544,7 +47661,7 @@ async function runStart(profileDir2, profileName) {
47544
47661
  logger.error("ws.run.crash", { message: e.message, stack: e.stack });
47545
47662
  if (client.isStopped) return;
47546
47663
  bus.log(t("start.recovered", { message: e.message }), "error");
47547
- await new Promise((resolve9) => setTimeout(resolve9, 1e3));
47664
+ await new Promise((resolve10) => setTimeout(resolve10, 1e3));
47548
47665
  }
47549
47666
  }
47550
47667
  };
@@ -47590,7 +47707,7 @@ import { join as join33 } from "path";
47590
47707
  // src/core/control-client.ts
47591
47708
  import { connect as connect2 } from "net";
47592
47709
  function connectControl(socketPath, bus) {
47593
- return new Promise((resolve9, reject) => {
47710
+ return new Promise((resolve10, reject) => {
47594
47711
  const socket = connect2(socketPath);
47595
47712
  socket.setEncoding("utf8");
47596
47713
  let ready = false;
@@ -47637,7 +47754,7 @@ function connectControl(socketPath, bus) {
47637
47754
  bus.setTokens(frame.tokens);
47638
47755
  for (const entry of frame.transcript) bus.pushEntry(entry);
47639
47756
  ready = true;
47640
- resolve9({ info: frame.info, close });
47757
+ resolve10({ info: frame.info, close });
47641
47758
  break;
47642
47759
  case "transcript":
47643
47760
  bus.pushEntry(frame.entry);
@@ -47717,18 +47834,18 @@ async function runAttach(profileDir2, profileName) {
47717
47834
  // src/commands/ai-login.ts
47718
47835
  import { spawn as spawn11 } from "child_process";
47719
47836
  import { mkdirSync as mkdirSync8 } from "fs";
47720
- import { basename as basename7 } from "path";
47837
+ import { basename as basename8 } from "path";
47721
47838
  function runProviderLogin(cmd, envVar, dir2) {
47722
- return new Promise((resolve9) => {
47839
+ return new Promise((resolve10) => {
47723
47840
  const child = spawn11(cmd, [], {
47724
47841
  stdio: "inherit",
47725
47842
  env: { ...process.env, [envVar]: dir2 }
47726
47843
  });
47727
47844
  child.on("error", (err) => {
47728
47845
  console.error(t("aiLogin.launchFailed", { cmd, message: err.message }));
47729
- resolve9(1);
47846
+ resolve10(1);
47730
47847
  });
47731
- child.on("exit", (code) => resolve9(code ?? 0));
47848
+ child.on("exit", (code) => resolve10(code ?? 0));
47732
47849
  });
47733
47850
  }
47734
47851
  async function runAiLogin(profileDir2, profileName, aiFilter) {
@@ -47740,7 +47857,7 @@ async function runAiLogin(profileDir2, profileName, aiFilter) {
47740
47857
  return;
47741
47858
  }
47742
47859
  const selected = aiFilter ? credentials.filter(
47743
- (c, i) => c.profile === aiFilter || basename7(resolveHomePath(c.profile)) === aiFilter || String(i + 1) === aiFilter
47860
+ (c, i) => c.profile === aiFilter || basename8(resolveHomePath(c.profile)) === aiFilter || String(i + 1) === aiFilter
47744
47861
  ) : credentials;
47745
47862
  if (selected.length === 0) {
47746
47863
  console.log(t("aiLogin.noMatch", { filter: aiFilter ?? "", list: credentials.map((c) => c.profile).join(", ") }));
@@ -47868,10 +47985,10 @@ function Picker({
47868
47985
  ] });
47869
47986
  }
47870
47987
  function selectFromList(items, title) {
47871
- return new Promise((resolve9) => {
47988
+ return new Promise((resolve10) => {
47872
47989
  let chosen = null;
47873
47990
  const app = render_default(/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Picker, { items, title, onDone: (v) => chosen = v }));
47874
- void app.waitUntilExit().then(() => resolve9(chosen));
47991
+ void app.waitUntilExit().then(() => resolve10(chosen));
47875
47992
  });
47876
47993
  }
47877
47994
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@4pm/cli",
3
- "version": "1.5.37",
3
+ "version": "1.5.40",
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",