@agimon-ai/po-runner 0.0.0-alpha.20 → 0.0.0-alpha.21

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.
@@ -5,14 +5,15 @@ import { n as stopRunnerProcess, t as reconcileActiveRunners } from "../reconcil
5
5
  import { t as SystemClock } from "../clock-Cv2pddgo.mjs";
6
6
  import { t as activeRunnerRecovery } from "../compaction-nNlE6e5I.mjs";
7
7
  import { t as RmuxBackend } from "../rmuxBackend-rjrVTG6K.mjs";
8
- import { n as TmuxBackend, r as PtyBackendChain, t as createRunnerDependencies } from "../runnerDependencies-B0Vj8ZEc.mjs";
8
+ import { n as TERM_GRACE_MS } from "../launcher-CCYsFBM9.mjs";
9
+ import { n as TmuxBackend, r as PtyBackendChain, t as createRunnerDependencies } from "../runnerDependencies-7h_cxOva.mjs";
9
10
  import { n as resolveRunnerStoreDirectory, r as runnerStateDirFor, t as RunnerPaths } from "../runnerPaths-Dibbvyx_.mjs";
10
11
  import { a as formatRunnerStatus, i as formatRunnerFinishedNotice, n as createDefaultProcessRegistry, o as isRunnerRecord, r as formatRunnerFinished } from "../runnerRegistry-BgaR5O86.mjs";
11
12
  import fs from "node:fs";
12
13
  import path from "node:path";
13
14
  import { resolveRootSessionId } from "@agimon-ai/po-core/childProcess";
14
15
  import { composeServerProviderOverrides, defineServerPlugin, packageResourcePath, readPackageResource } from "@agimon-ai/po-core/serverPlugin";
15
- import { composeRootHooks, composeRootInjects, defineChannel, defineHook, defineResource, defineRoot, defineRoute, defineServerCommand, defineServerTool } from "@agimon-ai/po-core/extensionFile";
16
+ import { composeRootHooks, composeRootInjects, defineChannel, defineHook, defineResource, defineRoot, defineRoute, defineServerCommand, defineServerTool, runCleanups } from "@agimon-ai/po-core/extensionFile";
16
17
  import { PO_BACKGROUND_WORK_SERVICE, readPoBackgroundWorkService } from "@agimon-ai/po-core/backgroundWork";
17
18
  import { createPoTelemetry } from "@agimon-ai/po-telemetry";
18
19
  import { CONFIG_DIR_NAME } from "@earendil-works/pi-coding-agent";
@@ -274,36 +275,36 @@ function createRunnerServerRuntime(container, host, directEvents, wakeAgent, exe
274
275
  await supervision?.catch((error) => process.emitWarning(`Could not initialize headless runner supervision: ${String(error)}`));
275
276
  const ownedSessionId = sessionId;
276
277
  if (ownedSessionId === void 0) return;
277
- const records = await container.runnerRegistry.listBySession(ownedSessionId).catch(() => []);
278
- await Promise.all(records.map(async (record) => {
279
- try {
280
- if (!await stopRunnerProcess(record, container.launcher, container.rmuxBackend, {
281
- registry: container.runnerRegistry,
282
- intent: {
278
+ await runCleanups([
279
+ async () => {
280
+ const records = await container.runnerRegistry.listBySession(ownedSessionId);
281
+ const errors = (await Promise.allSettled(records.map(async (record) => {
282
+ await stopRunnerProcess(record, container.launcher, container.rmuxBackend, {
283
+ registry: container.runnerRegistry,
284
+ intent: {
285
+ reason: "stopped",
286
+ terminationReason: "parent_session_cleanup",
287
+ stopReason: "session ended"
288
+ }
289
+ });
290
+ const deadline = container.clock.now() + TERM_GRACE_MS;
291
+ while (container.processControl.isAlive(record.pid)) {
292
+ if (container.clock.now() >= deadline) throw new Error(`Could not stop runner ${record.id} during session shutdown`);
293
+ await new Promise((resolve) => container.clock.after(100, resolve));
294
+ }
295
+ await container.runnerRegistry.complete(record.id, {
283
296
  reason: "stopped",
284
- terminationReason: "parent_session_cleanup",
297
+ code: null,
298
+ signal: null,
285
299
  stopReason: "session ended"
286
- }
287
- }) && container.processControl.isAlive(record.pid)) {
288
- process.emitWarning(`Could not stop runner ${record.id} during session shutdown`);
289
- return;
290
- }
291
- await container.runnerRegistry.complete(record.id, {
292
- reason: "stopped",
293
- code: null,
294
- signal: null,
295
- stopReason: "session ended"
296
- }, ownedSessionId);
297
- } catch (error) {
298
- process.emitWarning(`Could not clean up runner ${record.id}: ${String(error)}`);
299
- }
300
- }));
301
- try {
302
- await container.ptyHost.disposeAll();
303
- } finally {
304
- container.lifeline.dispose();
305
- container.runnerRegistry.close();
306
- }
300
+ }, ownedSessionId);
301
+ }))).filter((result) => result.status === "rejected").map((result) => result.reason);
302
+ if (errors.length) throw new AggregateError(errors, "Runner process cleanup failed.");
303
+ },
304
+ () => container.ptyHost.disposeAll(),
305
+ () => container.lifeline.dispose(),
306
+ () => container.runnerRegistry.close()
307
+ ], "Runner runtime cleanup failed.");
307
308
  })();
308
309
  return runtimeDisposal;
309
310
  };
@@ -505,9 +506,11 @@ function createRunnerServerRuntime(container, host, directEvents, wakeAgent, exe
505
506
  } catch (error) {
506
507
  process.emitWarning(`Could not clear runner status: ${String(error)}`);
507
508
  }
508
- await disposeRuntime();
509
- await telemetry?.recordEvent("po_runner.session_finished", { outcome: "stopped" });
510
- await telemetry?.shutdown();
509
+ await runCleanups([
510
+ disposeRuntime,
511
+ () => telemetry?.recordEvent("po_runner.session_finished", { outcome: "stopped" }),
512
+ () => telemetry?.shutdown()
513
+ ], "Runner shutdown failed.");
511
514
  })();
512
515
  return disposal;
513
516
  }