@proagentstore/cli 0.4.36 → 0.4.37

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.
@@ -225,12 +225,35 @@ export class CodingRuntime {
225
225
  isUnderTakeover(sessionId) {
226
226
  return this.takeovers.has(sessionId);
227
227
  }
228
- /** Stop every session (runner shutdown). */
228
+ /**
229
+ * Stop every session (runner shutdown).
230
+ *
231
+ * Each `stop()` is isolated (#274 lineage). `stop()` kills a child process, and killing an
232
+ * already-dead or wedged one throws — so a single bad session used to abort the loop, leaving
233
+ * every LATER session's engine running and skipping `sessions.clear()` entirely. The caller
234
+ * (`LocalRunner.close`) wraps this in a `catch {}`, so that escape was silent: the runner
235
+ * reported a clean shutdown while orphaned CLI processes kept editing the user's repo with
236
+ * nothing left holding their ids. Same shape as the `browserContext.close()` leak — a throw
237
+ * on the teardown path is what MAKES the leak, so every session is stopped independently and
238
+ * the maps always clear.
239
+ */
229
240
  closeAll() {
230
- for (const s of this.sessions.values())
231
- s.stop();
241
+ const failures = [];
242
+ for (const s of this.sessions.values()) {
243
+ try {
244
+ s.stop();
245
+ }
246
+ catch (e) {
247
+ failures.push(e);
248
+ }
249
+ }
232
250
  this.sessions.clear();
233
251
  this.takeovers.clear();
252
+ if (failures.length) {
253
+ // Cleared the state, then report: teardown completed as far as it could, but the
254
+ // operator needs to know a child process may have survived it.
255
+ throw new AggregateError(failures, `${failures.length} coding session(s) failed to stop`);
256
+ }
234
257
  }
235
258
  /** True if any session this runtime owns still has a live agent process. */
236
259
  hasLiveSessions() {
@@ -193,8 +193,12 @@ export class LocalRunner {
193
193
  try {
194
194
  this.coding.closeAll();
195
195
  }
196
- catch {
197
- // a stuck coding session must not block the browser teardown below
196
+ catch (e) {
197
+ // A stuck coding session must not block the browser teardown below — but it must not
198
+ // vanish either. `closeAll` now stops every session independently and only throws to
199
+ // report which ones refused, so reaching here means a child process may have outlived
200
+ // the runner. Silence here is what let that read as a clean shutdown.
201
+ console.warn(`[runner] ${e instanceof Error ? e.message : String(e)} — a CLI process may still be running; check \`ps\` if a repo keeps changing`);
198
202
  }
199
203
  await this.mcp?.stop().catch(() => undefined);
200
204
  this.mcp = null;
package/dist/index.js CHANGED
@@ -533,7 +533,14 @@ var publishCommand = new Command5("publish").description("Publish an agent to Pr
533
533
  writeError("No agent.json found. Run `pags init` first.");
534
534
  process.exit(1);
535
535
  }
536
- const manifest = JSON.parse(readFileSync3(manifestPath, "utf-8"));
536
+ let manifest;
537
+ try {
538
+ manifest = JSON.parse(readFileSync3(manifestPath, "utf-8"));
539
+ } catch (e) {
540
+ writeError(`agent.json is not valid JSON: ${e instanceof Error ? e.message : String(e)}`);
541
+ process.exit(1);
542
+ return;
543
+ }
537
544
  const slug = manifest.id;
538
545
  if (!slug) {
539
546
  writeError("agent.json missing id");
@@ -592,8 +599,12 @@ var publishCommand = new Command5("publish").description("Publish an agent to Pr
592
599
  cwd: dir,
593
600
  stdio: "inherit"
594
601
  });
595
- } catch {
596
- writeLine(" Push skipped (up to date or no commits)");
602
+ } catch (e) {
603
+ writeError(`
604
+ Push failed: ${e instanceof Error ? e.message : String(e)}`);
605
+ writeError(" Nothing was published \u2014 fix the push (pull/rebase, or check your GitHub auth) and retry.\n");
606
+ process.exit(1);
607
+ return;
597
608
  }
598
609
  }
599
610
  writeLine("\n Registering agent in store...");
@@ -874,10 +885,23 @@ async function connectViaRelay(instanceIds, localUrl, runnerToken, opts, force =
874
885
  writeLine(` Agents: ${instanceIds.length} instance${instanceIds.length === 1 ? "" : "s"}`);
875
886
  writeLine(" No cloudflared needed. Ctrl+C to disconnect.");
876
887
  writeLine("\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550");
888
+ let heartbeatFailing = false;
877
889
  const heartbeat = () => {
878
890
  const timer = setTimeout(async () => {
891
+ let failure = null;
879
892
  for (const id of [...attached.keys()]) {
880
- await requestPags("POST", `/v1/instances/${apiPathSegment(id)}/runtime/heartbeat`, opts, { runnerNode }).catch(() => void 0);
893
+ try {
894
+ await requestPags("POST", `/v1/instances/${apiPathSegment(id)}/runtime/heartbeat`, opts, { runnerNode });
895
+ } catch (e) {
896
+ failure = e instanceof Error ? e.message : String(e);
897
+ }
898
+ }
899
+ if (failure && !heartbeatFailing) {
900
+ heartbeatFailing = true;
901
+ writeError(`Heartbeat failed: ${failure} \u2014 the console will show this machine as OFFLINE until it recovers. The relay itself is still connected; don't run \`pags up --force\` elsewhere.`);
902
+ } else if (!failure && heartbeatFailing) {
903
+ heartbeatFailing = false;
904
+ writeLine("Heartbeat recovered \u2014 this machine reads as online again.");
881
905
  }
882
906
  heartbeat();
883
907
  }, 3e4);
@@ -1499,7 +1523,10 @@ var upCommand = new Command7("up").description("Start the browser runner for all
1499
1523
  stdio: "inherit",
1500
1524
  env: process.env
1501
1525
  });
1502
- } catch {
1526
+ } catch (e) {
1527
+ const status = e.status;
1528
+ writeLine(` Restart failed${typeof status === "number" ? ` (exit ${status})` : ""} \u2014 the runner is NOT running. Run 'pags up' again.`);
1529
+ process.exit(typeof status === "number" && status !== 0 ? status : 1);
1503
1530
  }
1504
1531
  process.exit(0);
1505
1532
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@proagentstore/cli",
3
- "version": "0.4.36",
3
+ "version": "0.4.37",
4
4
  "description": "CLI for creating, publishing, and running ProAgentStore agents",
5
5
  "license": "MIT",
6
6
  "type": "module",