@4pm/cli 1.11.0 → 1.12.1-b

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 +55 -13
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -32543,16 +32543,48 @@ function readInstalledVersion() {
32543
32543
  return "0.0.0";
32544
32544
  }
32545
32545
  }
32546
+ var NPM_INSTALL_TIMEOUT_MS = 18e4;
32547
+ var DOWNLOAD_TIMEOUT_MS = 6e4;
32548
+ function tailReason(raw) {
32549
+ const s3 = raw.trim();
32550
+ return s3.length > 800 ? `\u2026${s3.slice(-800)}` : s3;
32551
+ }
32546
32552
  function updateViaNpm(version) {
32547
32553
  if (!/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/.test(version)) {
32548
32554
  throw new Error(`Refusing to update: invalid version string "${version}".`);
32549
32555
  }
32550
- execSync2(`npm i -g @4pm/cli@${version}`, { stdio: "inherit" });
32556
+ try {
32557
+ execSync2(`npm i -g @4pm/cli@${version}`, {
32558
+ stdio: ["ignore", "pipe", "pipe"],
32559
+ encoding: "utf8",
32560
+ timeout: NPM_INSTALL_TIMEOUT_MS
32561
+ });
32562
+ } catch (err) {
32563
+ const e = err;
32564
+ if (e.killed) {
32565
+ throw new Error(`npm install timed out after ${NPM_INSTALL_TIMEOUT_MS / 1e3}s (\`npm i -g @4pm/cli@${version}\`).`);
32566
+ }
32567
+ const out = `${e.stderr?.toString() ?? ""}
32568
+ ${e.stdout?.toString() ?? ""}`;
32569
+ const reason = tailReason(out) || e.message || "npm install failed";
32570
+ throw new Error(`npm install failed: ${reason}`);
32571
+ }
32551
32572
  }
32552
32573
  async function updateViaDownload(tarballUrl, checksum, signature) {
32553
- const res = await fetch(tarballUrl);
32554
- if (!res.ok) throw new Error(`Failed to download tarball: HTTP ${res.status}`);
32555
- const buf = Buffer.from(await res.arrayBuffer());
32574
+ const controller = new AbortController();
32575
+ const timer = setTimeout(() => controller.abort(), DOWNLOAD_TIMEOUT_MS);
32576
+ let buf;
32577
+ try {
32578
+ const res = await fetch(tarballUrl, { signal: controller.signal });
32579
+ if (!res.ok) throw new Error(`Failed to download tarball: HTTP ${res.status}`);
32580
+ buf = Buffer.from(await res.arrayBuffer());
32581
+ } catch (err) {
32582
+ throw new Error(
32583
+ controller.signal.aborted ? `Downloading the update tarball timed out after ${DOWNLOAD_TIMEOUT_MS / 1e3}s.` : `Failed to download tarball: ${String(err)}`
32584
+ );
32585
+ } finally {
32586
+ clearTimeout(timer);
32587
+ }
32556
32588
  const actual = createHash2("sha256").update(buf).digest("hex");
32557
32589
  if (actual !== checksum) {
32558
32590
  throw new Error("Tarball checksum mismatch \u2014 aborting update (ADR-0015).");
@@ -37623,8 +37655,20 @@ async function writeTemplateMarker(target) {
37623
37655
  const marker = { templateVersion: PROJECT_TEMPLATE.version, scaffoldedAt: (/* @__PURE__ */ new Date()).toISOString() };
37624
37656
  await writeFile(join6(dir2, ".4pm.json"), JSON.stringify(marker, null, 2) + "\n", "utf8");
37625
37657
  }
37658
+ function readSpecField(spec, key) {
37659
+ const fields = spec.fields;
37660
+ if (Array.isArray(fields)) {
37661
+ const f2 = fields.find(
37662
+ (x) => !!x && typeof x.id === "string" && x.id === key
37663
+ );
37664
+ if (f2 && typeof f2.value === "string") return f2.value;
37665
+ }
37666
+ return typeof spec[key] === "string" ? spec[key] : "";
37667
+ }
37626
37668
  async function aiInit(target, spec, emit) {
37627
- emit("ai-init", "AI init: subagents, README, CLAUDE.md\u2026");
37669
+ const guideFile = readSpecField(spec, "ai_guide_file") === "AGENT.md" ? "AGENT.md" : "CLAUDE.md";
37670
+ const guideInstructions = readSpecField(spec, "ai_guide_instructions").trim();
37671
+ emit("ai-init", `AI init: subagents, README, ${guideFile}\u2026`);
37628
37672
  const subagents = Array.isArray(spec.subagents) ? spec.subagents : [];
37629
37673
  if (subagents.length > 0) {
37630
37674
  await mkdir(join6(target, ".claude", "agents"), { recursive: true });
@@ -37647,14 +37691,12 @@ ${(sa.description || "").trim()}
37647
37691
  ${specJson}`
37648
37692
  );
37649
37693
  await generateFile(
37650
- join6(target, "CLAUDE.md"),
37651
- `Write a CLAUDE.md (Markdown only, no preamble) with guidance/conventions for AI agents working in this project, derived from its spec JSON:
37652
- ${specJson}`
37653
- );
37654
- await generateFile(
37655
- join6(target, "AGENT.md"),
37656
- `Write an AGENT.md (Markdown only, no preamble) with guidance/conventions for AI agents working in this project, derived from its spec JSON:
37657
- ${specJson}`
37694
+ join6(target, guideFile),
37695
+ `Write a ${guideFile} (Markdown only, no preamble) with guidance/conventions for AI agents working in this project, derived from its spec JSON:
37696
+ ${specJson}` + (guideInstructions ? `
37697
+ Also incorporate these additional instructions/content:
37698
+ ${guideInstructions}
37699
+ ` : "")
37658
37700
  );
37659
37701
  }
37660
37702
  async function generateFile(path, prompt) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@4pm/cli",
3
- "version": "1.11.0",
3
+ "version": "1.12.1b",
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",