@agimon-ai/po-team 0.0.0-alpha.2 → 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.
Files changed (120) hide show
  1. package/LICENSE +166 -5
  2. package/README.md +11 -12
  3. package/dist/{agentDiscovery-Whwzc4dP.cjs → agentDiscovery-DTTlM_LT.cjs} +246 -350
  4. package/dist/agentDiscovery-DTTlM_LT.cjs.map +1 -0
  5. package/dist/{agentDiscovery-ZQlFkKvB.mjs → agentDiscovery-ZNG8iZXV.mjs} +210 -279
  6. package/dist/agentDiscovery-ZNG8iZXV.mjs.map +1 -0
  7. package/dist/apiContracts.cjs +10 -3
  8. package/dist/apiContracts.cjs.map +1 -1
  9. package/dist/apiContracts.d.mts.map +1 -1
  10. package/dist/apiContracts.mjs +10 -3
  11. package/dist/apiContracts.mjs.map +1 -1
  12. package/dist/{externalProcessIpc-ojE0pvw0.cjs → atomicJson-DRT03Ql5.cjs} +155 -21
  13. package/dist/atomicJson-DRT03Ql5.cjs.map +1 -0
  14. package/dist/{externalProcessIpc-C-15lJrB.mjs → atomicJson-VVM1iAPu.mjs} +140 -12
  15. package/dist/atomicJson-VVM1iAPu.mjs.map +1 -0
  16. package/dist/{capabilityCeiling-CF7kAS18.mjs → capabilityCeiling-BaHT9v9S.mjs} +3 -3
  17. package/dist/capabilityCeiling-BaHT9v9S.mjs.map +1 -0
  18. package/dist/{capabilityCeiling-C-Y7H8oC.cjs → capabilityCeiling-CO3ZjYmY.cjs} +3 -3
  19. package/dist/capabilityCeiling-CO3ZjYmY.cjs.map +1 -0
  20. package/dist/capabilityCeiling.cjs +2 -2
  21. package/dist/capabilityCeiling.d.mts +2 -2
  22. package/dist/capabilityCeiling.mjs +2 -2
  23. package/dist/delegation.cjs +1 -1
  24. package/dist/delegation.cjs.map +1 -1
  25. package/dist/delegation.d.mts +1 -1
  26. package/dist/delegation.mjs +1 -1
  27. package/dist/delegation.mjs.map +1 -1
  28. package/dist/delegationApi.cjs +30 -30
  29. package/dist/delegationApi.d.mts +2 -2
  30. package/dist/delegationApi.mjs +1 -2
  31. package/dist/env.cjs +1 -1
  32. package/dist/env.d.mts +1 -1
  33. package/dist/env.mjs +1 -2
  34. package/dist/{environment-DrqhrxG_.mjs → environment-BtvJI2S-.mjs} +3 -3
  35. package/dist/environment-BtvJI2S-.mjs.map +1 -0
  36. package/dist/{environment-ma5oQ7uM.d.mts → environment-Bz1OlWIT.d.mts} +2 -2
  37. package/dist/{environment-ma5oQ7uM.d.mts.map → environment-Bz1OlWIT.d.mts.map} +1 -1
  38. package/dist/{environment-CaCW3SgT.cjs → environment-Cqs7vHJL.cjs} +3 -3
  39. package/dist/environment-Cqs7vHJL.cjs.map +1 -0
  40. package/dist/extensions/native.mjs +34 -12
  41. package/dist/extensions/native.mjs.map +1 -1
  42. package/dist/extensions/server.cjs +990 -786
  43. package/dist/extensions/server.cjs.map +1 -1
  44. package/dist/extensions/server.d.mts +2 -2
  45. package/dist/extensions/server.d.mts.map +1 -1
  46. package/dist/extensions/server.mjs +975 -772
  47. package/dist/extensions/server.mjs.map +1 -1
  48. package/dist/extensions/web.mjs +994 -807
  49. package/dist/extensions/web.mjs.map +1 -1
  50. package/dist/fablePlan.cjs +3 -3
  51. package/dist/fablePlan.d.mts +2 -2
  52. package/dist/fablePlan.mjs +1 -2
  53. package/dist/{fablePlanApi-CZ3uUcMi.d.mts → fablePlanApi-BTNKjLni.d.mts} +6 -6
  54. package/dist/{fablePlanApi-CZ3uUcMi.d.mts.map → fablePlanApi-BTNKjLni.d.mts.map} +1 -1
  55. package/dist/{fablePlanApi-wBu9bRXU.cjs → fablePlanApi-BhI4jnDP.cjs} +12 -12
  56. package/dist/fablePlanApi-BhI4jnDP.cjs.map +1 -0
  57. package/dist/{fablePlanApi-BsHhgVFV.mjs → fablePlanApi-DuMg43Hu.mjs} +5 -5
  58. package/dist/fablePlanApi-DuMg43Hu.mjs.map +1 -0
  59. package/dist/fablePlanApi.cjs +3 -3
  60. package/dist/fablePlanApi.d.mts +2 -2
  61. package/dist/fablePlanApi.mjs +1 -2
  62. package/dist/index.cjs +17 -8
  63. package/dist/index.cjs.map +1 -1
  64. package/dist/index.d.mts +5 -1
  65. package/dist/index.d.mts.map +1 -1
  66. package/dist/index.mjs +15 -5
  67. package/dist/index.mjs.map +1 -1
  68. package/dist/rolldown-runtime-VH7oDXx4.cjs +28 -0
  69. package/dist/runs/background/cliRunnerEntry.cjs +26 -25
  70. package/dist/runs/background/cliRunnerEntry.cjs.map +1 -1
  71. package/dist/runs/background/cliRunnerEntry.mjs +14 -14
  72. package/dist/runs/background/cliRunnerEntry.mjs.map +1 -1
  73. package/dist/runtimeSubagentPolicy.cjs +3 -3
  74. package/dist/runtimeSubagentPolicy.d.mts +2 -2
  75. package/dist/runtimeSubagentPolicy.mjs +1 -2
  76. package/dist/runtimeSubagentTool.cjs +7 -2
  77. package/dist/runtimeSubagentTool.d.mts +1 -1
  78. package/dist/runtimeSubagentTool.mjs +1 -2
  79. package/dist/{subagentPolicy-ALJam4GN.d.mts → subagentPolicy-BE-OZoa-.d.mts} +6 -6
  80. package/dist/subagentPolicy-BE-OZoa-.d.mts.map +1 -0
  81. package/dist/{subagentPolicy-DQRyKDH-.cjs → subagentPolicy-DIpaKHO8.cjs} +8 -8
  82. package/dist/subagentPolicy-DIpaKHO8.cjs.map +1 -0
  83. package/dist/{subagentPolicy-DxjsKeyj.mjs → subagentPolicy-LfcXuqO5.mjs} +5 -5
  84. package/dist/subagentPolicy-LfcXuqO5.mjs.map +1 -0
  85. package/dist/subagentPolicy.cjs +3 -3
  86. package/dist/subagentPolicy.d.mts +2 -2
  87. package/dist/subagentPolicy.mjs +1 -2
  88. package/dist/{subagentTool-Ca2zQXKw.cjs → subagentTool-BueNPGHo.cjs} +5 -16
  89. package/dist/subagentTool-BueNPGHo.cjs.map +1 -0
  90. package/dist/{subagentTool-BTssGLw8.d.mts → subagentTool-UdB3s6Mn.d.mts} +2 -11
  91. package/dist/subagentTool-UdB3s6Mn.d.mts.map +1 -0
  92. package/dist/{subagentTool-WOYrjxgT.mjs → subagentTool-a2oh2v5B.mjs} +5 -16
  93. package/dist/subagentTool-a2oh2v5B.mjs.map +1 -0
  94. package/dist/subagentTool.cjs +7 -2
  95. package/dist/subagentTool.d.mts +1 -1
  96. package/dist/subagentTool.mjs +1 -2
  97. package/dist/teamSnapshot.d.mts +1 -0
  98. package/dist/teamSnapshot.d.mts.map +1 -1
  99. package/dist/teamSnapshot.mjs +1 -2
  100. package/package.json +25 -24
  101. package/dist/agentDiscovery-Whwzc4dP.cjs.map +0 -1
  102. package/dist/agentDiscovery-ZQlFkKvB.mjs.map +0 -1
  103. package/dist/atomicJson-D0346bt5.cjs +0 -178
  104. package/dist/atomicJson-D0346bt5.cjs.map +0 -1
  105. package/dist/atomicJson-D2t0CDh9.mjs +0 -137
  106. package/dist/atomicJson-D2t0CDh9.mjs.map +0 -1
  107. package/dist/capabilityCeiling-C-Y7H8oC.cjs.map +0 -1
  108. package/dist/capabilityCeiling-CF7kAS18.mjs.map +0 -1
  109. package/dist/environment-CaCW3SgT.cjs.map +0 -1
  110. package/dist/environment-DrqhrxG_.mjs.map +0 -1
  111. package/dist/externalProcessIpc-C-15lJrB.mjs.map +0 -1
  112. package/dist/externalProcessIpc-ojE0pvw0.cjs.map +0 -1
  113. package/dist/fablePlanApi-BsHhgVFV.mjs.map +0 -1
  114. package/dist/fablePlanApi-wBu9bRXU.cjs.map +0 -1
  115. package/dist/subagentPolicy-ALJam4GN.d.mts.map +0 -1
  116. package/dist/subagentPolicy-DQRyKDH-.cjs.map +0 -1
  117. package/dist/subagentPolicy-DxjsKeyj.mjs.map +0 -1
  118. package/dist/subagentTool-BTssGLw8.d.mts.map +0 -1
  119. package/dist/subagentTool-Ca2zQXKw.cjs.map +0 -1
  120. package/dist/subagentTool-WOYrjxgT.mjs.map +0 -1
@@ -2,32 +2,33 @@ Object.defineProperties(exports, {
2
2
  __esModule: { value: true },
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
- const require_atomicJson = require("../atomicJson-D0346bt5.cjs");
6
- const require_environment = require("../environment-CaCW3SgT.cjs");
7
- const require_capabilityCeiling = require("../capabilityCeiling-C-Y7H8oC.cjs");
8
- const require_fablePlanApi = require("../fablePlanApi-wBu9bRXU.cjs");
9
- const require_agentDiscovery = require("../agentDiscovery-Whwzc4dP.cjs");
10
- const require_subagentPolicy = require("../subagentPolicy-DQRyKDH-.cjs");
11
- const require_subagentTool = require("../subagentTool-Ca2zQXKw.cjs");
5
+ const require_rolldown_runtime = require("../rolldown-runtime-VH7oDXx4.cjs");
6
+ const require_environment = require("../environment-Cqs7vHJL.cjs");
7
+ const require_capabilityCeiling = require("../capabilityCeiling-CO3ZjYmY.cjs");
8
+ const require_fablePlanApi = require("../fablePlanApi-BhI4jnDP.cjs");
9
+ const require_agentDiscovery = require("../agentDiscovery-DTTlM_LT.cjs");
10
+ const require_subagentPolicy = require("../subagentPolicy-DIpaKHO8.cjs");
11
+ const require_subagentTool = require("../subagentTool-BueNPGHo.cjs");
12
12
  const require_teamSnapshot = require("../teamSnapshot-oKuGFdYc.cjs");
13
- const require_externalProcessIpc = require("../externalProcessIpc-ojE0pvw0.cjs");
13
+ const require_atomicJson = require("../atomicJson-DRT03Ql5.cjs");
14
14
  let node_buffer = require("node:buffer");
15
15
  let _agimon_ai_po_core_childProcess = require("@agimon-ai/po-core/childProcess");
16
16
  let _agimon_ai_po_core_delegation = require("@agimon-ai/po-core/delegation");
17
17
  let typebox = require("typebox");
18
- let node_fs = require("node:fs");
19
- node_fs = require_atomicJson.__toESM(node_fs, 1);
20
18
  let node_path = require("node:path");
21
- node_path = require_atomicJson.__toESM(node_path, 1);
19
+ node_path = require_rolldown_runtime.__toESM(node_path, 1);
20
+ let _agimon_ai_po_core_platform = require("@agimon-ai/po-core/platform");
21
+ let node_fs = require("node:fs");
22
+ node_fs = require_rolldown_runtime.__toESM(node_fs, 1);
22
23
  let node_os = require("node:os");
23
- node_os = require_atomicJson.__toESM(node_os, 1);
24
- let _agimon_ai_po_core_serverFacet = require("@agimon-ai/po-core/serverFacet");
24
+ node_os = require_rolldown_runtime.__toESM(node_os, 1);
25
+ let _agimon_ai_po_core_serverPlugin = require("@agimon-ai/po-core/serverPlugin");
25
26
  let _agimon_ai_po_core_extensionFile = require("@agimon-ai/po-core/extensionFile");
27
+ let _agimon_ai_po_config = require("@agimon-ai/po-config");
26
28
  let _agimon_ai_po_core_backgroundWork = require("@agimon-ai/po-core/backgroundWork");
27
29
  let _agimon_ai_po_core_childSession = require("@agimon-ai/po-core/childSession");
28
30
  let _agimon_ai_po_core_contextContributions = require("@agimon-ai/po-core/contextContributions");
29
31
  let _agimon_ai_po_core_mcpToolResolver = require("@agimon-ai/po-core/mcpToolResolver");
30
- let _agimon_ai_po_core_readiness = require("@agimon-ai/po-core/readiness");
31
32
  let _agimon_ai_po_session = require("@agimon-ai/po-session");
32
33
  let _agimon_ai_po_telemetry = require("@agimon-ai/po-telemetry");
33
34
  let typebox_value = require("typebox/value");
@@ -35,7 +36,9 @@ let node_crypto = require("node:crypto");
35
36
  let node_child_process = require("node:child_process");
36
37
  let node_url = require("node:url");
37
38
  let _agimon_ai_po_core_headless = require("@agimon-ai/po-core/headless");
39
+ let _agimon_ai_po_config_majorModes = require("@agimon-ai/po-config/majorModes");
38
40
  require("@agimon-ai/po-core/cordisHost");
41
+ let _agimon_ai_po_core_hubChannel = require("@agimon-ai/po-core/hubChannel");
39
42
  //#region src/services/config/index.ts
40
43
  /**
41
44
  * `subagent` tool config file: read/write, and the scoped `ExtensionConfig`
@@ -177,13 +180,13 @@ var AdmissionGate = class {
177
180
  }
178
181
  if (!waited) {
179
182
  waited = true;
180
- request.report?.("doom_team.admission_wait", {
183
+ request.report?.("po_team.admission_wait", {
181
184
  "team.live_runs": live,
182
185
  "team.max_live_runs": request.maxLiveRuns
183
186
  });
184
187
  }
185
188
  if (this.now() >= deadline) {
186
- request.report?.("doom_team.admission_timeout", {
189
+ request.report?.("po_team.admission_timeout", {
187
190
  "team.live_runs": live,
188
191
  "team.max_live_runs": request.maxLiveRuns,
189
192
  duration_ms: this.now() - waitStartedAt
@@ -420,7 +423,7 @@ const AGENT_NAMES = Object.freeze([
420
423
  "fabia"
421
424
  ]);
422
425
  function agentIdentitiesDir(scope) {
423
- return node_path.join(require_externalProcessIpc.sessionScopeDir(scope), IDENTITIES_DIR_NAME);
426
+ return node_path.join(require_atomicJson.sessionScopeDir(scope), IDENTITIES_DIR_NAME);
424
427
  }
425
428
  /**
426
429
  * The role an identity advertises, taken from the last segment of the agent
@@ -515,26 +518,6 @@ function claimAgentIdentity(scope, input) {
515
518
  }
516
519
  return degraded;
517
520
  }
518
- /**
519
- * Point an existing identity at a new run id.
520
- *
521
- * Restore mints a fresh run id for what is conceptually the same agent, so the
522
- * identity has to be carried across rather than derived again. This is a
523
- * single-writer rewrite of one claim, so the lost-update hazard that rules out
524
- * a shared registry file does not apply.
525
- */
526
- function adoptAgentIdentity(scope, identity, runId) {
527
- const file = node_path.join(agentIdentitiesDir(scope), `${identity}.json`);
528
- const existing = readClaim(file);
529
- if (!existing) return;
530
- try {
531
- node_fs.writeFileSync(file, `${JSON.stringify({
532
- ...existing,
533
- runId,
534
- claimedAt: Date.now()
535
- })}\n`, { mode: 384 });
536
- } catch {}
537
- }
538
521
  /** Render an identity for display, marking the inline case that has no agent file on disk. */
539
522
  function formatAgentIdentity(identity, inline) {
540
523
  if (!identity) return void 0;
@@ -1070,7 +1053,7 @@ function preflightSubagentDepth(depth, config) {
1070
1053
  }
1071
1054
  //#endregion
1072
1055
  //#region src/services/errors/index.ts
1073
- var DoomTeamExpectedError = class extends Error {
1056
+ var PoTeamExpectedError = class extends Error {
1074
1057
  code;
1075
1058
  retryable;
1076
1059
  recovery;
@@ -1079,11 +1062,11 @@ var DoomTeamExpectedError = class extends Error {
1079
1062
  this.code = code;
1080
1063
  this.retryable = retryable;
1081
1064
  this.recovery = recovery;
1082
- this.name = "DoomTeamExpectedError";
1065
+ this.name = "PoTeamExpectedError";
1083
1066
  }
1084
1067
  };
1085
1068
  function invalidRequest(message, recovery) {
1086
- return new DoomTeamExpectedError("invalid_request", message, false, recovery);
1069
+ return new PoTeamExpectedError("invalid_request", message, false, recovery);
1087
1070
  }
1088
1071
  //#endregion
1089
1072
  //#region src/services/modelInfo/index.ts
@@ -1123,6 +1106,12 @@ function toModelInfo(model) {
1123
1106
  thinkingLevelMap: model.thinkingLevelMap
1124
1107
  };
1125
1108
  }
1109
+ /** The parent's authenticated models as the host lists them now; only the parent model when it cannot list. */
1110
+ async function availableModelInfos(execution) {
1111
+ const models = await execution.getAvailableModels?.();
1112
+ if (models) return models.map(toModelInfo);
1113
+ return execution.model ? [toModelInfo(execution.model)] : [];
1114
+ }
1126
1115
  function splitKnownThinkingSuffix(model) {
1127
1116
  const colonIdx = model.lastIndexOf(THINKING_SUFFIX_SEPARATOR);
1128
1117
  if (colonIdx === -1) return {
@@ -1406,6 +1395,205 @@ function selectAvailableModel(primaryModel, fallbackModels, availableModels, pre
1406
1395
  }
1407
1396
  }
1408
1397
  //#endregion
1398
+ //#region src/services/nativeRunCoordinator/index.ts
1399
+ /**
1400
+ * The root session's agent. Every Team launcher except the browser's is one of
1401
+ * its tools, so it is who sent a task or steer that arrives through them.
1402
+ */
1403
+ const MAIN_AGENT_SENDER = {
1404
+ kind: "agent",
1405
+ id: "main",
1406
+ name: "Main agent"
1407
+ };
1408
+ /** The person at the browser, who launches and guides runs from the Agents tab. */
1409
+ const HUMAN_SENDER = {
1410
+ kind: "human",
1411
+ name: "You"
1412
+ };
1413
+ function terminalState(event) {
1414
+ return event.state === "completed" || event.state === "failed" || event.state === "stopped" ? event.state : void 0;
1415
+ }
1416
+ function entryKey(sessionId, runId) {
1417
+ return JSON.stringify([sessionId, runId]);
1418
+ }
1419
+ /** A stored run's identity, as `start` put it in the request's `meta`. */
1420
+ function storedRunIdentity(run) {
1421
+ const meta = run.request.meta;
1422
+ if (typeof meta?.identity !== "string") return void 0;
1423
+ return {
1424
+ identity: meta.identity,
1425
+ inline: meta.inline === true,
1426
+ ...typeof meta.agentDescription === "string" ? { agentDescription: meta.agentDescription } : {},
1427
+ ...typeof meta.agentFilePath === "string" ? { agentFilePath: meta.agentFilePath } : {}
1428
+ };
1429
+ }
1430
+ var NativeRunCoordinator = class {
1431
+ childSessions;
1432
+ tracker;
1433
+ notifier;
1434
+ projection;
1435
+ entries = /* @__PURE__ */ new Map();
1436
+ closed = false;
1437
+ closing;
1438
+ constructor(childSessions, tracker, notifier, projection) {
1439
+ this.childSessions = childSessions;
1440
+ this.tracker = tracker;
1441
+ this.notifier = notifier;
1442
+ this.projection = projection;
1443
+ }
1444
+ service() {
1445
+ if (this.closed) throw new Error("The native Team run coordinator is closed.");
1446
+ const service = this.childSessions?.get();
1447
+ if (!service) throw new Error("The in-process Pi child-session service is unavailable.");
1448
+ return service;
1449
+ }
1450
+ async start(sessionId, request, identity) {
1451
+ if (!sessionId.trim()) throw new Error("Native child runs require a session identity.");
1452
+ const handle = await this.service().start({
1453
+ ...request,
1454
+ ...identity ? { meta: {
1455
+ ...request.meta,
1456
+ ...JSON.parse(JSON.stringify(identity))
1457
+ } } : {}
1458
+ });
1459
+ return this.adopt(sessionId, request.scope, request, handle, identity);
1460
+ }
1461
+ async restore(sessionId, run, intercom) {
1462
+ const service = this.service();
1463
+ if (!service.restore) throw new Error("This child-session service cannot restore runs.");
1464
+ const handle = await service.restore(run.request.runId, intercom ? { intercom } : void 0);
1465
+ return this.adopt(sessionId, run.request.scope, run.request, handle, storedRunIdentity(run));
1466
+ }
1467
+ async adopt(sessionId, scope, request, handle, identity) {
1468
+ if (this.closed) {
1469
+ await handle.dispose();
1470
+ throw new Error("The native Team run coordinator closed during child startup.");
1471
+ }
1472
+ const entry = {
1473
+ sessionId,
1474
+ scope,
1475
+ request,
1476
+ ...identity ? { identity } : {},
1477
+ handle,
1478
+ terminal: false
1479
+ };
1480
+ const key = entryKey(sessionId, request.runId);
1481
+ this.entries.set(key, entry);
1482
+ try {
1483
+ const unsubscribe = handle.subscribe((event) => this.onEvent(entry, event));
1484
+ if (entry.terminal) unsubscribe();
1485
+ else entry.unsubscribe = unsubscribe;
1486
+ return handle;
1487
+ } catch (error) {
1488
+ this.entries.delete(key);
1489
+ await handle.dispose().catch(() => void 0);
1490
+ throw error;
1491
+ }
1492
+ }
1493
+ get(sessionId, runId) {
1494
+ return this.entries.get(entryKey(sessionId, runId))?.handle;
1495
+ }
1496
+ /**
1497
+ * The newest entries of a run this session's child service stored, from its durable conversation, also once the
1498
+ * run finished or the session restarted; undefined for a run it cannot read, such as an external one.
1499
+ */
1500
+ async readTranscript(sessionId, runId, limit) {
1501
+ const service = this.service();
1502
+ if (!service.readTranscriptPage) return void 0;
1503
+ try {
1504
+ return (await service.readTranscriptPage(runId, { limit })).entries;
1505
+ } catch (error) {
1506
+ if (this.entries.has(entryKey(sessionId, runId))) throw error;
1507
+ return;
1508
+ }
1509
+ }
1510
+ status(sessionId, runId) {
1511
+ return this.tracker.getNative(sessionId, runId);
1512
+ }
1513
+ async reported(runId) {
1514
+ return this.service().reported?.(runId);
1515
+ }
1516
+ async steer(sessionId, runId, message, signal) {
1517
+ const handle = this.get(sessionId, runId);
1518
+ if (!handle) throw new Error(`No active native run matches '${runId}'.`);
1519
+ await handle.steer(message, signal);
1520
+ }
1521
+ async stop(sessionId, runId, reason) {
1522
+ const handle = this.get(sessionId, runId);
1523
+ if (!handle) throw new Error(`No active native run matches '${runId}'.`);
1524
+ await handle.stop(reason);
1525
+ }
1526
+ async close() {
1527
+ this.closed = true;
1528
+ this.closing ??= (async () => {
1529
+ const active = [...this.entries.values()];
1530
+ for (const entry of active) {
1531
+ entry.unsubscribe?.();
1532
+ this.entries.delete(entryKey(entry.sessionId, entry.request.runId));
1533
+ }
1534
+ const failures = (await Promise.allSettled(active.map((entry) => entry.handle.dispose()))).filter((outcome) => outcome.status === "rejected").map((outcome) => outcome.reason);
1535
+ if (failures.length) throw new AggregateError(failures, "Native Team run shutdown failed.");
1536
+ })();
1537
+ return this.closing;
1538
+ }
1539
+ onEvent(entry, event) {
1540
+ entry.startedAt ??= event.timestamp;
1541
+ const status = terminalState(event);
1542
+ const projection = {
1543
+ runId: event.runId,
1544
+ agent: entry.request.agent,
1545
+ ...entry.identity ? {
1546
+ identity: entry.identity.identity,
1547
+ inline: entry.identity.inline
1548
+ } : {},
1549
+ ...entry.identity?.agentDescription ? { agentDescription: entry.identity.agentDescription } : {},
1550
+ ...entry.identity?.agentFilePath ? { agentFilePath: entry.identity.agentFilePath } : {},
1551
+ task: entry.request.task,
1552
+ cwd: entry.request.cwd,
1553
+ runtime: "pi",
1554
+ status: event.state === "starting" ? "queued" : event.state === "running" ? "running" : event.state,
1555
+ startedAt: entry.startedAt,
1556
+ updatedAt: event.timestamp,
1557
+ ...event.cost === void 0 ? {} : { cost: event.cost },
1558
+ ...event.tokens === void 0 ? {} : { tokens: event.tokens },
1559
+ ...event.toolCount === void 0 ? {} : { toolCount: event.toolCount },
1560
+ ...event.model === void 0 ? {} : { model: event.model },
1561
+ ...event.thinking === void 0 ? {} : { thinking: event.thinking },
1562
+ ...event.message ? {
1563
+ error: status === "failed" || status === "stopped" ? event.message : void 0,
1564
+ summary: event.message
1565
+ } : {}
1566
+ };
1567
+ this.tracker.upsertNative(entry.sessionId, entry.scope, projection);
1568
+ this.projection?.publish(entry.sessionId, projection);
1569
+ if (!status || entry.terminal) return;
1570
+ entry.terminal = true;
1571
+ entry.unsubscribe?.();
1572
+ this.entries.delete(entryKey(entry.sessionId, entry.request.runId));
1573
+ const result = {
1574
+ runId: entry.request.runId,
1575
+ agent: entry.request.agent,
1576
+ ...entry.identity ? {
1577
+ identity: entry.identity.identity,
1578
+ inline: entry.identity.inline
1579
+ } : {},
1580
+ task: entry.request.task,
1581
+ cwd: entry.request.cwd,
1582
+ runtime: "pi",
1583
+ state: status,
1584
+ success: status === "completed",
1585
+ summary: event.message ?? (status === "completed" ? "Native child run completed." : `Native child run ${status}.`),
1586
+ durationMs: Math.max(0, event.timestamp - (this.tracker.getNative(entry.sessionId, entry.request.runId)?.startedAt ?? event.timestamp)),
1587
+ sessionId: entry.sessionId
1588
+ };
1589
+ if (this.notifier) this.notifier.deliver(result).then(async (delivered) => {
1590
+ if (!delivered) return;
1591
+ this.tracker.acknowledgeHandoff(entry.sessionId, entry.request.runId);
1592
+ await this.childSessions?.get()?.markReported?.(entry.request.runId);
1593
+ }).catch(() => void 0);
1594
+ }
1595
+ };
1596
+ //#endregion
1409
1597
  //#region src/services/runtimeRegistry/index.ts
1410
1598
  /**
1411
1599
  * Which agent runtime executes a run, and how to invoke it.
@@ -1522,12 +1710,12 @@ async function runWithConcurrency(factories, concurrency, report) {
1522
1710
  }
1523
1711
  }
1524
1712
  }
1525
- report?.("doom_team.concurrency_started", {
1713
+ report?.("po_team.concurrency_started", {
1526
1714
  "team.task_count": factories.length,
1527
1715
  "team.concurrency": effectiveConcurrency
1528
1716
  });
1529
1717
  await Promise.all(Array.from({ length: effectiveConcurrency }, () => worker()));
1530
- report?.("doom_team.concurrency_finished", {
1718
+ report?.("po_team.concurrency_finished", {
1531
1719
  "team.task_count": factories.length,
1532
1720
  "team.concurrency": effectiveConcurrency,
1533
1721
  "team.failure_count": results.filter((result) => result?.status === "rejected").length,
@@ -1574,8 +1762,8 @@ async function runWithConcurrency(factories, concurrency, report) {
1574
1762
  * be worse than not checking at all (false confidence). Wiring this needs
1575
1763
  * a real session-scoped store owned by a lifecycle-bound service - a
1576
1764
  * follow-up, not guessed here.
1577
- * - Fork context is resolved here and requires a captured persisted Pi source;
1578
- * unavailable or non-Pi fork requests fail closed rather than becoming fresh
1765
+ * - Fork context is resolved here and requires the parent session's branch;
1766
+ * unavailable fork requests fail closed rather than becoming fresh
1579
1767
  * launches.
1580
1768
  * - Per-task overrides with no direct `BuildPiArgsInput` field confirmed yet
1581
1769
  * (`skill`, `toolBudget`, `turnBudget`, `outputSchema`/structured output,
@@ -1611,9 +1799,8 @@ function describeForkFailure(reason) {
1611
1799
  /**
1612
1800
  * Map a captured parent branch onto the spawn request's fork fields.
1613
1801
  *
1614
- * `parentSessionFile` and `parentLeafId` describe a terminal Pi capture only. A
1615
- * v4 source already carries its own file and branch, so flattening it into
1616
- * those fields would describe it in the wrong vocabulary and lose the branch.
1802
+ * A headless host's branch forks a native child inside its own Harness. A
1803
+ * terminal Pi capture describes a branch for an external runtime only.
1617
1804
  */
1618
1805
  function forkRequestFields(captured) {
1619
1806
  if (!captured) return { parentForkFailure: "no-capture-installed" };
@@ -1621,7 +1808,6 @@ function forkRequestFields(captured) {
1621
1808
  if (!captured.ok) return { parentForkFailure: captured.reason };
1622
1809
  const { source } = captured;
1623
1810
  return {
1624
- parentForkSource: source.terminalSource,
1625
1811
  ...source.sessionFile ? { parentSessionFile: source.sessionFile } : {},
1626
1812
  parentLeafId: source.leafId
1627
1813
  };
@@ -1643,34 +1829,25 @@ function captureSessionForkSource(manager, mode) {
1643
1829
  ok: false,
1644
1830
  reason: "unsupported-version"
1645
1831
  };
1646
- const branch = manager.getBranch(leafId);
1647
- if (branch.at(-1)?.id !== leafId) return {
1832
+ if (manager.getBranch(leafId).at(-1)?.id !== leafId) return {
1648
1833
  ok: false,
1649
1834
  reason: "branch-mismatch"
1650
1835
  };
1651
- const sourceSessionId = manager.getSessionId();
1652
- if (!sourceSessionId.trim()) return {
1836
+ if (!manager.getSessionId().trim()) return {
1653
1837
  ok: false,
1654
1838
  reason: "no-session-id"
1655
1839
  };
1656
- const terminalSource = Object.freeze({
1657
- kind: "terminal-pi-fork",
1658
- sourceSessionId,
1659
- sourceLeafId: leafId,
1660
- snapshotJsonl: `${[header, ...branch].map((record) => JSON.stringify(record)).join("\n")}\n`
1661
- });
1662
1840
  const sessionFile = manager.getSessionFile();
1663
1841
  return {
1664
1842
  ok: true,
1665
1843
  source: {
1666
1844
  leafId,
1667
- terminalSource,
1668
1845
  ...readableSessionFile(sessionFile) ? { sessionFile } : {}
1669
1846
  }
1670
1847
  };
1671
1848
  }
1672
1849
  function resolveEffectiveContext(taskInput, agent) {
1673
- return taskInput.sessionFile ? CONTEXT_FRESH : taskInput.context ?? agent.defaultContext ?? CONTEXT_FRESH;
1850
+ return taskInput.context ?? agent.defaultContext ?? CONTEXT_FRESH;
1674
1851
  }
1675
1852
  const DEFAULT_PARALLEL_CONCURRENCY = 4;
1676
1853
  /**
@@ -1680,14 +1857,13 @@ const DEFAULT_PARALLEL_CONCURRENCY = 4;
1680
1857
  * soon as its child confirms it started, and the child then runs detached. So
1681
1858
  * `runWithConcurrency` throttles how fast children are STARTED, not how many
1682
1859
  * are running - `{tasks: [8], concurrency: 4}` ends up with eight live model
1683
- * processes, not four. 8 matches the sibling implementation's
1684
- * `PI_TEAM_MATE_MAX_PARALLEL`.
1860
+ * processes, not four. 30 lets one call fan a whole swarm out.
1685
1861
  *
1686
1862
  * This is a per-call declaration limit and nothing more. What actually bounds
1687
1863
  * live children across concurrent calls is `AdmissionGate`
1688
1864
  * (`runs/shared/admissionGate.ts`), which every spawn passes through.
1689
1865
  */
1690
- const DEFAULT_PARALLEL_MAX_TASKS = 8;
1866
+ const DEFAULT_PARALLEL_MAX_TASKS = 30;
1691
1867
  /**
1692
1868
  * Process-wide ceiling on children ALIVE at once.
1693
1869
  *
@@ -1718,14 +1894,14 @@ function bestEffortRuntimeWarnings(runtime, agentConfig, excludeTools) {
1718
1894
  ...agentConfig.skills?.length || agentConfig.skillPath?.length ? ["skills"] : [],
1719
1895
  ...agentConfig.extensions !== void 0 || agentConfig.subagentOnlyExtensions?.length ? ["extensions"] : []
1720
1896
  ];
1721
- if (unsupportedResources.length > 0) warnings.push(`Doom Team cannot project or enforce configured Pi ${unsupportedResources.join(", ")} on runtime '${runtime}'.`);
1897
+ if (unsupportedResources.length > 0) warnings.push(`Po Team cannot project or enforce configured Pi ${unsupportedResources.join(", ")} on runtime '${runtime}'.`);
1722
1898
  if (agentConfig.skills?.length) warnings.push(`Configured skills were not injected: ${agentConfig.skills.join(", ")}.`);
1723
1899
  if (excludeTools?.length) warnings.push(`Runtime '${runtime}' cannot enforce Team package tool exclusions; launched best effort for: ${excludeTools.join(", ")}.`);
1724
1900
  return warnings;
1725
1901
  }
1726
1902
  function readWorkflowPreferences(payload) {
1727
1903
  if (payload === void 0) return {};
1728
- const invalid = (detail) => new DoomTeamExpectedError(ERROR_CODE_INVALID_REQUEST, `WORKFLOW_RUN_CONFIG ${detail}`, false, "Provide a JSON object with optional nonblank subagentModel and recognized subagentThinking.");
1904
+ const invalid = (detail) => new PoTeamExpectedError(ERROR_CODE_INVALID_REQUEST, `WORKFLOW_RUN_CONFIG ${detail}`, false, "Provide a JSON object with optional nonblank subagentModel and recognized subagentThinking.");
1729
1905
  let value;
1730
1906
  try {
1731
1907
  value = JSON.parse(payload);
@@ -1743,29 +1919,40 @@ function readWorkflowPreferences(payload) {
1743
1919
  if (preferences.subagentThinking && !THINKING_LEVELS.some((level) => level === preferences.subagentThinking)) throw invalid(`subagentThinking must be one of: ${THINKING_LEVELS.join(", ")}.`);
1744
1920
  return preferences;
1745
1921
  }
1746
- function resolvedModelSelection(taskInput, agentConfig, runtime, parentModel, availableModels, teamPackageModels, preferences) {
1922
+ function resolvedModelSelection(taskInput, agentConfig, runtime, parentModel, availableModels, teamPackageModels, preferences, planning = {}, teamThinking) {
1747
1923
  const parentModelId = isPiRuntime(runtime) && parentModel ? `${parentModel.provider}/${parentModel.id}` : void 0;
1748
1924
  const agentModels = [...agentConfig.modelSource?.scope === "package" ? [] : [agentConfig.model], ...agentConfig.fallbackModels ?? []];
1749
1925
  const candidates = (isPiRuntime(runtime) ? [
1750
1926
  taskInput.model,
1751
1927
  preferences.subagentModel,
1928
+ planning.subagentModel,
1752
1929
  ...agentModels,
1753
1930
  ...teamPackageModels ?? [],
1754
1931
  parentModelId
1755
1932
  ] : [
1756
1933
  taskInput.model,
1757
1934
  preferences.subagentModel,
1935
+ planning.subagentModel,
1758
1936
  ...agentModels,
1759
1937
  ...teamPackageModels ?? []
1760
1938
  ]).filter((candidate) => Boolean(candidate?.trim()));
1761
1939
  const [primaryModel, ...fallbackModels] = candidates;
1762
1940
  const agentThinking = typeof agentConfig.thinking === "string" ? agentConfig.thinking : void 0;
1763
- if (!preferences.subagentModel && !preferences.subagentThinking) return {
1764
- primaryModel,
1765
- fallbackModels,
1766
- model: selectAvailableModel(primaryModel, fallbackModels, availableModels),
1767
- thinking: agentThinking
1941
+ const teamThinkingFor = (model) => {
1942
+ if (agentConfig.thinking === false || !teamThinking) return void 0;
1943
+ const info = findModelInfo(model, availableModels);
1944
+ return info && !getSupportedThinkingLevels(info).some((level) => level === teamThinking) ? void 0 : teamThinking;
1768
1945
  };
1946
+ if (!preferences.subagentModel && !preferences.subagentThinking && !planning.subagentModel && !planning.subagentThinking) {
1947
+ const model = selectAvailableModel(primaryModel, fallbackModels, availableModels);
1948
+ const selectedSuffix = model ? splitKnownThinkingSuffix(model).thinkingSuffix.slice(1) : void 0;
1949
+ return {
1950
+ primaryModel,
1951
+ fallbackModels,
1952
+ model,
1953
+ thinking: agentThinking ?? (selectedSuffix || void 0) ?? teamThinkingFor(model)
1954
+ };
1955
+ }
1769
1956
  let model;
1770
1957
  let selectedCandidate;
1771
1958
  for (const candidate of candidates) {
@@ -1777,11 +1964,13 @@ function resolvedModelSelection(taskInput, agentConfig, runtime, parentModel, av
1777
1964
  }
1778
1965
  const selectedSuffix = model ? splitKnownThinkingSuffix(model).thinkingSuffix.slice(1) : void 0;
1779
1966
  const explicitThinking = selectedCandidate === taskInput.model ? selectedSuffix : void 0;
1780
- const thinking = explicitThinking || preferences.subagentThinking || selectedSuffix || agentThinking;
1781
- const workflowThinking = !explicitThinking && (preferences.subagentThinking || selectedCandidate === preferences.subagentModel && selectedSuffix);
1967
+ const planningThinking = !planning.subagentModel || selectedCandidate === planning.subagentModel ? planning.subagentThinking : void 0;
1968
+ const preferredThinking = (!preferences.subagentModel || selectedCandidate === preferences.subagentModel || selectedCandidate === taskInput.model ? preferences.subagentThinking : void 0) || planningThinking;
1969
+ const thinking = explicitThinking || preferredThinking || selectedSuffix || agentThinking || teamThinkingFor(model);
1970
+ const workflowThinking = !explicitThinking && (preferredThinking || selectedCandidate === preferences.subagentModel && selectedSuffix);
1782
1971
  const modelInfo = findModelInfo(model, availableModels);
1783
- if (isPiRuntime(runtime) && workflowThinking && modelInfo && !getSupportedThinkingLevels(modelInfo).some((level) => level === thinking)) throw new DoomTeamExpectedError(ERROR_CODE_INVALID_REQUEST, `WORKFLOW_RUN_CONFIG thinking '${thinking}' is unsupported by model '${modelInfo.fullId}'.`, false, `Choose a supported thinking level: ${getSupportedThinkingLevels(modelInfo).join(", ")}.`);
1784
- if (model && selectedSuffix && !explicitThinking && preferences.subagentThinking) model = splitKnownThinkingSuffix(model).baseModel;
1972
+ if (isPiRuntime(runtime) && workflowThinking && modelInfo && !getSupportedThinkingLevels(modelInfo).some((level) => level === thinking)) throw new PoTeamExpectedError(ERROR_CODE_INVALID_REQUEST, `Subagent thinking '${thinking}' is unsupported by model '${modelInfo.fullId}'.`, false, `Choose a supported thinking level: ${getSupportedThinkingLevels(modelInfo).join(", ")}.`);
1973
+ if (model && selectedSuffix && !explicitThinking && preferredThinking) model = splitKnownThinkingSuffix(model).baseModel;
1785
1974
  return {
1786
1975
  primaryModel,
1787
1976
  fallbackModels,
@@ -1807,7 +1996,8 @@ var SpawnPlanner = class {
1807
1996
  nativeRuns;
1808
1997
  teamChannel;
1809
1998
  environment;
1810
- constructor(agents, spawner, policies = new require_capabilityCeiling.SubagentCapabilityPolicyStore(), skills, reportConcurrencyEvent, _mcpToolResolver, admission, childSessions, nativeRuns, teamChannel, environment = {}) {
1999
+ agentConfig;
2000
+ constructor(agents, spawner, policies = new require_capabilityCeiling.SubagentCapabilityPolicyStore(), skills, reportConcurrencyEvent, _mcpToolResolver, admission, childSessions, nativeRuns, teamChannel, environment = {}, agentConfig) {
1811
2001
  this.agents = agents;
1812
2002
  this.spawner = spawner;
1813
2003
  this.policies = policies;
@@ -1818,6 +2008,7 @@ var SpawnPlanner = class {
1818
2008
  this.nativeRuns = nativeRuns;
1819
2009
  this.teamChannel = teamChannel;
1820
2010
  this.environment = environment;
2011
+ this.agentConfig = agentConfig;
1821
2012
  }
1822
2013
  generateRunId() {
1823
2014
  return crypto.randomUUID();
@@ -1827,15 +2018,9 @@ var SpawnPlanner = class {
1827
2018
  try {
1828
2019
  stat = node_fs.statSync(cwd);
1829
2020
  } catch {
1830
- throw new DoomTeamExpectedError(ERROR_CODE_INVALID_REQUEST, `Working directory '${cwd}' does not exist.`, false, "Retry with an existing directory.");
2021
+ throw new PoTeamExpectedError(ERROR_CODE_INVALID_REQUEST, `Working directory '${cwd}' does not exist.`, false, "Retry with an existing directory.");
1831
2022
  }
1832
- if (!stat.isDirectory()) throw new DoomTeamExpectedError(ERROR_CODE_INVALID_REQUEST, `Working directory '${cwd}' is not a directory.`, false, "Retry with an existing directory.");
1833
- }
1834
- resolveTeamPackageExcludeTools() {
1835
- return require_agentDiscovery.resolveActiveTeamPackageConfig()?.config.excludeTools;
1836
- }
1837
- resolveTeamPackageModels() {
1838
- return require_agentDiscovery.resolveActiveTeamModelSpecs();
2023
+ if (!stat.isDirectory()) throw new PoTeamExpectedError(ERROR_CODE_INVALID_REQUEST, `Working directory '${cwd}' is not a directory.`, false, "Retry with an existing directory.");
1839
2024
  }
1840
2025
  executableAvailable(command) {
1841
2026
  if (node_path.isAbsolute(command) || command.includes(node_path.sep)) try {
@@ -1855,17 +2040,17 @@ var SpawnPlanner = class {
1855
2040
  }
1856
2041
  resolveTaskList(request) {
1857
2042
  const hasSingle = request.single !== void 0;
1858
- if (hasSingle === (request.tasks !== void 0)) throw new DoomTeamExpectedError(ERROR_CODE_INVALID_REQUEST, "A run requires exactly one of internal single or tasks representations.", false, "Submit a non-empty requests array.");
2043
+ if (hasSingle === (request.tasks !== void 0)) throw new PoTeamExpectedError(ERROR_CODE_INVALID_REQUEST, "A run requires exactly one of internal single or tasks representations.", false, "Submit a non-empty requests array.");
1859
2044
  if (hasSingle) return [request.single];
1860
- if (!request.tasks || request.tasks.length === 0) throw new DoomTeamExpectedError(ERROR_CODE_INVALID_REQUEST, "A run requires at least one entry in its requests collection.", false, "Submit a non-empty requests array.");
2045
+ if (!request.tasks || request.tasks.length === 0) throw new PoTeamExpectedError(ERROR_CODE_INVALID_REQUEST, "A run requires at least one entry in its requests collection.", false, "Submit a non-empty requests array.");
1861
2046
  return request.tasks;
1862
2047
  }
1863
- resolveAgentOrThrow(name, cwd, scope) {
1864
- const resolved = this.agents.find(cwd, scope, name);
1865
- if (!resolved) throw new DoomTeamExpectedError(ERROR_CODE_AGENT_NOT_FOUND, `Unknown agent '${name}'.`, false, "Call subagent({\"action\":\"agents\"}) and retry with an exact name.");
2048
+ async resolveAgentOrThrow(name, cwd, scope) {
2049
+ const resolved = await this.agents.find(cwd, scope, name);
2050
+ if (!resolved) throw new PoTeamExpectedError(ERROR_CODE_AGENT_NOT_FOUND, `Unknown agent '${name}'.`, false, "Call subagent({\"action\":\"agents\"}) and retry with an exact name.");
1866
2051
  return resolved;
1867
2052
  }
1868
- resolveExecutableAgent(taskInput, cwd, scope) {
2053
+ async resolveExecutableAgent(taskInput, cwd, scope) {
1869
2054
  if (!taskInput.inlineAgent) return this.resolveAgentOrThrow(taskInput.agent, cwd, scope);
1870
2055
  return {
1871
2056
  name: taskInput.agent.trim(),
@@ -1959,12 +2144,12 @@ var SpawnPlanner = class {
1959
2144
  * the module header.
1960
2145
  */
1961
2146
  async spawnOneChild(input) {
1962
- const { runId, operationId, agentConfig, identity, capabilityCeiling, excludeTools, teamPackageModels, workflowPreferences, taskInput, childIndex, fanout, fallbackCwd, parentSessionId, parentForkSource, sessionScope, environment, parentSessionFile, maxLiveRuns, admissionTimeoutMs, handshakeTimeoutMs, artifacts, artifactDir, availableModels, parentModel, runtime, runtimes, skillProjectionCache } = input;
2147
+ const { runId, operationId, agentConfig, identity, capabilityCeiling, excludeTools, teamPackageModels, teamThinking, workflowPreferences, planningPreferences, taskInput, childIndex, fanout, fallbackCwd, parentSessionId, parentForkSource, sessionScope, environment, parentSessionFile, maxLiveRuns, admissionTimeoutMs, handshakeTimeoutMs, artifacts, artifactDir, availableModels, parentModel, runtime, runtimes, skillProjectionCache, sender } = input;
1963
2148
  const cwd = taskInput.cwd ?? fallbackCwd;
1964
2149
  const task = taskInput.task ?? "";
1965
2150
  const effectiveContext = resolveEffectiveContext(taskInput, agentConfig);
1966
2151
  const effectiveRuntime = taskInput.runtime ?? runtime ?? agentConfig.runtime ?? "pi";
1967
- const modelSelection = resolvedModelSelection(taskInput, agentConfig, effectiveRuntime, parentModel, availableModels, teamPackageModels, workflowPreferences);
2152
+ const modelSelection = resolvedModelSelection(taskInput, agentConfig, effectiveRuntime, parentModel, availableModels, teamPackageModels, workflowPreferences, planningPreferences, teamThinking);
1968
2153
  if (modelSelection.primaryModel && availableModels !== void 0 && !modelSelection.model) return {
1969
2154
  agent: agentConfig.name,
1970
2155
  identity: identity.identity,
@@ -1986,7 +2171,11 @@ var SpawnPlanner = class {
1986
2171
  error: error instanceof Error ? error.message : String(error)
1987
2172
  };
1988
2173
  }
1989
- const warnings = [...skillProjection.warnings, ...bestEffortRuntimeWarnings(effectiveRuntime, agentConfig, excludeTools)];
2174
+ const warnings = [
2175
+ ...modelSelection.primaryModel && modelSelection.model && !selectAvailableModel(modelSelection.primaryModel, [], availableModels) ? [`[fallback] ${modelSelection.primaryModel} is unavailable. Using ${modelSelection.model}.`] : [],
2176
+ ...skillProjection.warnings,
2177
+ ...bestEffortRuntimeWarnings(effectiveRuntime, agentConfig, excludeTools)
2178
+ ];
1990
2179
  const warning = warnings.length > 0 ? warnings.join(" ") : void 0;
1991
2180
  const spawnInput = {
1992
2181
  runId,
@@ -2001,7 +2190,6 @@ var SpawnPlanner = class {
2001
2190
  sessionScope,
2002
2191
  ...parentSessionFile ? { parentSessionFile } : {},
2003
2192
  piArgs: {
2004
- ...taskInput.sessionFile ? { sessionFile: taskInput.sessionFile } : {},
2005
2193
  ...modelSelection.model ? { model: modelSelection.model } : {},
2006
2194
  ...capabilityCeiling ? { capabilityCeiling } : {},
2007
2195
  ...effectiveContext === CONTEXT_FORK && parentSessionId ? { parentSessionId } : {}
@@ -2013,7 +2201,7 @@ var SpawnPlanner = class {
2013
2201
  runtimes
2014
2202
  };
2015
2203
  const admission = this.admission;
2016
- if (!admission) throw new Error("Doom Team spawn admission is not configured.");
2204
+ if (!admission) throw new Error("Po Team spawn admission is not configured.");
2017
2205
  let ticket;
2018
2206
  try {
2019
2207
  ticket = await admission.admit({
@@ -2035,11 +2223,8 @@ var SpawnPlanner = class {
2035
2223
  if (isPiRuntime(effectiveRuntime)) {
2036
2224
  if (!this.nativeRuns || !this.childSessions?.get()) throw new Error("The native Team run coordinator is unavailable.");
2037
2225
  const scope = sessionScope;
2038
- const source = taskInput.sessionFile ? {
2039
- kind: "v4-restore",
2040
- sessionFile: taskInput.sessionFile
2041
- } : effectiveContext === CONTEXT_FORK ? parentForkSource ?? (() => {
2042
- throw new Error("Native fork input requires an immutable terminal Pi snapshot.");
2226
+ const source = effectiveContext === CONTEXT_FORK ? parentForkSource ?? (() => {
2227
+ throw new Error("Native fork input requires the parent session's branch.");
2043
2228
  })() : { kind: "fresh" };
2044
2229
  const intercom = this.teamChannel?.createNativeChildIntercom({
2045
2230
  rootSessionId: scope.rootSessionId,
@@ -2062,6 +2247,8 @@ var SpawnPlanner = class {
2062
2247
  source,
2063
2248
  agent: agentConfig.name,
2064
2249
  task,
2250
+ ...warning ? { meta: { warning } } : {},
2251
+ sender: sender ?? MAIN_AGENT_SENDER,
2065
2252
  cwd,
2066
2253
  ...modelSelection.model ? { model: modelSelection.model } : {},
2067
2254
  ...typeof modelSelection.thinking === "string" ? { thinking: modelSelection.thinking } : {},
@@ -2078,7 +2265,9 @@ var SpawnPlanner = class {
2078
2265
  environment
2079
2266
  }, {
2080
2267
  identity: identity.identity,
2081
- inline: identity.inline
2268
+ inline: identity.inline,
2269
+ ...agentConfig.description ? { agentDescription: agentConfig.description } : {},
2270
+ ...agentConfig.filePath ? { agentFilePath: agentConfig.filePath } : {}
2082
2271
  });
2083
2272
  } catch (error) {
2084
2273
  intercom?.dispose?.();
@@ -2120,71 +2309,67 @@ var SpawnPlanner = class {
2120
2309
  }
2121
2310
  }
2122
2311
  async spawn(request, config) {
2312
+ if (!this.agentConfig) throw new PoTeamExpectedError("runtime_unavailable", "Team agent configuration is not loaded yet.", true, "Retry after the session configuration is ready.");
2313
+ const team = await this.agentConfig.current();
2123
2314
  const tasks = this.resolveTaskList(request);
2124
2315
  const workflowPreferences = readWorkflowPreferences(request.environment?.WORKFLOW_RUN_CONFIG ?? this.environment.WORKFLOW_RUN_CONFIG);
2316
+ const planningConfig = request.parentSelection?.state?.["minor-mode"]?.includes("plan") ? team.planningSubagents : void 0;
2317
+ const planningPreferences = {
2318
+ subagentModel: planningConfig?.model,
2319
+ subagentThinking: planningConfig?.thinking
2320
+ };
2125
2321
  const fanout = tasks.length > 1;
2126
- const teamPackageExcludeTools = this.resolveTeamPackageExcludeTools();
2127
- const teamPackageModels = this.resolveTeamPackageModels();
2322
+ const teamPackageExcludeTools = team.excludeTools ? [...team.excludeTools] : void 0;
2323
+ const teamPackageModels = team.models;
2128
2324
  const capabilityCeiling = this.policies.resolve();
2129
2325
  const depthCheck = preflightSubagentDepth(request.currentDepth ?? resolveCurrentSubagentDepth(), config);
2130
- if (depthCheck.error) throw new DoomTeamExpectedError(ERROR_CODE_UNSUPPORTED_OPERATION, depthCheck.error, false, "Give each child a self-contained task within the Team package policy.");
2326
+ if (depthCheck.error) throw new PoTeamExpectedError(ERROR_CODE_UNSUPPORTED_OPERATION, depthCheck.error, false, "Give each child a self-contained task within the Team package policy.");
2131
2327
  const maxTasks = config.parallel?.maxTasks ?? DEFAULT_PARALLEL_MAX_TASKS;
2132
- if (tasks.length > maxTasks) throw new DoomTeamExpectedError(ERROR_CODE_INVALID_REQUEST, `Run requested ${tasks.length} tasks, but at most ${maxTasks} may be declared in one call. Concurrency throttles how fast they start, not how many run.`, false, "Send at most that many requests in this call and wait for them, or raise parallel.maxTasks in the subagent config. Splitting the same width across extra calls does not raise the live-child ceiling.");
2328
+ if (tasks.length > maxTasks) throw new PoTeamExpectedError(ERROR_CODE_INVALID_REQUEST, `Run requested ${tasks.length} tasks, but at most ${maxTasks} may be declared in one call. Concurrency throttles how fast they start, not how many run.`, false, "Send at most that many requests in this call and wait for them, or raise parallel.maxTasks in the subagent config. Splitting the same width across extra calls does not raise the live-child ceiling.");
2133
2329
  for (const taskInput of tasks) {
2134
- if (!taskInput.task?.trim()) throw new DoomTeamExpectedError(ERROR_CODE_INVALID_REQUEST, `Run request for '${taskInput.agent}' requires a nonblank task.`, false, "Provide a self-contained nonblank task.");
2135
- if (taskInput.inlineAgent && !taskInput.inlineAgent.systemPrompt.trim()) throw new DoomTeamExpectedError(ERROR_CODE_INVALID_REQUEST, `Inline agent '${taskInput.agent}' requires a nonblank system prompt.`, false, "Provide a focused read-only exploration role.");
2330
+ if (!taskInput.task?.trim()) throw new PoTeamExpectedError(ERROR_CODE_INVALID_REQUEST, `Run request for '${taskInput.agent}' requires a nonblank task.`, false, "Provide a self-contained nonblank task.");
2331
+ if (taskInput.inlineAgent && !taskInput.inlineAgent.systemPrompt.trim()) throw new PoTeamExpectedError(ERROR_CODE_INVALID_REQUEST, `Inline agent '${taskInput.agent}' requires a nonblank system prompt.`, false, "Provide a focused read-only exploration role.");
2136
2332
  }
2137
2333
  const resolvedAgentCache = /* @__PURE__ */ new Map();
2138
- const resolvedAgents = tasks.map((taskInput) => {
2139
- if (taskInput.inlineAgent) return this.resolveExecutableAgent(taskInput, taskInput.cwd ?? request.cwd, request.agentScope);
2334
+ const resolvedAgents = [];
2335
+ for (const taskInput of tasks) {
2140
2336
  const cacheKey = [
2141
2337
  request.agentScope,
2142
2338
  require_agentDiscovery.canonicalizeDiscoveryCwd(taskInput.cwd ?? request.cwd),
2143
2339
  taskInput.agent
2144
2340
  ].join("\0");
2145
- const cached = resolvedAgentCache.get(cacheKey);
2146
- if (cached) return cached;
2147
- const resolved = this.resolveExecutableAgent(taskInput, taskInput.cwd ?? request.cwd, request.agentScope);
2148
- resolvedAgentCache.set(cacheKey, resolved);
2149
- return resolved;
2150
- });
2341
+ let resolved = taskInput.inlineAgent ? void 0 : resolvedAgentCache.get(cacheKey);
2342
+ if (!resolved) {
2343
+ resolved = await this.resolveExecutableAgent(taskInput, taskInput.cwd ?? request.cwd, request.agentScope);
2344
+ if (!taskInput.inlineAgent) resolvedAgentCache.set(cacheKey, resolved);
2345
+ }
2346
+ resolvedAgents.push(resolved);
2347
+ }
2151
2348
  for (const [index, taskInput] of tasks.entries()) {
2152
2349
  const effectiveContext = resolveEffectiveContext(taskInput, resolvedAgents[index]);
2153
2350
  const runtime = taskInput.runtime ?? request.runtime ?? resolvedAgents[index].runtime ?? "pi";
2154
2351
  if (effectiveContext === CONTEXT_FORK) {
2155
- if (!isPiRuntime(runtime)) throw new DoomTeamExpectedError(ERROR_CODE_UNSUPPORTED_CONTEXT, `Fork context requires ${PI_RUNTIME_REQUIREMENT} for '${taskInput.agent}'.`, false, "Use a Pi agent for fork context or explicitly request a fresh run.");
2156
- if (!request.parentForkSource) throw new DoomTeamExpectedError(ERROR_CODE_UNSUPPORTED_CONTEXT, `Fork context is unavailable for '${taskInput.agent}': ${describeForkFailure(request.parentForkFailure)}.`, false, "Use an active Pi session with a completed parent turn or explicitly request a fresh run.");
2352
+ if (!isPiRuntime(runtime)) throw new PoTeamExpectedError(ERROR_CODE_UNSUPPORTED_CONTEXT, `Fork context requires ${PI_RUNTIME_REQUIREMENT} for '${taskInput.agent}'.`, false, "Use a Pi agent for fork context or explicitly request a fresh run.");
2353
+ if (!request.parentForkSource) throw new PoTeamExpectedError(ERROR_CODE_UNSUPPORTED_CONTEXT, `Fork context is unavailable for '${taskInput.agent}': ${describeForkFailure(request.parentForkFailure)}.`, false, "Use an active Pi session with a completed parent turn or explicitly request a fresh run.");
2157
2354
  }
2158
2355
  }
2159
- if (request.preallocatedRunIds && request.preallocatedRunIds.length !== tasks.length) throw new DoomTeamExpectedError(ERROR_CODE_OPERATION_CONFLICT, "The operation journal run-id count does not match the request count.", false, "Submit the run as a new tool call.");
2356
+ if (request.preallocatedRunIds && request.preallocatedRunIds.length !== tasks.length) throw new PoTeamExpectedError(ERROR_CODE_OPERATION_CONFLICT, "The operation journal run-id count does not match the request count.", false, "Submit the run as a new tool call.");
2160
2357
  const runIds = request.preallocatedRunIds ?? tasks.map(() => this.generateRunId());
2161
- const identities = tasks.map((taskInput, index) => {
2162
- const inline = taskInput.inlineAgent !== void 0;
2163
- if (!taskInput.identity) return claimAgentIdentity(request.sessionScope, {
2164
- agent: resolvedAgents[index].name,
2165
- inline,
2166
- runId: runIds[index]
2167
- });
2168
- adoptAgentIdentity(request.sessionScope, taskInput.identity, runIds[index]);
2169
- return {
2170
- identity: taskInput.identity,
2171
- name: "",
2172
- role: roleFromAgent(resolvedAgents[index].name),
2173
- number: 0,
2174
- inline,
2175
- persisted: true
2176
- };
2177
- });
2358
+ const identities = tasks.map((taskInput, index) => claimAgentIdentity(request.sessionScope, {
2359
+ agent: resolvedAgents[index].name,
2360
+ inline: taskInput.inlineAgent !== void 0,
2361
+ runId: runIds[index]
2362
+ }));
2178
2363
  const runtimes = resolveRuntimeTable(config.runtimes);
2179
2364
  for (const [index, taskInput] of tasks.entries()) {
2180
2365
  const agent = resolvedAgents[index];
2181
2366
  const cwd = taskInput.cwd ?? request.cwd;
2182
2367
  this.validateCwd(cwd);
2183
2368
  const runtime = taskInput.runtime ?? request.runtime ?? agent.runtime ?? "pi";
2184
- const modelSelection = resolvedModelSelection(taskInput, agent, runtime, request.parentModel, request.availableModels, teamPackageModels, workflowPreferences);
2185
- if (modelSelection.primaryModel && request.availableModels !== void 0 && !modelSelection.model) throw new DoomTeamExpectedError(ERROR_CODE_MODEL_UNAVAILABLE, `No authenticated model is available for '${agent.name}'.`, false, "Authenticate the requested model or choose an available model.");
2186
- if (taskInput.inlineAgent && !isPiRuntime(runtime)) throw new DoomTeamExpectedError(ERROR_CODE_UNSUPPORTED_OPERATION, `Inline agent '${taskInput.agent}' requires ${PI_RUNTIME_REQUIREMENT} to enforce its read-only tools.`, false, "Remove the runtime override or use a discovered external-runtime agent without inlineAgent.");
2187
- if (capabilityCeiling && !isPiRuntime(runtime)) throw new DoomTeamExpectedError(ERROR_CODE_UNSUPPORTED_OPERATION, `Runtime '${runtime}' cannot enforce the active capability ceiling.`, false, `Use ${PI_RUNTIME_REQUIREMENT} while plan mode or another capability ceiling is active.`);
2369
+ const modelSelection = resolvedModelSelection(taskInput, agent, runtime, request.parentModel, request.availableModels, teamPackageModels, workflowPreferences, planningPreferences, team.thinking);
2370
+ if (modelSelection.primaryModel && request.availableModels !== void 0 && !modelSelection.model) throw new PoTeamExpectedError(ERROR_CODE_MODEL_UNAVAILABLE, `No authenticated model is available for '${agent.name}'.`, false, "Authenticate the requested model or choose an available model.");
2371
+ if (taskInput.inlineAgent && !isPiRuntime(runtime)) throw new PoTeamExpectedError(ERROR_CODE_UNSUPPORTED_OPERATION, `Inline agent '${taskInput.agent}' requires ${PI_RUNTIME_REQUIREMENT} to enforce its read-only tools.`, false, "Remove the runtime override or use a discovered external-runtime agent without inlineAgent.");
2372
+ if (capabilityCeiling && !isPiRuntime(runtime)) throw new PoTeamExpectedError(ERROR_CODE_UNSUPPORTED_OPERATION, `Runtime '${runtime}' cannot enforce the active capability ceiling.`, false, `Use ${PI_RUNTIME_REQUIREMENT} while plan mode or another capability ceiling is active.`);
2188
2373
  if (!isPiRuntime(runtime)) {
2189
2374
  let command;
2190
2375
  try {
@@ -2193,9 +2378,9 @@ var SpawnPlanner = class {
2193
2378
  cwd
2194
2379
  }).command;
2195
2380
  } catch (error) {
2196
- throw new DoomTeamExpectedError(ERROR_CODE_RUNTIME_UNAVAILABLE, error instanceof Error ? error.message : String(error), false, `Configure a valid external runtime or use ${PI_RUNTIME_REQUIREMENT}.`);
2381
+ throw new PoTeamExpectedError(ERROR_CODE_RUNTIME_UNAVAILABLE, error instanceof Error ? error.message : String(error), false, `Configure a valid external runtime or use ${PI_RUNTIME_REQUIREMENT}.`);
2197
2382
  }
2198
- if (!this.executableAvailable(command)) throw new DoomTeamExpectedError(ERROR_CODE_RUNTIME_UNAVAILABLE, `Executable '${command}' for runtime '${runtime}' is unavailable.`, false, `Install the executable, configure its absolute path, or use ${PI_RUNTIME_REQUIREMENT}.`);
2383
+ if (!this.executableAvailable(command)) throw new PoTeamExpectedError(ERROR_CODE_RUNTIME_UNAVAILABLE, `Executable '${command}' for runtime '${runtime}' is unavailable.`, false, `Install the executable, configure its absolute path, or use ${PI_RUNTIME_REQUIREMENT}.`);
2199
2384
  }
2200
2385
  }
2201
2386
  const concurrency = fanout ? request.concurrency ?? config.parallel?.concurrency ?? DEFAULT_PARALLEL_CONCURRENCY : 1;
@@ -2209,7 +2394,9 @@ var SpawnPlanner = class {
2209
2394
  identity: identities[childIndex],
2210
2395
  excludeTools: teamPackageExcludeTools,
2211
2396
  teamPackageModels,
2397
+ teamThinking: team.thinking,
2212
2398
  workflowPreferences,
2399
+ planningPreferences,
2213
2400
  capabilityCeiling,
2214
2401
  taskInput,
2215
2402
  childIndex,
@@ -2218,6 +2405,7 @@ var SpawnPlanner = class {
2218
2405
  parentSessionId: request.parentSessionId,
2219
2406
  parentForkSource: request.parentForkSource,
2220
2407
  sessionScope: request.sessionScope,
2408
+ ...request.sender ? { sender: request.sender } : {},
2221
2409
  environment: request.environment ?? {},
2222
2410
  parentSessionFile: request.parentSessionFile,
2223
2411
  maxLiveRuns,
@@ -2243,7 +2431,7 @@ var SpawnPlanner = class {
2243
2431
  //#endregion
2244
2432
  //#region src/services/delegationBridge/index.ts
2245
2433
  /**
2246
- * Serves `doom-task` through Team's session-bound delegation service: turn a
2434
+ * Serves `po-task` through Team's session-bound delegation service: turn a
2247
2435
  * request into a spawned run, report its progress, and settle it exactly once.
2248
2436
  *
2249
2437
  * WHY THIS IS NOT IN `pi.ts`:
@@ -2273,7 +2461,7 @@ const DELEGATION_PROGRESS_INTERVAL_MS = 250;
2273
2461
  const SETTLED_DELEGATION_WINDOW = 256;
2274
2462
  /**
2275
2463
  * Terminal states, named because they are an external contract with
2276
- * `doom-task`'s `DelegationManager`, which branches on the exact strings.
2464
+ * `po-task`'s `DelegationManager`, which branches on the exact strings.
2277
2465
  */
2278
2466
  const STATUS_COMPLETED = "completed";
2279
2467
  const STATUS_CANCELLED = "cancelled";
@@ -2295,7 +2483,7 @@ function createDelegationBridge(deps) {
2295
2483
  entry.disposeProgress?.();
2296
2484
  active.delete(entry.requestId);
2297
2485
  rememberSettled(entry.requestId);
2298
- ctx.emit(_agimon_ai_po_core_delegation.DOOM_DELEGATION_FINISHED_EVENT, result);
2486
+ ctx.emit(_agimon_ai_po_core_delegation.PO_DELEGATION_FINISHED_EVENT, result);
2299
2487
  };
2300
2488
  /** Ask the run to stop. Returns the failure message when the request itself failed. */
2301
2489
  const stop = (entry, reason) => {
@@ -2326,7 +2514,13 @@ function createDelegationBridge(deps) {
2326
2514
  timeoutWarningSent = true;
2327
2515
  const secondsRemaining = Math.max(1, Math.ceil(warningLeadMs / 1e3));
2328
2516
  const secondsLabel = `${secondsRemaining} second${secondsRemaining === 1 ? "" : "s"}`;
2329
- deps.management.steer(runId, `This delegation will time out in about ${secondsLabel}. Stop exploring now, complete the highest-value remaining work, and return a concise result before the deadline. If you cannot finish, return verified findings and blockers immediately.`).catch(() => void 0);
2517
+ deps.management.steer(runId, {
2518
+ text: `This delegation will time out in about ${secondsLabel}. Stop exploring now, complete the highest-value remaining work, and return a concise result before the deadline. If you cannot finish, return verified findings and blockers immediately.`,
2519
+ sender: {
2520
+ kind: "system",
2521
+ name: "Po"
2522
+ }
2523
+ }).catch(() => void 0);
2330
2524
  worked = true;
2331
2525
  }
2332
2526
  const progressKey = [
@@ -2339,7 +2533,7 @@ function createDelegationBridge(deps) {
2339
2533
  ].map((value) => String(value)).join(":");
2340
2534
  if (progressKey === lastProgress) return worked;
2341
2535
  lastProgress = progressKey;
2342
- ctx.emit(_agimon_ai_po_core_delegation.DOOM_DELEGATION_UPDATED_EVENT, {
2536
+ ctx.emit(_agimon_ai_po_core_delegation.PO_DELEGATION_UPDATED_EVENT, {
2343
2537
  requestId: entry.requestId,
2344
2538
  runId,
2345
2539
  ...job.status !== void 0 ? { status: job.status } : {},
@@ -2414,7 +2608,7 @@ function createDelegationBridge(deps) {
2414
2608
  settled: false
2415
2609
  };
2416
2610
  active.set(request.requestId, entry);
2417
- ctx.emit(_agimon_ai_po_core_delegation.DOOM_DELEGATION_ACCEPTED_EVENT, { requestId: request.requestId });
2611
+ ctx.emit(_agimon_ai_po_core_delegation.PO_DELEGATION_ACCEPTED_EVENT, { requestId: request.requestId });
2418
2612
  try {
2419
2613
  const forkSource = await session.captureForkSource?.();
2420
2614
  const outcome = (await deps.planner.spawn({
@@ -2429,8 +2623,10 @@ function createDelegationBridge(deps) {
2429
2623
  agentScope: "both",
2430
2624
  sessionScope: session.sessionScope,
2431
2625
  parentSessionId: session.sessionId,
2626
+ parentSelection: session.parentSelection,
2627
+ environment: session.environment,
2432
2628
  ...forkRequestFields(forkSource),
2433
- availableModels: session.availableModels,
2629
+ availableModels: await session.availableModels(),
2434
2630
  ...session.parentModel ? { parentModel: session.parentModel } : {}
2435
2631
  }, deps.loadConfig())).outcomes[0];
2436
2632
  if (!outcome?.runId) {
@@ -2453,10 +2649,15 @@ function createDelegationBridge(deps) {
2453
2649
  return;
2454
2650
  }
2455
2651
  entry.runtimeStartedAt = Date.now();
2456
- ctx.emit(_agimon_ai_po_core_delegation.DOOM_DELEGATION_STARTED_EVENT, {
2652
+ ctx.emit(_agimon_ai_po_core_delegation.PO_DELEGATION_STARTED_EVENT, {
2457
2653
  requestId: request.requestId,
2458
2654
  runId: outcome.runId
2459
2655
  });
2656
+ if (outcome.warning) try {
2657
+ await session.reportWarning?.(outcome.warning);
2658
+ } catch (error) {
2659
+ process.emitWarning(`Delegation warning could not be delivered: ${error instanceof Error ? error.message : String(error)}`);
2660
+ }
2460
2661
  await monitor(entry, request, ctx, jobs, session.sessionId, session.sessionScope);
2461
2662
  } catch (error) {
2462
2663
  finish(entry, {
@@ -2484,15 +2685,15 @@ function createDelegationBridge(deps) {
2484
2685
  createService(ctx, session) {
2485
2686
  const service = {
2486
2687
  sessionId: session.sessionId,
2487
- generation: `doom-delegation:${crypto.randomUUID()}`,
2688
+ generation: `po-delegation:${crypto.randomUUID()}`,
2488
2689
  async request(request) {
2489
2690
  if (!(0, typebox_value.Check)(_agimon_ai_po_core_delegation.DelegationRequestSchema, request)) throw new TypeError("Invalid delegation request.");
2490
- ctx.emit(_agimon_ai_po_core_delegation.DOOM_DELEGATION_REQUESTED_EVENT, request);
2691
+ ctx.emit(_agimon_ai_po_core_delegation.PO_DELEGATION_REQUESTED_EVENT, request);
2491
2692
  await onRequested(request, ctx, session);
2492
2693
  },
2493
2694
  cancel(request) {
2494
2695
  if (!(0, typebox_value.Check)(_agimon_ai_po_core_delegation.DelegationCancelSchema, request)) throw new TypeError("Invalid delegation cancel request.");
2495
- ctx.emit(_agimon_ai_po_core_delegation.DOOM_DELEGATION_CANCELLED_EVENT, request);
2696
+ ctx.emit(_agimon_ai_po_core_delegation.PO_DELEGATION_CANCELLED_EVENT, request);
2496
2697
  onCancelled(request.requestId, request.reason, ctx);
2497
2698
  }
2498
2699
  };
@@ -2541,7 +2742,7 @@ var SpawnHandshake = class {
2541
2742
  resolve(outcome);
2542
2743
  };
2543
2744
  removeMessage = options.child.onMessage((raw) => {
2544
- const message = require_externalProcessIpc.parseExternalRunnerMessage(raw, {
2745
+ const message = require_atomicJson.parseExternalRunnerMessage(raw, {
2545
2746
  runId: options.runId,
2546
2747
  scopeKey: options.scopeKey
2547
2748
  });
@@ -2580,7 +2781,7 @@ const FABLE_PROFILE_RESULT_FILE_NAME = "fable-profile-result.json";
2580
2781
  const DEFAULT_HANDSHAKE_TIMEOUT_MS = 1e4;
2581
2782
  /** `runs/<runId>` under the explicit session scope. */
2582
2783
  function runDirFor(scope, runId) {
2583
- return node_path.join(require_externalProcessIpc.scopeRunsDir(scope), runId);
2784
+ return node_path.join(require_atomicJson.scopeRunsDir(scope), runId);
2584
2785
  }
2585
2786
  function fableProfileResultPathFor(scope, runId) {
2586
2787
  return node_path.join(runDirFor(scope, runId), FABLE_PROFILE_RESULT_FILE_NAME);
@@ -2595,10 +2796,10 @@ function resolveRunnerEntry(builtRelativePath, sourceRelativePath, stem) {
2595
2796
  if (node_fs.existsSync(builtCandidate)) return builtCandidate;
2596
2797
  const sourceCandidate = node_path.join(directory, "src", `${sourceRelativePath}.ts`);
2597
2798
  if (node_fs.existsSync(sourceCandidate)) return sourceCandidate;
2598
- throw new Error(`Doom Team runner '${stem}' is unavailable at '${builtCandidate}' or '${sourceCandidate}'.`);
2799
+ throw new Error(`Po Team runner '${stem}' is unavailable at '${builtCandidate}' or '${sourceCandidate}'.`);
2599
2800
  }
2600
2801
  const parent = node_path.dirname(directory);
2601
- if (parent === directory) throw new Error(`Could not locate the Doom Team package root for runner '${stem}'.`);
2802
+ if (parent === directory) throw new Error(`Could not locate the Po Team package root for runner '${stem}'.`);
2602
2803
  directory = parent;
2603
2804
  }
2604
2805
  }
@@ -2653,7 +2854,7 @@ var AsyncSubagentSpawner = class {
2653
2854
  }
2654
2855
  child.unref();
2655
2856
  child.channel?.unref();
2656
- const endpoint = require_externalProcessIpc.childProcessEndpoint(child);
2857
+ const endpoint = require_atomicJson.childProcessEndpoint(child);
2657
2858
  return {
2658
2859
  pid: child.pid,
2659
2860
  onError: (handler) => child.on("error", handler),
@@ -2676,23 +2877,23 @@ var AsyncSubagentSpawner = class {
2676
2877
  const runDir = runDirFor(scope, runId);
2677
2878
  const env = {
2678
2879
  ...input.environment,
2679
- ...require_externalProcessIpc.sessionScopeEnvironment(scope),
2880
+ ...require_atomicJson.sessionScopeEnvironment(scope),
2680
2881
  [require_environment.SUBAGENT_RUN_ID_ENV]: runId
2681
2882
  };
2682
2883
  let fableLaunch;
2683
2884
  let launchConfig;
2684
2885
  const fail = (message) => {
2685
- if (fableLaunch) require_externalProcessIpc.cleanupClaudeFableLaunch(fableLaunch);
2886
+ if (fableLaunch) require_atomicJson.cleanupClaudeFableLaunch(fableLaunch);
2686
2887
  node_fs.rmSync(fableProfileResultPathFor(scope, runId), { force: true });
2687
2888
  throw new Error(message);
2688
2889
  };
2689
2890
  const ceiling = input.piArgs.capabilityCeiling;
2690
2891
  if (ceiling && (!input.externalProfile || !(ceiling.allowedExternalProfiles ?? []).includes(input.externalProfile))) return fail(`External profile '${input.externalProfile ?? "none"}' is denied by the active capability ceiling.`);
2691
- if (input.externalProfile !== void 0 && input.externalProfile !== require_externalProcessIpc.CLAUDE_FABLE_PROFILE) return fail(`External profile '${input.externalProfile}' is not trusted.`);
2692
- if (input.externalProfile === require_externalProcessIpc.CLAUDE_FABLE_PROFILE) {
2892
+ if (input.externalProfile !== void 0 && input.externalProfile !== require_atomicJson.CLAUDE_FABLE_PROFILE) return fail(`External profile '${input.externalProfile}' is not trusted.`);
2893
+ if (input.externalProfile === require_atomicJson.CLAUDE_FABLE_PROFILE) {
2693
2894
  if (runtime !== "claude" || input.piArgs.model !== "fable") return fail("The Fable profile requires runtime claude and model fable.");
2694
2895
  if (input.inlineAgent || input.piArgs.sessionFile || input.piArgs.parentSessionId) return fail("The Fable profile requires a fresh isolated context.");
2695
- fableLaunch = require_externalProcessIpc.prepareClaudeFableLaunch({
2896
+ fableLaunch = require_atomicJson.prepareClaudeFableLaunch({
2696
2897
  runId,
2697
2898
  prompt: task,
2698
2899
  repositoryCwd: cwd,
@@ -2713,7 +2914,7 @@ var AsyncSubagentSpawner = class {
2713
2914
  stdinPath: fableLaunch.stdinPath,
2714
2915
  cleanupPaths: fableLaunch.cleanupPaths,
2715
2916
  profileResultPath: fableProfileResultPathFor(scope, runId),
2716
- resultPath: node_path.join(require_externalProcessIpc.scopeResultsDir(scope), `${runId}.json`),
2917
+ resultPath: node_path.join(require_atomicJson.scopeResultsDir(scope), `${runId}.json`),
2717
2918
  internal: input.internal === true
2718
2919
  };
2719
2920
  } else launchConfig = {
@@ -2729,7 +2930,7 @@ var AsyncSubagentSpawner = class {
2729
2930
  }),
2730
2931
  cwd,
2731
2932
  env: Object.fromEntries(Object.entries(env).filter((entry) => typeof entry[1] === "string")),
2732
- resultPath: node_path.join(require_externalProcessIpc.scopeResultsDir(scope), `${runId}.json`),
2933
+ resultPath: node_path.join(require_atomicJson.scopeResultsDir(scope), `${runId}.json`),
2733
2934
  internal: input.internal === true
2734
2935
  };
2735
2936
  const child = this.spawnChild(scope, process.execPath, [resolveCliRunnerEntry()], {
@@ -2795,8 +2996,8 @@ const FABLE_STAGE = {
2795
2996
  interrupted: "interrupted"
2796
2997
  };
2797
2998
  const FABLE_EVENT = {
2798
- stageStarted: "doom_team.fable_stage_started",
2799
- finished: "doom_team.fable_finished"
2999
+ stageStarted: "po_team.fable_stage_started",
3000
+ finished: "po_team.fable_finished"
2800
3001
  };
2801
3002
  const SESSION_ENDED_REASON = "Fable bridge session ended.";
2802
3003
  const FABLE_ERROR = {
@@ -2986,7 +3187,7 @@ function createFablePlanBridge(deps) {
2986
3187
  return Object.freeze({
2987
3188
  ...provider,
2988
3189
  sessionId: session.sessionId,
2989
- generation: `doom-fable-plan:${crypto.randomUUID()}`
3190
+ generation: `po-fable-plan:${crypto.randomUUID()}`
2990
3191
  });
2991
3192
  },
2992
3193
  abandonAll() {
@@ -3174,7 +3375,7 @@ function parseTeamToolParams(raw) {
3174
3375
  if (!raw || typeof raw !== "object" || Array.isArray(raw)) throw invalidRequest("Intercom params must be an object.", "Use one documented intercom action shape.");
3175
3376
  const params = raw;
3176
3377
  const action = TEAM_ACTIONS.find((candidate) => candidate === params.action);
3177
- if (!action) throw new DoomTeamExpectedError("unsupported_operation", `Unsupported intercom action: ${String(params.action)}.`, false, "Use members, send, ask, pending, or reply.");
3378
+ if (!action) throw new PoTeamExpectedError("unsupported_operation", `Unsupported intercom action: ${String(params.action)}.`, false, "Use members, send, ask, pending, or reply.");
3178
3379
  if (!isOptionalString(params.to) || !isOptionalString(params.message) || !isOptionalString(params.requestId)) throw invalidRequest("Intercom to, message and requestId values must be strings.", "Correct the action fields and retry.");
3179
3380
  const allowed = new Set(action === "members" || action === "pending" ? ["action"] : action === "reply" ? [
3180
3381
  "action",
@@ -3287,7 +3488,14 @@ var NativeTeamDirectChannel = class {
3287
3488
  bindRuntime: (runtime) => {
3288
3489
  const member = this.members.get(memberId);
3289
3490
  if (!member || disposed) throw new Error(`Native team member '${memberId}' is no longer active.`);
3290
- member.deliver = (message) => runtime.steer(message.content);
3491
+ member.deliver = ({ content, details: { from } }) => runtime.steer({
3492
+ text: content,
3493
+ sender: from.role === "main" ? MAIN_AGENT_SENDER : {
3494
+ kind: "agent",
3495
+ id: from.runId ?? from.name,
3496
+ name: from.name
3497
+ }
3498
+ });
3291
3499
  return {
3292
3500
  name: NATIVE_TEAM_TOOL_NAME,
3293
3501
  description: "Communicate with active native agents in this root session.",
@@ -3385,7 +3593,7 @@ var NativeTeamDirectChannel = class {
3385
3593
  if (params.action === "reply") {
3386
3594
  const request = this.asks.get(params.requestId ?? "");
3387
3595
  const asker = request && this.members.get(request.fromMemberId);
3388
- if (!request || request.toMemberId !== memberId || !asker) throw new DoomTeamExpectedError("recipient_not_found", `No open intercom ask matches requestId '${params.requestId}'. It may already be answered, or its asker has finished.`, false, "Call intercom({\"action\":\"pending\"}) and retry with an exact requestId, or continue without replying.");
3596
+ if (!request || request.toMemberId !== memberId || !asker) throw new PoTeamExpectedError("recipient_not_found", `No open intercom ask matches requestId '${params.requestId}'. It may already be answered, or its asker has finished.`, false, "Call intercom({\"action\":\"pending\"}) and retry with an exact requestId, or continue without replying.");
3389
3597
  await this.deliver(asker, formatDirectMessage(member.context, "reply", request.id, message));
3390
3598
  this.closeAsk(request);
3391
3599
  return {
@@ -3400,7 +3608,7 @@ var NativeTeamDirectChannel = class {
3400
3608
  };
3401
3609
  }
3402
3610
  const target = this.findMember(params.to);
3403
- if (!target) throw new DoomTeamExpectedError("recipient_not_found", `Active intercom member '${params.to}' was not found.`, true, "Call intercom({\"action\":\"members\"}) and retry with an active member id.");
3611
+ if (!target) throw new PoTeamExpectedError("recipient_not_found", `Active intercom member '${params.to}' was not found.`, true, "Call intercom({\"action\":\"members\"}) and retry with an active member id.");
3404
3612
  const messageId = operationMessageId(memberId, operationId);
3405
3613
  const isAsk = params.action === "ask";
3406
3614
  const result = () => ({
@@ -3470,15 +3678,15 @@ var NativeTeamDirectChannel = class {
3470
3678
  }
3471
3679
  async deliver(target, message) {
3472
3680
  const id = target.context.memberId;
3473
- if (this.members.get(id) !== target) throw new DoomTeamExpectedError("communication_unavailable", `Intercom member '${id}' has finished.`, false, "Call intercom({\"action\":\"members\"}) to see who is active.");
3474
- if (!target.deliver) throw new DoomTeamExpectedError("communication_unavailable", `Intercom member '${id}' is not ready.`, true, "Retry after the child session starts.");
3681
+ if (this.members.get(id) !== target) throw new PoTeamExpectedError("communication_unavailable", `Intercom member '${id}' has finished.`, false, "Call intercom({\"action\":\"members\"}) to see who is active.");
3682
+ if (!target.deliver) throw new PoTeamExpectedError("communication_unavailable", `Intercom member '${id}' is not ready.`, true, "Retry after the child session starts.");
3475
3683
  target.inFlight += 1;
3476
3684
  try {
3477
3685
  await target.deliver(message);
3478
3686
  target.delivered = true;
3479
3687
  } catch (error) {
3480
- if (error instanceof DoomTeamExpectedError) throw error;
3481
- throw new DoomTeamExpectedError("communication_unavailable", `Intercom member '${id}' could not receive the message: ${error instanceof Error ? error.message : String(error)}`, true, "Retry shortly, or continue without it.");
3688
+ if (error instanceof PoTeamExpectedError) throw error;
3689
+ throw new PoTeamExpectedError("communication_unavailable", `Intercom member '${id}' could not receive the message: ${error instanceof Error ? error.message : String(error)}`, true, "Retry shortly, or continue without it.");
3482
3690
  } finally {
3483
3691
  target.inFlight -= 1;
3484
3692
  target.release?.(true);
@@ -3505,7 +3713,7 @@ var TeamChannelRuntime = class {
3505
3713
  }
3506
3714
  execute(operationId, rawParams) {
3507
3715
  const context = this.context;
3508
- if (!context || !this.directChannel) throw new DoomTeamExpectedError("communication_unavailable", "Intercom is not active for this session.", true, "Wait for session startup or reload Doom Team.");
3716
+ if (!context || !this.directChannel) throw new PoTeamExpectedError("communication_unavailable", "Intercom is not active for this session.", true, "Wait for session startup or reload Po Team.");
3509
3717
  return this.directChannel.execute(context.memberId, operationId, rawParams);
3510
3718
  }
3511
3719
  bindMainSession(rootSessionId) {
@@ -3562,51 +3770,80 @@ var NativeTeamChannelService = class {
3562
3770
  };
3563
3771
  //#endregion
3564
3772
  //#region src/services/headlessIntercomTool/index.ts
3773
+ /**
3774
+ * Finds the peer a `to` value names: its session ID first, then its session
3775
+ * name, ignoring case, so an agent can use the name a person typed. A name two
3776
+ * peers share is refused with their IDs rather than guessed.
3777
+ */
3778
+ function resolvePeer(peers, to) {
3779
+ const byId = peers.find((peer) => peer.sessionId === to);
3780
+ if (byId !== void 0) return byId;
3781
+ const wanted = to.toLowerCase();
3782
+ const named = peers.filter((peer) => peer.name.trim().toLowerCase() === wanted);
3783
+ if (named.length > 1) throw invalidRequest(`${String(named.length)} sessions are named "${to}".`, `Send to one session ID: ${named.map((peer) => peer.sessionId).join(", ")}.`);
3784
+ return named[0];
3785
+ }
3786
+ function describePeerLine(peer) {
3787
+ const details = [
3788
+ `session ${peer.sessionId}`,
3789
+ ...peer.profile === void 0 ? [] : [`profile ${peer.profile}`],
3790
+ ...peer.sharedGroups.length === 0 ? [] : [`shared groups: ${peer.sharedGroups.join(", ")}`]
3791
+ ];
3792
+ return `- ${peer.name.trim() === "" ? peer.sessionId : peer.name} (${details.join("; ")}): use send; it can reply to you the same way`;
3793
+ }
3565
3794
  function createHeadlessIntercomTool(channel, sessions) {
3566
3795
  return {
3567
3796
  name: "intercom",
3568
3797
  label: "Intercom",
3569
3798
  description: "Communicate with active agents and related live sessions.",
3570
3799
  parameters: TeamToolParamsSchema,
3571
- promptGuidelines: ["Send only new progress, blockers, or decisions. Do not repeat task briefs or delegation instructions.", "Use members to find related sessions, then send to their session ID to delegate work such as workflow recovery. Session peers use send, not ask/reply."],
3800
+ promptGuidelines: ["Send only new progress, blockers, or decisions. Do not repeat task briefs or delegation instructions.", "Use members to find related sessions by the names people give them, then send to that name or its session ID. Session peers use send, not ask/reply, and can send back."],
3572
3801
  executionMode: "serial",
3573
3802
  async execute(toolCallId, parameters, signal, onUpdate) {
3574
3803
  const params = parseTeamToolParams(parameters);
3575
3804
  const peers = channel.current() === void 0 ? [] : sessions?.peers() ?? [];
3576
3805
  const to = params.to?.trim();
3577
- if (sessions !== void 0 && to !== void 0 && peers.includes(to)) {
3578
- if (params.action !== "send") throw invalidRequest("Session peers support send only.", "Use send with the session ID.");
3806
+ const knownId = channel.current() !== void 0 && to !== void 0 && sessions?.canCommunicate(to) === true;
3807
+ const teamMember = to !== void 0 && channel.snapshot().members.some((member) => member.name === to) && !knownId && !peers.some((peer) => peer.sessionId === to);
3808
+ const peer = sessions === void 0 || to === void 0 || teamMember ? void 0 : knownId ? peers.find((candidate) => candidate.sessionId === to) : resolvePeer(peers, to);
3809
+ const recipientId = knownId ? to : peer?.sessionId;
3810
+ if (sessions !== void 0 && recipientId !== void 0) {
3811
+ if (params.action !== "send") throw invalidRequest("Session peers support send only.", "Use send with the session name or ID.");
3579
3812
  const message = validateMessage(params.message);
3580
3813
  const delivery = sessions.delivery();
3581
3814
  if (delivery === void 0) throw new Error("Session delivery is unavailable.");
3815
+ const senderName = sessions.name?.()?.trim() || sessions.sessionId;
3816
+ const toName = peer?.name.trim() || recipientId;
3582
3817
  const receipt = await delivery.deliver({
3583
3818
  deliveryId: `intercom:${sessions.sessionId}:${toolCallId}`,
3584
- recipientKey: to,
3819
+ recipientKey: recipientId,
3585
3820
  kind: "intercom_message",
3586
- prompt: `Message from session ${sessions.sessionId} via intercom.\n\n${message}\n\nReply using intercom({ action: "send", to: "${sessions.sessionId}", message: "..." }).`,
3821
+ prompt: `Message from session ${senderName} via intercom.\n\n${message}\n\nReply using intercom({ action: "send", to: ${JSON.stringify(senderName)}, message: "..." }).`,
3587
3822
  delivery: "steer"
3588
3823
  });
3589
3824
  return {
3590
3825
  content: [{
3591
3826
  type: "text",
3592
- text: `Message queued for session ${to}.`
3827
+ text: `Message queued for session ${toName}.`
3593
3828
  }],
3594
3829
  details: {
3595
3830
  ...receipt,
3596
- to
3831
+ to: recipientId,
3832
+ toName
3597
3833
  }
3598
3834
  };
3599
3835
  }
3600
- const result = (0, _agimon_ai_po_core_headless.toDoomHeadlessToolResult)(await channel.execute(toolCallId, parameters, signal, onUpdate && ((partial) => onUpdate((0, _agimon_ai_po_core_headless.toDoomHeadlessToolResult)(partial)))));
3836
+ const result = (0, _agimon_ai_po_core_headless.toPoHeadlessToolResult)(await channel.execute(toolCallId, parameters, signal, onUpdate && ((partial) => onUpdate((0, _agimon_ai_po_core_headless.toPoHeadlessToolResult)(partial)))));
3601
3837
  if (params.action !== "members" || peers.length === 0) return result;
3602
3838
  return {
3603
3839
  ...result,
3604
3840
  content: [...result.content, {
3605
3841
  type: "text",
3606
- text: peers.map((id) => `- ${id}: related session (send only)`).join("\n")
3842
+ text: peers.map(describePeerLine).join("\n")
3607
3843
  }],
3608
- details: { members: [...channel.snapshot().members, ...peers.map((id) => ({
3609
- name: id,
3844
+ details: { members: [...channel.snapshot().members, ...peers.map((peer) => ({
3845
+ name: peer.name || peer.sessionId,
3846
+ sessionId: peer.sessionId,
3610
3847
  role: "session"
3611
3848
  }))] }
3612
3849
  };
@@ -3728,6 +3965,7 @@ var AsyncJobTracker = class {
3728
3965
  startedAt: projection.startedAt,
3729
3966
  updatedAt: projection.updatedAt,
3730
3967
  ...projection.error === void 0 ? {} : { error: projection.error },
3968
+ ...projection.promptWithheld ? { promptWithheld: true } : {},
3731
3969
  ...projection.summary === void 0 ? {} : { summary: projection.summary },
3732
3970
  ...projection.tokens === void 0 ? {} : { tokens: projection.tokens },
3733
3971
  ...projection.cost === void 0 ? {} : { cost: projection.cost },
@@ -3939,7 +4177,7 @@ function formatDuration(ms) {
3939
4177
  */
3940
4178
  const MAX_RETAINED_EVENTS = 1e3;
3941
4179
  const NEWLINE_BYTE = 10;
3942
- function isRecord$1(value) {
4180
+ function isRecord$2(value) {
3943
4181
  return typeof value === "object" && value !== null && !Array.isArray(value);
3944
4182
  }
3945
4183
  function parseLine(line) {
@@ -3947,7 +4185,7 @@ function parseLine(line) {
3947
4185
  if (!trimmed) return void 0;
3948
4186
  try {
3949
4187
  const parsed = JSON.parse(trimmed);
3950
- return isRecord$1(parsed) ? parsed : void 0;
4188
+ return isRecord$2(parsed) ? parsed : void 0;
3951
4189
  } catch {
3952
4190
  return;
3953
4191
  }
@@ -3982,7 +4220,7 @@ function parseArgsPayload(payload) {
3982
4220
  if (!payload) return void 0;
3983
4221
  try {
3984
4222
  const parsed = JSON.parse(payload);
3985
- return isRecord$1(parsed) ? parsed : void 0;
4223
+ return isRecord$2(parsed) ? parsed : void 0;
3986
4224
  } catch {
3987
4225
  return;
3988
4226
  }
@@ -4177,125 +4415,63 @@ function readFleetTranscript(transcriptPath) {
4177
4415
  warning: tail.warning
4178
4416
  } : { events: tail.events };
4179
4417
  }
4180
- //#endregion
4181
- //#region src/services/suspendedRuns/index.ts
4418
+ function contentText(content) {
4419
+ if (typeof content === "string") return content;
4420
+ if (!Array.isArray(content)) return "";
4421
+ return content.flatMap((part) => isRecord$2(part) && part.type === "text" && typeof part.text === "string" ? [part.text] : []).join("\n");
4422
+ }
4182
4423
  /**
4183
- * Runs stopped by a session shutdown, and enough about each to start it again.
4184
- *
4185
- * WHY EVERY SHUTDOWN SUSPENDS, WITH NO SPECIAL CASE FOR `reload`:
4186
- * Pi emits `session_shutdown` for `quit`, `reload`, `new`, `resume` and `fork`.
4187
- * An earlier design kept children alive across `reload` alone, on the grounds
4188
- * that `/domains`, `/major-mode` and `/profile` reload the extension rather than
4189
- * change the session. That is true, and it still makes `reload` the one case
4190
- * behaving differently from the other four - which is a rule someone has to
4191
- * remember, and a branch that silently does the wrong thing if Pi ever adds a
4192
- * sixth reason. Suspending uniformly costs a respawn on reload and removes the
4193
- * special case; restore is cheap because the child continues its own transcript
4194
- * rather than starting over.
4195
- *
4196
- * WHY RESTORE IS OFFERED AND NEVER AUTOMATIC:
4197
- * Reopening a session would otherwise spawn N processes and start spending
4198
- * tokens on tasks that may be days stale. `session_start` reports what is
4199
- * suspended; something explicit has to ask for it back.
4200
- *
4201
- * AVOID:
4202
- * - Auto-restoring from any lifecycle event
4203
- * - Recording a suspended run without its `sessionFile`; without it a restore
4204
- * restarts the work instead of continuing it
4424
+ * Events of a native run's durable transcript page, so a native run renders through the same tail as a file
4425
+ * transcript. Entries are projected messages: `{ type: 'message', timestamp, message }` with Pi message roles.
4205
4426
  */
4206
- const SUSPENDED_RUN_VERSION = 1;
4207
- const JSON_SUFFIX = ".json";
4208
- function suspendedPath(scope, runId) {
4209
- return node_path.join(require_externalProcessIpc.scopeSuspendedDir(scope), `${runId}${JSON_SUFFIX}`);
4210
- }
4211
- function suspendRun(scope, record) {
4212
- require_atomicJson.writeAtomicJson(suspendedPath(scope, record.runId), {
4213
- version: SUSPENDED_RUN_VERSION,
4214
- ...record
4215
- });
4216
- }
4217
- function parseSuspendedRun(raw) {
4218
- let parsed;
4219
- try {
4220
- parsed = JSON.parse(raw);
4221
- } catch {
4222
- return;
4223
- }
4224
- const result = parseVersioned(parsed, [SUSPENDED_RUN_VERSION]);
4225
- return result.ok && typeof result.value.runId === "string" ? result.value : void 0;
4226
- }
4227
- function listSuspendedRuns(scope) {
4228
- let entries;
4229
- try {
4230
- entries = node_fs.readdirSync(require_externalProcessIpc.scopeSuspendedDir(scope));
4231
- } catch {
4232
- return [];
4233
- }
4234
- const runs = [];
4427
+ function fleetEventsFromEntries(entries) {
4428
+ const events = [];
4429
+ const calls = /* @__PURE__ */ new Map();
4235
4430
  for (const entry of entries) {
4236
- if (!entry.endsWith(JSON_SUFFIX)) continue;
4237
- let run;
4238
- try {
4239
- run = parseSuspendedRun(node_fs.readFileSync(node_path.join(require_externalProcessIpc.scopeSuspendedDir(scope), entry), "utf-8"));
4240
- } catch {
4241
- continue;
4431
+ if (!isRecord$2(entry) || entry.type !== "message" || !isRecord$2(entry.message)) continue;
4432
+ const message = entry.message;
4433
+ const at = typeof entry.timestamp === "number" ? entry.timestamp : 0;
4434
+ if (message.role === "user") {
4435
+ const text = contentText(message.content);
4436
+ if (text.trim()) events.push({
4437
+ kind: "user",
4438
+ at,
4439
+ text
4440
+ });
4441
+ } else if (message.role === "assistant") {
4442
+ const parts = splitAssistantContent(message.content);
4443
+ for (const thinking of parts?.thinking ?? []) events.push({
4444
+ kind: "thinking",
4445
+ at,
4446
+ text: thinking
4447
+ });
4448
+ if (parts?.text.trim()) events.push({
4449
+ kind: "assistant",
4450
+ at,
4451
+ text: parts.text,
4452
+ ...typeof message.model === "string" ? { model: message.model } : {}
4453
+ });
4454
+ for (const part of Array.isArray(message.content) ? message.content : []) {
4455
+ if (!isRecord$2(part) || part.type !== "toolCall" || typeof part.id !== "string") continue;
4456
+ const event = {
4457
+ kind: "tool",
4458
+ at,
4459
+ text: "",
4460
+ ...typeof part.name === "string" ? { name: part.name } : {},
4461
+ status: "running",
4462
+ ...isRecord$2(part.arguments) ? { args: part.arguments } : {}
4463
+ };
4464
+ calls.set(part.id, event);
4465
+ events.push(event);
4466
+ }
4467
+ } else if (message.role === "toolResult" && typeof message.toolCallId === "string") {
4468
+ const call = calls.get(message.toolCallId);
4469
+ if (!call) continue;
4470
+ call.result = contentText(message.content);
4471
+ call.status = message.isError === true ? "error" : "ok";
4242
4472
  }
4243
- if (run) runs.push(run);
4244
- }
4245
- return runs.sort((left, right) => left.suspendedAt - right.suspendedAt);
4246
- }
4247
- async function listSuspendedRunsAsync(scope) {
4248
- let entries;
4249
- try {
4250
- entries = await node_fs.promises.readdir(require_externalProcessIpc.scopeSuspendedDir(scope));
4251
- } catch {
4252
- return [];
4253
- }
4254
- const runs = [];
4255
- for (const entry of entries) {
4256
- if (!entry.endsWith(JSON_SUFFIX)) continue;
4257
- try {
4258
- const run = parseSuspendedRun(await node_fs.promises.readFile(node_path.join(require_externalProcessIpc.scopeSuspendedDir(scope), entry), "utf-8"));
4259
- if (run) runs.push(run);
4260
- } catch {}
4261
- }
4262
- return runs.sort((left, right) => left.suspendedAt - right.suspendedAt);
4263
- }
4264
- /** Drop a record once its run has been restored, or explicitly discarded. */
4265
- function clearSuspendedRun(scope, runId) {
4266
- try {
4267
- node_fs.rmSync(suspendedPath(scope, runId), { force: true });
4268
- } catch {}
4269
- }
4270
- /** Whether an explicit restore can safely continue this exact run. */
4271
- function isSuspendedRunResumable(run) {
4272
- if (run.runtime !== "pi" || !run.agent.trim() || !run.task.trim() || !run.cwd.trim() || !run.sessionFile) return false;
4273
- try {
4274
- node_fs.accessSync(run.sessionFile, node_fs.constants.R_OK);
4275
- return true;
4276
- } catch {
4277
- return false;
4278
4473
  }
4279
- }
4280
- /** The identity prefix for a suspended line, empty for a record written before identities existed. */
4281
- function suspendedLabel(run) {
4282
- const label = formatAgentIdentity(run.identity, run.inline);
4283
- return label ? `${label}, ` : "";
4284
- }
4285
- /** One line per suspended run, for the report `session_start` prints. */
4286
- function formatSuspendedRuns(runs) {
4287
- if (runs.length === 0) return "";
4288
- const lines = runs.map((run) => {
4289
- const continues = isSuspendedRunResumable(run) ? "resumable" : "not resumable";
4290
- return `- ${run.runId} (${suspendedLabel(run)}${run.agent}, ${run.runtime}, ${continues}): ${run.task.split("\n")[0]}`;
4291
- });
4292
- const noun = runs.length === 1 ? "subagent" : "subagents";
4293
- return [
4294
- `${runs.length} suspended ${noun} from this session:`,
4295
- ...lines,
4296
- "",
4297
- "They are stopped. Restore one with subagent {\"action\":\"restore\",\"id\":\"<run-id>\"}, or leave them."
4298
- ].join("\n");
4474
+ return events;
4299
4475
  }
4300
4476
  function age(job, now) {
4301
4477
  return job.startedAt ? formatDuration(Math.max(0, now - job.startedAt)) : "unknown";
@@ -4306,8 +4482,8 @@ function age(job, now) {
4306
4482
  * Takes `now` rather than calling `Date.now()` so a test asserting rendered
4307
4483
  * ages does not have to freeze global time.
4308
4484
  */
4309
- function formatFleetView(jobs, now = Date.now(), suspended = []) {
4310
- if (jobs.length === 0 && suspended.length === 0) return "No runs tracked in this session. A run appears here once it has been launched from this session.";
4485
+ function formatFleetView(jobs, now = Date.now()) {
4486
+ if (jobs.length === 0) return "No runs tracked in this session. A run appears here once it has been launched from this session.";
4311
4487
  const lines = [`${jobs.length} active run${jobs.length === 1 ? "" : "s"}:`];
4312
4488
  for (const job of jobs) {
4313
4489
  const parts = [`- ${job.runId}`];
@@ -4318,18 +4494,8 @@ function formatFleetView(jobs, now = Date.now(), suspended = []) {
4318
4494
  if (job.error) parts.push(`error: ${job.error}`);
4319
4495
  lines.push(parts.join(" · "));
4320
4496
  }
4321
- if (suspended.length > 0) {
4322
- lines.push("", `${suspended.length} suspended run${suspended.length === 1 ? "" : "s"}:`);
4323
- for (const run of suspended) {
4324
- const recovery = isSuspendedRunResumable(run) ? `restore with { action: "restore", id: "${run.runId}" }` : "not resumable; submit a new explicit run";
4325
- const label = formatAgentIdentity(run.identity, run.inline);
4326
- lines.push(`- ${run.runId} (${label ? `${label}, ` : ""}${run.agent}, ${run.runtime}): ${recovery}`);
4327
- }
4328
- }
4329
- if (jobs.length > 0) {
4330
- lines.push("");
4331
- lines.push(`Inspect one with { action: "status", id: "<run id>", transcriptLines: 80 }.`);
4332
- }
4497
+ lines.push("");
4498
+ lines.push(`Inspect one with { action: "status", id: "<run id>", transcriptLines: 80 }.`);
4333
4499
  return lines.join("\n");
4334
4500
  }
4335
4501
  /** Tool output shown to the model, bounded so one long result cannot crowd out the rest of the tail. */
@@ -4362,11 +4528,25 @@ function formatEvent(event) {
4362
4528
  */
4363
4529
  function formatRunTranscript(status, maxLines) {
4364
4530
  const transcriptPath = status?.transcriptPath;
4365
- if (!transcriptPath) return status ? "This run has no transcript. Artifacts were disabled for it (artifacts: false), so nothing was recorded." : "No status found for this run, so there is no transcript to read.";
4531
+ if (!transcriptPath) return status ? "This run has no transcript to read." : "No status found for this run, so there is no transcript to read.";
4366
4532
  const transcript = readFleetTranscript(transcriptPath);
4367
4533
  if (transcript.warning) return `Transcript at '${transcriptPath}' could not be read: ${transcript.warning}`;
4368
4534
  if (transcript.events.length === 0) return `Transcript at '${transcriptPath}' is empty. The run has not written anything yet.`;
4369
- const rendered = transcript.events.flatMap((event) => formatEvent(event).split("\n"));
4535
+ return formatTail(transcript.events, maxLines);
4536
+ }
4537
+ /**
4538
+ * A native run's transcript tail, read from its durable conversation rather than a file.
4539
+ *
4540
+ * ponytail: `entries` is one page of the newest entries, so the "of N lines" count covers that page, not the
4541
+ * whole run; read older pages first if a caller needs the full count.
4542
+ */
4543
+ function formatNativeRunTranscript(entries, maxLines) {
4544
+ const events = fleetEventsFromEntries(entries);
4545
+ if (events.length === 0) return "The run has no transcript entries yet.";
4546
+ return formatTail(events, maxLines);
4547
+ }
4548
+ function formatTail(events, maxLines) {
4549
+ const rendered = events.flatMap((event) => formatEvent(event).split("\n"));
4370
4550
  const kept = rendered.slice(-maxLines);
4371
4551
  const dropped = rendered.length - kept.length;
4372
4552
  return [
@@ -4384,7 +4564,7 @@ function hashArguments(args) {
4384
4564
  }
4385
4565
  function journalPath(scope, operationId) {
4386
4566
  const safeId = (0, node_crypto.createHash)(HASH_ALGORITHM).update(operationId).digest(HASH_ENCODING);
4387
- return node_path.join(require_externalProcessIpc.scopeRunsDir(scope), "..", "operations", `${safeId}.json`);
4567
+ return node_path.join(require_atomicJson.scopeRunsDir(scope), "..", "operations", `${safeId}.json`);
4388
4568
  }
4389
4569
  function readRecord(file) {
4390
4570
  return JSON.parse(node_fs.readFileSync(file, "utf8"));
@@ -4414,7 +4594,7 @@ function startOperation(scope, operationId, args, runIds) {
4414
4594
  } catch (error) {
4415
4595
  if (!(error instanceof Error && "code" in error && error.code === "EEXIST")) throw error;
4416
4596
  const existing = readRecord(file);
4417
- if (existing.argumentHash !== argumentHash) throw new DoomTeamExpectedError("operation_conflict", `Operation '${operationId}' was already used with different arguments.`, false, "Submit the operation as a new tool call.");
4597
+ if (existing.argumentHash !== argumentHash) throw new PoTeamExpectedError("operation_conflict", `Operation '${operationId}' was already used with different arguments.`, false, "Submit the operation as a new tool call.");
4418
4598
  return {
4419
4599
  kind: "replay",
4420
4600
  record: existing
@@ -4451,7 +4631,6 @@ function progressMessage(params) {
4451
4631
  case require_subagentTool.SUBAGENT_ACTIONS.run: return `Starting ${params.requests.length} subagent${params.requests.length === 1 ? "" : "s"}...`;
4452
4632
  case require_subagentTool.SUBAGENT_ACTIONS.steer: return `Steering subagent ${params.id}...`;
4453
4633
  case require_subagentTool.SUBAGENT_ACTIONS.stop: return `Requesting stop for subagent ${params.id}...`;
4454
- case require_subagentTool.SUBAGENT_ACTIONS.restore: return `Restoring subagent ${params.id}...`;
4455
4634
  default: return;
4456
4635
  }
4457
4636
  }
@@ -4479,12 +4658,6 @@ function publicAgent(agent) {
4479
4658
  ...tools.length ? { tools } : {}
4480
4659
  };
4481
4660
  }
4482
- function publicSuspendedRun(run) {
4483
- return {
4484
- ...run,
4485
- resumable: isSuspendedRunResumable(run)
4486
- };
4487
- }
4488
4661
  /** One agent in full, as the model reads it. Shared with the headless tool. */
4489
4662
  function formatAgentDetail(agent) {
4490
4663
  const detail = publicAgent(agent);
@@ -4514,7 +4687,7 @@ function validateParams(input) {
4514
4687
  requireNonblank(record, "id", action);
4515
4688
  requireNonblank(record, "message", action);
4516
4689
  }
4517
- if (action === require_subagentTool.SUBAGENT_ACTIONS.stop || action === require_subagentTool.SUBAGENT_ACTIONS.restore) requireNonblank(record, "id", action);
4690
+ if (action === require_subagentTool.SUBAGENT_ACTIONS.stop) requireNonblank(record, "id", action);
4518
4691
  return raw;
4519
4692
  }
4520
4693
  var SubagentToolService = class {
@@ -4531,7 +4704,7 @@ var SubagentToolService = class {
4531
4704
  this.environment = environment;
4532
4705
  }
4533
4706
  sessionScope(ctx) {
4534
- return require_externalProcessIpc.createSessionScope((0, _agimon_ai_po_core_childProcess.resolveRootSessionId)(ctx.sessionManager.getSessionId(), this.environment));
4707
+ return require_atomicJson.createSessionScope((0, _agimon_ai_po_core_childProcess.resolveRootSessionId)(ctx.sessionManager.getSessionId(), this.environment));
4535
4708
  }
4536
4709
  trackOutcomes(result, ctx) {
4537
4710
  const scope = this.sessionScope(ctx);
@@ -4579,7 +4752,7 @@ var SubagentToolService = class {
4579
4752
  const operation = startOperation(scope, operationId, params, params.requests.map(() => (0, node_crypto.randomUUID)()));
4580
4753
  if (operation.kind === "replay") {
4581
4754
  if (operation.record.state === "completed" && operation.record.result) return operation.record.result;
4582
- throw new DoomTeamExpectedError("delivery_unconfirmed", `Operation '${operationId}' is already pending for runs: ${operation.record.runIds.join(", ")}.`, true, "Call subagent({\"action\":\"status\"}) and do not submit the run again.");
4755
+ throw new PoTeamExpectedError("delivery_unconfirmed", `Operation '${operationId}' is already pending for runs: ${operation.record.runIds.join(", ")}.`, true, "Call subagent({\"action\":\"status\"}) and do not submit the run again.");
4583
4756
  }
4584
4757
  const result = this.trackOutcomes(await this.planner.spawn(this.buildSpawnRequest(operationId, params, ctx, operation.record.runIds), loadConfig().config), ctx);
4585
4758
  const started = result.outcomes.filter((outcome) => outcome.runId);
@@ -4587,7 +4760,7 @@ var SubagentToolService = class {
4587
4760
  const outcomeLines = result.outcomes.map((outcome) => {
4588
4761
  return `- ${formatAgentIdentity(outcome.identity, outcome.inline) ?? outcome.agent}: ${outcome.runId ? outcome.runId : `failed: ${outcome.error ?? "unknown error"}`}${outcome.warning ? `\n Warning: ${outcome.warning}` : ""}`;
4589
4762
  });
4590
- if (started.length === 0 && failed.length > 0) throw new DoomTeamExpectedError("runtime_unavailable", `No requested subagent started.\n${outcomeLines.join("\n")}`, true, "Correct the reported launch failures. If an agent name is uncertain, call subagent({\"action\":\"agents\"}) before retrying only corrected requests.");
4763
+ if (started.length === 0 && failed.length > 0) throw new PoTeamExpectedError("runtime_unavailable", `No requested subagent started.\n${outcomeLines.join("\n")}`, true, "Correct the reported launch failures. If an agent name is uncertain, call subagent({\"action\":\"agents\"}) before retrying only corrected requests.");
4591
4764
  const subagentLabel = result.outcomes.length === 1 ? "subagent" : "subagents";
4592
4765
  const summary = failed.length === 0 ? `Started ${started.length} ${subagentLabel}:` : `Started ${started.length}/${result.outcomes.length} ${subagentLabel}; ${failed.length} failed:`;
4593
4766
  const next = failed.length === 0 ? "Completion will arrive asynchronously. Continue only non-overlapping work, or end your turn." : "Completion will arrive asynchronously for started runs. Do not resubmit them; retry only corrected failed entries.";
@@ -4604,44 +4777,35 @@ var SubagentToolService = class {
4604
4777
  completeOperation(scope, operationId, operation.record, response);
4605
4778
  return response;
4606
4779
  }
4607
- executeAgents(params, ctx) {
4780
+ async executeAgents(params, ctx) {
4608
4781
  const cwd = params.cwd ?? ctx.cwd;
4609
4782
  const scope = scopeOrDefault(params.scope);
4610
4783
  if (!params.name) {
4611
- const result = this.discovery.discover(cwd, scope);
4784
+ const result = await this.discovery.discover(cwd, scope);
4612
4785
  return textResult(formatAgentList(result.agents), { agents: result.agents.map(publicAgent) });
4613
4786
  }
4614
- const agent = this.discovery.find(cwd, scope, params.name);
4787
+ const agent = await this.discovery.find(cwd, scope, params.name);
4615
4788
  if (!agent) {
4616
- const candidates = this.discovery.discover(cwd, scope).agents.map((candidate) => candidate.name).toSorted();
4617
- throw new DoomTeamExpectedError("agent_not_found", `No executable agent matches '${params.name}'.${candidates.length ? ` Available: ${candidates.join(", ")}.` : ""}`, false, "Call subagent({\"action\":\"agents\"}) and retry with an exact name.");
4789
+ const candidates = (await this.discovery.discover(cwd, scope)).agents.map((candidate) => candidate.name).toSorted();
4790
+ throw new PoTeamExpectedError("agent_not_found", `No executable agent matches '${params.name}'.${candidates.length ? ` Available: ${candidates.join(", ")}.` : ""}`, false, "Call subagent({\"action\":\"agents\"}) and retry with an exact name.");
4618
4791
  }
4619
4792
  return textResult(formatAgentDetail(agent), { agent: publicAgent(agent) });
4620
4793
  }
4621
- async executeManagement(params, ctx, signal, preallocatedRunIds, operationId) {
4794
+ async executeManagement(params, ctx, signal) {
4622
4795
  const scope = this.sessionScope(ctx);
4623
4796
  this.management.bindSessionScope(scope);
4624
4797
  const jobs = this.tracker.forSession(ctx.sessionManager.getSessionId(), scope);
4625
4798
  switch (params.action) {
4626
4799
  case require_subagentTool.SUBAGENT_ACTIONS.status: {
4627
- const suspendedRuns = listSuspendedRuns(scope);
4628
4800
  if (!("id" in params)) {
4629
4801
  if ("transcriptLines" in params && params.transcriptLines !== void 0) throw invalidRequest("transcriptLines requires a run id.", "Add id or omit transcriptLines for fleet status.");
4630
4802
  const runs = jobs.list();
4631
- return textResult(formatFleetView(runs, Date.now(), suspendedRuns), {
4632
- fleet: runs,
4633
- suspended: suspendedRuns.map(publicSuspendedRun)
4634
- });
4803
+ return textResult(formatFleetView(runs, Date.now()), { fleet: runs });
4635
4804
  }
4636
4805
  const runId = params.id;
4637
4806
  if (!runId) throw invalidRequest("transcriptLines requires a run id.", "Add id or omit transcriptLines for fleet status.");
4638
- const suspended = suspendedRuns.find((run) => run.runId === runId);
4639
- if (suspended && params.transcriptLines === void 0) {
4640
- const recovery = isSuspendedRunResumable(suspended) ? `Restore it with { action: "restore", id: "${suspended.runId}" }.` : "It is not resumable; submit a new explicit run.";
4641
- return textResult(`Run '${suspended.runId}' is suspended. ${recovery}`, { suspended: publicSuspendedRun(suspended) });
4642
- }
4643
4807
  const result = this.management.status(runId);
4644
- if (!result.status && !result.runDir && !result.resultPath && !suspended) throw new DoomTeamExpectedError("run_not_found", `No run matches '${runId}'.`, false, "Call subagent({\"action\":\"status\"}) and retry with an exact id.");
4808
+ if (!result.status && !result.runDir && !result.resultPath) throw new PoTeamExpectedError("run_not_found", `No run matches '${runId}'.`, false, "Call subagent({\"action\":\"status\"}) and retry with an exact id.");
4645
4809
  if (params.transcriptLines !== void 0) return textResult(formatRunTranscript(result.status, params.transcriptLines ?? 80), { transcript: { runId: result.runId } });
4646
4810
  return textResult(result.status ? `Run '${result.runId}': ${result.status.state}` : `Run '${result.runId}' has no status yet.`, { status: result });
4647
4811
  }
@@ -4653,44 +4817,13 @@ var SubagentToolService = class {
4653
4817
  case require_subagentTool.SUBAGENT_ACTIONS.steer: {
4654
4818
  const id = resolveTrackedRunId(jobs, params.id);
4655
4819
  const runtime = jobs.get(id)?.runtime;
4656
- if (runtime && !isPiRuntime(runtime)) throw new DoomTeamExpectedError("unsupported_operation", `Run '${id}' uses '${runtime}', which does not support steering.`, false, `Use subagent({"action":"stop","id":"${id}"}) to terminate it.`);
4657
- const result = await this.management.steer(id, params.message, void 0, signal);
4820
+ if (runtime && !isPiRuntime(runtime)) throw new PoTeamExpectedError("unsupported_operation", `Run '${id}' uses '${runtime}', which does not support steering.`, false, `Use subagent({"action":"stop","id":"${id}"}) to terminate it.`);
4821
+ const result = await this.management.steer(id, {
4822
+ text: params.message,
4823
+ sender: MAIN_AGENT_SENDER
4824
+ }, void 0, signal);
4658
4825
  return textResult(`Steer request '${result.requestId}' for '${id}' is ${result.state}: ${result.message}`, { steer: result });
4659
4826
  }
4660
- case require_subagentTool.SUBAGENT_ACTIONS.suspended: {
4661
- const runs = listSuspendedRuns(scope);
4662
- return textResult(runs.length ? formatSuspendedRuns(runs) : "No suspended subagents in this session.", { suspended: runs.map(publicSuspendedRun) });
4663
- }
4664
- case require_subagentTool.SUBAGENT_ACTIONS.restore: {
4665
- const record = listSuspendedRuns(scope).find((run) => run.runId === params.id);
4666
- if (!record) throw new DoomTeamExpectedError("run_not_found", `No suspended run matches '${params.id}'.`, false, "Call subagent({\"action\":\"suspended\"}) and retry with an exact id.");
4667
- if (!isSuspendedRunResumable(record)) throw new DoomTeamExpectedError("not_resumable", `Suspended run '${params.id}' does not have complete, readable Pi recovery state.`, false, "Submit a new explicit run request instead of restoring this record.");
4668
- const outcome = this.trackOutcomes(await this.planner.spawn({
4669
- single: {
4670
- agent: record.agent,
4671
- ...record.inlineAgent ? { inlineAgent: record.inlineAgent } : {},
4672
- task: record.task,
4673
- cwd: record.cwd,
4674
- ...record.model ? { model: record.model } : {},
4675
- sessionFile: record.sessionFile,
4676
- ...record.identity ? { identity: record.identity } : {}
4677
- },
4678
- cwd: record.cwd,
4679
- agentScope: "both",
4680
- sessionScope: scope,
4681
- parentSessionId: ctx.sessionManager.getSessionId(),
4682
- availableModels: authenticatedModelInfos(ctx.modelRegistry),
4683
- ...operationId ? { operationId } : {},
4684
- ...preallocatedRunIds ? { preallocatedRunIds } : {}
4685
- }, loadConfig().config), ctx).outcomes[0];
4686
- if (!outcome?.runId) throw new DoomTeamExpectedError("not_resumable", `Could not restore '${params.id}': ${outcome?.error ?? "the spawn produced no run."}`, true, "Inspect suspended state, then submit a new explicit run if recovery is not possible.");
4687
- clearSuspendedRun(scope, params.id);
4688
- const restoredAs = formatAgentIdentity(outcome.identity, outcome.inline) ?? outcome.runId;
4689
- return textResult(`Restored '${params.id}' as '${restoredAs}' (${outcome.runId}), continuing its transcript.`, { restore: {
4690
- ...outcome,
4691
- restoredFrom: params.id
4692
- } });
4693
- }
4694
4827
  }
4695
4828
  }
4696
4829
  async execute(id, rawParams, signal, onUpdate, ctx) {
@@ -4699,22 +4832,22 @@ var SubagentToolService = class {
4699
4832
  if (progress) onUpdate?.(progressResult(progress, params.action));
4700
4833
  if (params.action === require_subagentTool.SUBAGENT_ACTIONS.run) return this.executeRun(id, params, ctx);
4701
4834
  if (params.action === require_subagentTool.SUBAGENT_ACTIONS.agents) return this.executeAgents(params, ctx);
4702
- if (!(params.action === require_subagentTool.SUBAGENT_ACTIONS.steer || params.action === require_subagentTool.SUBAGENT_ACTIONS.stop || params.action === require_subagentTool.SUBAGENT_ACTIONS.restore)) return this.executeManagement(params, ctx, signal);
4835
+ if (!(params.action === require_subagentTool.SUBAGENT_ACTIONS.steer || params.action === require_subagentTool.SUBAGENT_ACTIONS.stop)) return this.executeManagement(params, ctx, signal);
4703
4836
  const scope = this.sessionScope(ctx);
4704
4837
  this.management.bindSessionScope(scope);
4705
- const operation = startOperation(scope, id, params, params.action === require_subagentTool.SUBAGENT_ACTIONS.restore ? [(0, node_crypto.randomUUID)()] : []);
4838
+ const operation = startOperation(scope, id, params, []);
4706
4839
  if (operation.kind === "replay") {
4707
4840
  if (operation.record.state === "completed" && operation.record.result) return operation.record.result;
4708
- throw new DoomTeamExpectedError("delivery_unconfirmed", `Operation '${id}' is already pending.`, true, "Inspect run status before retrying this control operation.");
4841
+ throw new PoTeamExpectedError("delivery_unconfirmed", `Operation '${id}' is already pending.`, true, "Inspect run status before retrying this control operation.");
4709
4842
  }
4710
- const response = await this.executeManagement(params, ctx, signal, operation.record.runIds, id);
4843
+ const response = await this.executeManagement(params, ctx, signal);
4711
4844
  completeOperation(scope, id, operation.record, response);
4712
4845
  return response;
4713
4846
  }
4714
4847
  };
4715
4848
  //#endregion
4716
4849
  //#region src/services/headlessSubagentTool/index.ts
4717
- const SUBAGENT_DESCRIPTION = "Discover agents, start and manage persistent background subagent runs, and inspect suspended work.";
4850
+ const SUBAGENT_DESCRIPTION = "Discover agents, start and manage persistent background subagent runs.";
4718
4851
  /**
4719
4852
  * Every result carries the text the MODEL reads and the structured details the
4720
4853
  * cockpit card reads. The text is always given explicitly: a serialized detail
@@ -4750,25 +4883,24 @@ function scopeOf(value) {
4750
4883
  return value === "user" || value === "project" ? value : "both";
4751
4884
  }
4752
4885
  function createHeadlessSubagentTool(runtime, initialExecution) {
4753
- const scope = require_externalProcessIpc.createSessionScope(initialExecution.sessionId);
4886
+ const scope = require_atomicJson.createSessionScope(initialExecution.sessionId);
4754
4887
  const jobs = runtime.asyncJobTracker.forSession(initialExecution.sessionId, scope);
4755
4888
  return {
4756
4889
  name: "subagent",
4757
4890
  label: "Subagent",
4758
4891
  description: SUBAGENT_DESCRIPTION,
4759
4892
  parameters: require_subagentTool.SubagentToolSchema,
4760
- promptSnippet: "Discover, run, inspect, steer, stop, and restore persistent subagents",
4761
- promptGuidelines: ["Runs are persistent background work. Do not resubmit a run that already returned an id.", "Use status or suspended before retrying a failed or interrupted operation."],
4893
+ promptSnippet: "Discover, run, inspect, steer, and stop persistent subagents",
4894
+ promptGuidelines: ["Runs are persistent background work. Do not resubmit a run that already returned an id.", "Use status before retrying a failed or interrupted operation."],
4762
4895
  executionMode: "serial",
4763
4896
  async execute(_toolCallId, parameters, signal, onUpdate, execution = initialExecution) {
4764
4897
  try {
4765
4898
  const params = validateParams(parameters);
4766
- const availableModels = execution.getAvailableModels?.().map(toModelInfo) ?? (execution.model ? [toModelInfo(execution.model)] : []);
4767
4899
  if (params.action === require_subagentTool.SUBAGENT_ACTIONS.agents) {
4768
4900
  const scope = scopeOf(params.scope);
4769
- const agents = runtime.discovery.discover(params.cwd ?? execution.cwd, scope).agents;
4770
- const selected = params.name ? runtime.discovery.find(params.cwd ?? execution.cwd, scope, params.name) : void 0;
4771
- if (params.name && !selected) throw new DoomTeamExpectedError("agent_not_found", `No executable agent matches '${params.name}'.`, false, "Call subagent({\"action\":\"agents\"}) and retry with an exact agent name.");
4901
+ const agents = (await runtime.discovery.discover(params.cwd ?? execution.cwd, scope)).agents;
4902
+ const selected = params.name ? await runtime.discovery.find(params.cwd ?? execution.cwd, scope, params.name) : void 0;
4903
+ if (params.name && !selected) throw new PoTeamExpectedError("agent_not_found", `No executable agent matches '${params.name}'.`, false, "Call subagent({\"action\":\"agents\"}) and retry with an exact agent name.");
4772
4904
  if (selected) return result(formatAgentDetail(selected), { agents: [publicAgent(selected)] });
4773
4905
  return result(formatAgentList(agents), { agents: agents.map((agent) => ({
4774
4906
  name: agent.name,
@@ -4794,12 +4926,13 @@ function createHeadlessSubagentTool(runtime, initialExecution) {
4794
4926
  })),
4795
4927
  cwd: execution.cwd,
4796
4928
  agentScope: scopeOf(params.scope),
4797
- sessionScope: require_externalProcessIpc.createSessionScope(execution.sessionId),
4929
+ sessionScope: require_atomicJson.createSessionScope(execution.sessionId),
4798
4930
  environment: execution.environment,
4799
4931
  parentSessionId: execution.sessionId,
4932
+ parentSelection: execution.selection,
4800
4933
  ...params.concurrency === void 0 ? {} : { concurrency: params.concurrency },
4801
4934
  ...params.artifacts === void 0 ? {} : { artifacts: params.artifacts },
4802
- availableModels,
4935
+ availableModels: await availableModelInfos(execution),
4803
4936
  ...execution.model ? { parentModel: execution.model } : {},
4804
4937
  ...parentForkSource ? { parentForkSource } : {}
4805
4938
  }, loadConfig().config);
@@ -4815,19 +4948,13 @@ function createHeadlessSubagentTool(runtime, initialExecution) {
4815
4948
  return result(formatFleetView(runs), { runs });
4816
4949
  }
4817
4950
  const status = runtime.management.statusAsync ? await runtime.management.statusAsync(params.id) : runtime.management.status(params.id);
4818
- return result([status.status ? [`Run '${status.runId}': ${status.status.state}`, status.status.summary ? `Summary: ${status.status.summary}` : void 0].filter((line) => line !== void 0).join("\n") : `Run '${status.runId}' has no status yet.`, params.transcriptLines === void 0 ? void 0 : formatRunTranscript(status.status, params.transcriptLines)].filter((text) => text !== void 0).join("\n\n"), {
4951
+ const statusText = status.status ? [`Run '${status.runId}': ${status.status.state}`, status.status.summary ? `Summary: ${status.status.summary}` : void 0].filter((line) => line !== void 0).join("\n") : `Run '${status.runId}' has no status yet.`;
4952
+ const nativeEntries = params.transcriptLines === void 0 || status.status?.transcriptPath !== void 0 ? void 0 : await runtime.nativeRuns.readTranscript(execution.sessionId, status.runId, params.transcriptLines);
4953
+ return result([statusText, params.transcriptLines === void 0 ? void 0 : nativeEntries !== void 0 ? formatNativeRunTranscript(nativeEntries, params.transcriptLines) : formatRunTranscript(status.status, params.transcriptLines)].filter((text) => text !== void 0).join("\n\n"), {
4819
4954
  runId: status.runId,
4820
4955
  status: status.status
4821
4956
  });
4822
4957
  }
4823
- if (params.action === require_subagentTool.SUBAGENT_ACTIONS.suspended) {
4824
- const suspended = listSuspendedRuns(require_externalProcessIpc.createSessionScope(execution.sessionId));
4825
- const text = suspended.length ? formatSuspendedRuns(suspended) : "No suspended subagents in this session.";
4826
- return result(text, {
4827
- suspended,
4828
- text
4829
- });
4830
- }
4831
4958
  const id = resolveTrackedRunId(jobs, params.id);
4832
4959
  if (params.action === require_subagentTool.SUBAGENT_ACTIONS.stop) {
4833
4960
  const control = await runtime.management.stop(id, params.reason);
@@ -4836,40 +4963,14 @@ function createHeadlessSubagentTool(runtime, initialExecution) {
4836
4963
  control
4837
4964
  });
4838
4965
  }
4839
- if (params.action === require_subagentTool.SUBAGENT_ACTIONS.steer) {
4840
- const steer = await runtime.management.steer(id, params.message, void 0, signal);
4841
- return result(`Steer request '${steer.requestId}' for '${id}' is ${steer.state}: ${steer.message}`, {
4842
- runId: id,
4843
- steer
4844
- });
4845
- }
4846
- const suspended = listSuspendedRuns(require_externalProcessIpc.createSessionScope(execution.sessionId)).find((item) => item.runId === params.id);
4847
- if (!suspended) throw new Error(`No suspended run matches '${params.id}'.`);
4848
- if (!isSuspendedRunResumable(suspended)) throw new Error(`Suspended run '${params.id}' is not resumable.`);
4849
- const outcome = (await runtime.spawnPlanner.spawn({
4850
- single: {
4851
- agent: suspended.agent,
4852
- ...suspended.inlineAgent ? { inlineAgent: suspended.inlineAgent } : {},
4853
- task: suspended.task,
4854
- cwd: suspended.cwd,
4855
- ...suspended.model ? { model: suspended.model } : {},
4856
- sessionFile: suspended.sessionFile,
4857
- ...suspended.identity ? { identity: suspended.identity } : {}
4858
- },
4859
- cwd: suspended.cwd,
4860
- agentScope: "both",
4861
- sessionScope: require_externalProcessIpc.createSessionScope(execution.sessionId),
4862
- environment: execution.environment,
4863
- runtime: "pi",
4864
- parentSessionId: execution.sessionId,
4865
- availableModels
4866
- }, loadConfig().config)).outcomes[0];
4867
- if (!outcome?.runId) throw new Error(`Could not restore '${params.id}': ${outcome?.error ?? "the spawn produced no run."}`);
4868
- clearSuspendedRun(require_externalProcessIpc.createSessionScope(execution.sessionId), params.id);
4869
- return result(`Restored '${params.id}' as '${outcome.runId}', continuing its transcript.`, { restore: {
4870
- ...outcome,
4871
- restoredFrom: params.id
4872
- } });
4966
+ const steer = await runtime.management.steer(id, {
4967
+ text: params.message,
4968
+ sender: MAIN_AGENT_SENDER
4969
+ }, void 0, signal);
4970
+ return result(`Steer request '${steer.requestId}' for '${id}' is ${steer.state}: ${steer.message}`, {
4971
+ runId: id,
4972
+ steer
4973
+ });
4873
4974
  } catch (error) {
4874
4975
  const message = error instanceof Error ? error.message : String(error);
4875
4976
  return result(message, message, true);
@@ -4879,7 +4980,7 @@ function createHeadlessSubagentTool(runtime, initialExecution) {
4879
4980
  }
4880
4981
  //#endregion
4881
4982
  //#region src/services/mcpTools/index.ts
4882
- const TEAM_MCP_TOOLS_SERVICE = "doom/team-mcp-tools";
4983
+ const TEAM_MCP_TOOLS_SERVICE = "po/team-mcp-tools";
4883
4984
  function mountMcpTools(tools) {
4884
4985
  return (context) => {
4885
4986
  context.plugin((providerContext) => {
@@ -4929,7 +5030,7 @@ function subscribeNativeRunProjection(sessionId, listener) {
4929
5030
  if (closed) return;
4930
5031
  closed = true;
4931
5032
  projection.listeners.delete(listener);
4932
- if (projection.listeners.size === 0 && projection.runs.size === 0) sessions.delete(sessionId);
5033
+ if (projection.listeners.size === 0 && projection.runs.size === 0 && sessions.get(sessionId) === projection) sessions.delete(sessionId);
4933
5034
  };
4934
5035
  }
4935
5036
  //#endregion
@@ -5145,7 +5246,7 @@ function formatGroupedCompletion(details) {
5145
5246
  *
5146
5247
  * Separate from `formatSingleCompletion` because the two have different
5147
5248
  * readers. That one is written for the model and embeds the run's full result
5148
- * preview; this one goes to `DoomHeadlessClient.notify`, which collapses every
5249
+ * preview; this one goes to `PoHeadlessClient.notify`, which collapses every
5149
5250
  * newline to a space and truncates at 4096 characters
5150
5251
  * (`packages/core/po-core/src/schemas/notification.ts`), and on the web
5151
5252
  * additionally drives a browser notification. Feeding the model-facing text to
@@ -5218,7 +5319,7 @@ function buildCompletionDetails(result) {
5218
5319
  * The custom-message type the parent renders completions under. The literal is
5219
5320
  * shared by the producer here and the TUI renderer registered for it
5220
5321
  * (`(frontend)/message/_lib/subagent-notify.cli.ts`, which draws through
5221
- * `completionNotice.ts`), and by the headless facet, which persists the same
5322
+ * `completionNotice.ts`), and by the server plugin, which persists the same
5222
5323
  * type as a session entry so a cockpit transcript records what was delivered.
5223
5324
  */
5224
5325
  const SUBAGENT_NOTIFY_MESSAGE_TYPE = "subagent-notify";
@@ -5344,41 +5445,149 @@ function active(job) {
5344
5445
  "stopped"
5345
5446
  ])).has(job.status);
5346
5447
  }
5347
- function suspendedRecord(job, reason, suspendedAt) {
5448
+ /**
5449
+ * Stops the live external runs of a session that ends. A native run is a conversation of the session's own
5450
+ * Harness and resumes with it, so it is left alone.
5451
+ */
5452
+ async function stopScopeRuns(options) {
5453
+ const jobs = options.jobs.filter((job) => !job.native && active(job));
5454
+ const outcomes = await Promise.allSettled(jobs.map((job) => options.stop(job.runId, options.reason)));
5348
5455
  return {
5349
- runId: job.runId,
5350
- agent: job.agent ?? "unknown",
5351
- ...job.identity === void 0 ? {} : { identity: job.identity },
5352
- ...job.inline === void 0 ? {} : { inline: job.inline },
5353
- runtime: job.runtime ?? (job.native ? "pi" : "external"),
5354
- task: job.task ?? "",
5355
- cwd: job.cwd ?? "",
5356
- ...job.status === void 0 ? {} : { lastStatus: job.status },
5357
- ...job.sessionFile === void 0 ? {} : { sessionFile: job.sessionFile },
5358
- suspendedAt,
5359
- reason
5456
+ stopped: jobs.map((job) => job.runId),
5457
+ unstoppable: jobs.filter((_, index) => outcomes[index]?.status === "rejected").map((job) => job.runId)
5360
5458
  };
5361
5459
  }
5362
- /** Persist resumable metadata, then stop every live run through its typed owner. */
5363
- async function suspendScopeRuns(options) {
5364
- const jobs = options.jobs.filter(active);
5365
- const suspendedAt = options.now?.() ?? Date.now();
5366
- for (const job of jobs) suspendRun(options.scope, suspendedRecord(job, options.reason, suspendedAt));
5367
- const outcomes = await Promise.allSettled(jobs.map((job) => options.stop(job.runId, options.reason)));
5460
+ //#endregion
5461
+ //#region src/schemas/team/packageConfig.ts
5462
+ const PO_TEAM_PACKAGE = "@agimon-ai/po-team";
5463
+ const TEAM_CONFIG_KEYS = ["models", "excludeTools"];
5464
+ const TEAM_MODEL_KEYS = ["model", "thinking"];
5465
+ const THINKING_VALUES = /* @__PURE__ */ new Set([
5466
+ "off",
5467
+ "minimal",
5468
+ "low",
5469
+ "medium",
5470
+ "high",
5471
+ "xhigh",
5472
+ "max"
5473
+ ]);
5474
+ function isRecord$1(value) {
5475
+ return typeof value === "object" && value !== null && !Array.isArray(value);
5476
+ }
5477
+ function assertKnownKeys(value, keys, location) {
5478
+ const unsupported = Object.keys(value).filter((key) => !keys.includes(key));
5479
+ if (unsupported.length > 0) throw new Error(`${location} has unsupported field(s): ${unsupported.join(", ")}`);
5480
+ }
5481
+ /** Validate and normalize one Team-owned package configuration mapping. */
5482
+ function parseTeamPackageConfig(value, location) {
5483
+ if (!isRecord$1(value)) throw new Error(`${location} must be a mapping`);
5484
+ assertKnownKeys(value, TEAM_CONFIG_KEYS, location);
5485
+ const hasModels = Object.hasOwn(value, "models");
5486
+ const hasExcludeTools = Object.hasOwn(value, "excludeTools");
5487
+ if (!hasModels && !hasExcludeTools) throw new Error(`${location} must define models or excludeTools`);
5488
+ let models;
5489
+ if (hasModels) {
5490
+ if (!Array.isArray(value.models) || value.models.length === 0) throw new Error(`${location}.models must be a non-empty array`);
5491
+ models = value.models.map((entry, index) => {
5492
+ const entryLocation = `${location}.models[${index}]`;
5493
+ if (!isRecord$1(entry)) throw new Error(`${entryLocation} must be a mapping`);
5494
+ assertKnownKeys(entry, TEAM_MODEL_KEYS, entryLocation);
5495
+ if (typeof entry.model !== "string" || !entry.model.trim()) throw new Error(`${entryLocation}.model must be a non-empty string`);
5496
+ if (entry.thinking !== void 0 && (typeof entry.thinking !== "string" || !THINKING_VALUES.has(entry.thinking))) throw new Error(`${entryLocation}.thinking must be one of: ${[...THINKING_VALUES].join(", ")}`);
5497
+ return {
5498
+ model: entry.model.trim(),
5499
+ ...entry.thinking ? { thinking: entry.thinking } : {}
5500
+ };
5501
+ });
5502
+ }
5503
+ let excludeTools;
5504
+ if (hasExcludeTools) {
5505
+ if (!Array.isArray(value.excludeTools) || value.excludeTools.length === 0) throw new Error(`${location}.excludeTools must be a non-empty array`);
5506
+ excludeTools = [...new Set(value.excludeTools.map((entry, index) => {
5507
+ if (typeof entry !== "string" || !entry.trim()) throw new Error(`${location}.excludeTools[${index}] must be a non-empty string`);
5508
+ return entry.trim();
5509
+ }))];
5510
+ }
5368
5511
  return {
5369
- suspended: jobs.map((job) => job.runId),
5370
- unstoppable: jobs.filter((_, index) => outcomes[index]?.status === "rejected").map((job) => job.runId)
5512
+ ...models ? { models } : {},
5513
+ ...excludeTools ? { excludeTools } : {}
5371
5514
  };
5372
5515
  }
5373
- /** Async form used by session startup. */
5374
- async function openScopeAsync(scope) {
5516
+ /** Merge Team configurations contributed by selected layers in selection order. */
5517
+ function mergeTeamPackageConfigurations(entries) {
5518
+ let models;
5519
+ const excludeTools = /* @__PURE__ */ new Set();
5520
+ let hasExcludeTools = false;
5521
+ for (const entry of entries) {
5522
+ const location = `Package "${entry.specifier}" config in layer "${entry.layer}" of .po/modes.yaml`;
5523
+ const next = parseTeamPackageConfig(entry.config, location);
5524
+ if (next.models) models = next.models.map((model) => ({ ...model }));
5525
+ if (next.excludeTools) {
5526
+ hasExcludeTools = true;
5527
+ for (const tool of next.excludeTools) excludeTools.add(tool);
5528
+ }
5529
+ }
5530
+ if (!models && !hasExcludeTools) return void 0;
5375
5531
  return {
5376
- pruned: [],
5377
- reaped: 0,
5378
- suspended: await listSuspendedRunsAsync(scope)
5532
+ ...models ? { models } : {},
5533
+ ...hasExcludeTools ? { excludeTools: [...excludeTools] } : {}
5379
5534
  };
5380
5535
  }
5381
5536
  //#endregion
5537
+ //#region src/services/teamAgentConfig/index.ts
5538
+ const PO_TEAM_AGENT_CONFIG_SERVICE = "po/team-agent-config";
5539
+ /** Normalize Team's ordered models without duplicating a known thinking suffix. */
5540
+ function teamModelSpecs(config) {
5541
+ return config?.models?.map(({ model, thinking }) => thinking ? `${model.replace(/:(?:off|minimal|low|medium|high|xhigh|max)$/, "")}:${thinking}` : model);
5542
+ }
5543
+ /** Session-local Team policy, loaded once for each injected config snapshot. */
5544
+ var TeamAgentConfigService = class {
5545
+ io;
5546
+ snapshot;
5547
+ loads = /* @__PURE__ */ new WeakMap();
5548
+ constructor(io) {
5549
+ this.io = io;
5550
+ }
5551
+ bind(snapshot) {
5552
+ this.snapshot = snapshot;
5553
+ return () => {
5554
+ if (this.snapshot === snapshot) this.snapshot = void 0;
5555
+ };
5556
+ }
5557
+ current() {
5558
+ if (!this.snapshot) return Promise.reject(new PoTeamExpectedError("runtime_unavailable", "Team agent configuration is not loaded yet.", true, "Retry after the session configuration is ready."));
5559
+ const snapshot = this.snapshot();
5560
+ const cached = this.loads.get(snapshot);
5561
+ if (cached) return cached;
5562
+ const load = this.load(snapshot).catch((error) => {
5563
+ this.loads.delete(snapshot);
5564
+ throw error;
5565
+ });
5566
+ this.loads.set(snapshot, load);
5567
+ return load;
5568
+ }
5569
+ currentOrUndefined() {
5570
+ return this.snapshot ? this.current() : Promise.resolve(void 0);
5571
+ }
5572
+ async load(snapshot) {
5573
+ const { fs, homeDirectory, environment } = this.io;
5574
+ if (!snapshot.harness.root) return { planningSubagents: snapshot.settings.modes?.planning?.subagents };
5575
+ const modes = await (0, _agimon_ai_po_config_majorModes.readMajorModesConfig)(fs, snapshot.harness.root, _agimon_ai_po_core_platform.BACKGROUND_CONTEXT, {
5576
+ homeDirectory,
5577
+ environment
5578
+ });
5579
+ const configurations = await (0, _agimon_ai_po_config_majorModes.readPackageConfigurations)(fs, modes, [...snapshot.harness.layers], PO_TEAM_PACKAGE, _agimon_ai_po_core_platform.BACKGROUND_CONTEXT);
5580
+ const config = mergeTeamPackageConfigurations(configurations);
5581
+ return {
5582
+ models: teamModelSpecs(config),
5583
+ thinking: config?.models?.[0]?.thinking,
5584
+ excludeTools: config?.excludeTools,
5585
+ planningSubagents: snapshot.settings.modes?.planning?.subagents,
5586
+ ...config ? { path: configurations.at(-1)?.filePath ?? node_path.join(snapshot.harness.root, ".po", "modes.yaml") } : {}
5587
+ };
5588
+ }
5589
+ };
5590
+ //#endregion
5382
5591
  //#region src/services/directRunBackgroundWork/index.ts
5383
5592
  const PROVIDER_NAME = "team-direct-runs";
5384
5593
  /** Publish direct Team runs owned by exactly one Pi session. */
@@ -5406,7 +5615,7 @@ function assertPolicy(policy) {
5406
5615
  /** Publishes Team's capability intersection store through a Cordis service. */
5407
5616
  function createSubagentPolicyService(store) {
5408
5617
  const service = {
5409
- generation: `doom-subagent-policy:${crypto.randomUUID()}`,
5618
+ generation: `po-subagent-policy:${crypto.randomUUID()}`,
5410
5619
  register(initialPolicy) {
5411
5620
  assertPolicy(initialPolicy);
5412
5621
  const owner = initialPolicy.owner;
@@ -5438,7 +5647,7 @@ function createSubagentPolicyService(store) {
5438
5647
  //#region src/services/teamCollaboration/index.ts
5439
5648
  /** Mount every Team-owned collaboration capability in one session fiber. */
5440
5649
  function teamCollaborationPlugin(ctx, config) {
5441
- const backgroundWork = (0, _agimon_ai_po_core_backgroundWork.readDoomBackgroundWorkService)(ctx);
5650
+ const backgroundWork = (0, _agimon_ai_po_core_backgroundWork.readPoBackgroundWorkService)(ctx);
5442
5651
  if (backgroundWork === void 0) throw new Error("Team requires the Po Session foundation.");
5443
5652
  const subagentPolicy = createSubagentPolicyService(config.policies);
5444
5653
  const delegation = config.delegation.createService(ctx, config.session);
@@ -5448,28 +5657,28 @@ function teamCollaborationPlugin(ctx, config) {
5448
5657
  cwd: config.session.cwd,
5449
5658
  environment: config.session.environment
5450
5659
  });
5451
- ctx.provide(require_subagentPolicy.DOOM_SUBAGENT_POLICY_SERVICE, subagentPolicy);
5452
- ctx.provide(_agimon_ai_po_core_delegation.DOOM_DELEGATION_SERVICE, delegation);
5453
- ctx.provide(require_fablePlanApi.DOOM_FABLE_PLAN_SERVICE, fablePlan);
5660
+ ctx.provide(require_subagentPolicy.PO_SUBAGENT_POLICY_SERVICE, subagentPolicy);
5661
+ ctx.provide(_agimon_ai_po_core_delegation.PO_DELEGATION_SERVICE, delegation);
5662
+ ctx.provide(require_fablePlanApi.PO_FABLE_PLAN_SERVICE, fablePlan);
5454
5663
  registerDirectRunBackgroundWork(ctx, backgroundWork, config.session.sessionId, config.directRunTracker);
5455
5664
  if (config.observeDelegation) {
5456
- ctx.on(_agimon_ai_po_core_delegation.DOOM_DELEGATION_REQUESTED_EVENT, (event) => config.observeDelegation?.({
5665
+ ctx.on(_agimon_ai_po_core_delegation.PO_DELEGATION_REQUESTED_EVENT, (event) => config.observeDelegation?.({
5457
5666
  kind: "requested",
5458
5667
  event
5459
5668
  }));
5460
- ctx.on(_agimon_ai_po_core_delegation.DOOM_DELEGATION_STARTED_EVENT, (event) => config.observeDelegation?.({
5669
+ ctx.on(_agimon_ai_po_core_delegation.PO_DELEGATION_STARTED_EVENT, (event) => config.observeDelegation?.({
5461
5670
  kind: "started",
5462
5671
  event
5463
5672
  }));
5464
- ctx.on(_agimon_ai_po_core_delegation.DOOM_DELEGATION_UPDATED_EVENT, (event) => config.observeDelegation?.({
5673
+ ctx.on(_agimon_ai_po_core_delegation.PO_DELEGATION_UPDATED_EVENT, (event) => config.observeDelegation?.({
5465
5674
  kind: "updated",
5466
5675
  event
5467
5676
  }));
5468
- ctx.on(_agimon_ai_po_core_delegation.DOOM_DELEGATION_FINISHED_EVENT, (event) => config.observeDelegation?.({
5677
+ ctx.on(_agimon_ai_po_core_delegation.PO_DELEGATION_FINISHED_EVENT, (event) => config.observeDelegation?.({
5469
5678
  kind: "finished",
5470
5679
  event
5471
5680
  }));
5472
- ctx.on(_agimon_ai_po_core_delegation.DOOM_DELEGATION_CANCELLED_EVENT, (event) => config.observeDelegation?.({
5681
+ ctx.on(_agimon_ai_po_core_delegation.PO_DELEGATION_CANCELLED_EVENT, (event) => config.observeDelegation?.({
5473
5682
  kind: "cancelled",
5474
5683
  event
5475
5684
  }));
@@ -5540,11 +5749,11 @@ var ManagementActions = class {
5540
5749
  if (exact) return exact;
5541
5750
  const matches = runs.filter((run) => run.runId.startsWith(id));
5542
5751
  if (matches.length === 1) return matches[0];
5543
- if (matches.length > 1) throw new DoomTeamExpectedError("run_not_found", `Multiple current-session runs match '${id}'.`, false, "Retry with a longer run id.");
5752
+ if (matches.length > 1) throw new PoTeamExpectedError("run_not_found", `Multiple current-session runs match '${id}'.`, false, "Retry with a longer run id.");
5544
5753
  }
5545
5754
  requireActiveJob(id) {
5546
5755
  const job = this.resolveJob(id);
5547
- if (!job) throw new DoomTeamExpectedError("run_not_found", `No active run matches '${id}'.`, false, "Call subagent({\"action\":\"status\"}) and retry with an exact run id.");
5756
+ if (!job) throw new PoTeamExpectedError("run_not_found", `No active run matches '${id}'.`, false, "Call subagent({\"action\":\"status\"}) and retry with an exact run id.");
5548
5757
  return job;
5549
5758
  }
5550
5759
  status(id) {
@@ -5558,7 +5767,20 @@ var ManagementActions = class {
5558
5767
  };
5559
5768
  }
5560
5769
  async statusAsync(id) {
5561
- return this.status(id);
5770
+ const live = this.status(id);
5771
+ if (live.status || !this.nativeRuns?.reported) return live;
5772
+ const run = await this.nativeRuns.reported(id);
5773
+ if (!run?.state) return live;
5774
+ return {
5775
+ ...live,
5776
+ status: statusProjection({
5777
+ runId: id,
5778
+ agent: run.agent,
5779
+ task: run.task,
5780
+ status: run.state,
5781
+ native: true
5782
+ })
5783
+ };
5562
5784
  }
5563
5785
  list() {
5564
5786
  return { runs: this.sessionJobs().list() };
@@ -5574,11 +5796,11 @@ var ManagementActions = class {
5574
5796
  const job = this.requireActiveJob(id);
5575
5797
  const requestId = (0, node_crypto.randomUUID)();
5576
5798
  if (job.native) {
5577
- if (!this.nativeRuns?.get(scope.rootSessionId, job.runId)) throw new DoomTeamExpectedError("run_not_found", `Native run '${job.runId}' is no longer active.`, false, "List active runs and retry with a current run id.");
5799
+ if (!this.nativeRuns?.get(scope.rootSessionId, job.runId)) throw new PoTeamExpectedError("run_not_found", `Native run '${job.runId}' is no longer active.`, false, "List active runs and retry with a current run id.");
5578
5800
  await this.nativeRuns.stop(scope.rootSessionId, job.runId, reason);
5579
5801
  return { requestId };
5580
5802
  }
5581
- if (!this.externalProcesses?.has(scope, job.runId)) throw new DoomTeamExpectedError("run_not_found", `External run '${job.runId}' is no longer active.`, false, "List active runs and retry with a current run id.");
5803
+ if (!this.externalProcesses?.has(scope, job.runId)) throw new PoTeamExpectedError("run_not_found", `External run '${job.runId}' is no longer active.`, false, "List active runs and retry with a current run id.");
5582
5804
  await this.externalProcesses.control(scope, job.runId, {
5583
5805
  command,
5584
5806
  requestId,
@@ -5592,7 +5814,7 @@ var ManagementActions = class {
5592
5814
  const requestId = (0, node_crypto.randomUUID)();
5593
5815
  const index = targetIndex ?? 0;
5594
5816
  if (job.native) {
5595
- if (!this.nativeRuns?.get(scope.rootSessionId, job.runId)) throw new DoomTeamExpectedError("run_not_found", `Native run '${job.runId}' is no longer active.`, false, "List active runs and retry with a current run id.");
5817
+ if (!this.nativeRuns?.get(scope.rootSessionId, job.runId)) throw new PoTeamExpectedError("run_not_found", `Native run '${job.runId}' is no longer active.`, false, "List active runs and retry with a current run id.");
5596
5818
  await this.nativeRuns.steer(scope.rootSessionId, job.runId, message, signal);
5597
5819
  return {
5598
5820
  requestId,
@@ -5601,11 +5823,11 @@ var ManagementActions = class {
5601
5823
  message: "Native child accepted the steer request."
5602
5824
  };
5603
5825
  }
5604
- if (!this.externalProcesses?.has(scope, job.runId)) throw new DoomTeamExpectedError("run_not_found", `External run '${job.runId}' is no longer active.`, false, "List active runs and retry with a current run id.");
5826
+ if (!this.externalProcesses?.has(scope, job.runId)) throw new PoTeamExpectedError("run_not_found", `External run '${job.runId}' is no longer active.`, false, "List active runs and retry with a current run id.");
5605
5827
  const acknowledgement = await this.externalProcesses.control(scope, job.runId, {
5606
5828
  command: "steer",
5607
5829
  requestId,
5608
- message,
5830
+ message: typeof message === "string" ? message : message.text,
5609
5831
  targetIndex: index
5610
5832
  });
5611
5833
  if (!acknowledgement) return {
@@ -5652,140 +5874,6 @@ var McpDirectToolResolverBinding = class {
5652
5874
  }
5653
5875
  };
5654
5876
  //#endregion
5655
- //#region src/services/nativeRunCoordinator/index.ts
5656
- function terminalState(event) {
5657
- return event.state === "completed" || event.state === "failed" || event.state === "stopped" ? event.state : void 0;
5658
- }
5659
- function entryKey(sessionId, runId) {
5660
- return JSON.stringify([sessionId, runId]);
5661
- }
5662
- var NativeRunCoordinator = class {
5663
- childSessions;
5664
- tracker;
5665
- notifier;
5666
- projection;
5667
- entries = /* @__PURE__ */ new Map();
5668
- closed = false;
5669
- closing;
5670
- constructor(childSessions, tracker, notifier, projection) {
5671
- this.childSessions = childSessions;
5672
- this.tracker = tracker;
5673
- this.notifier = notifier;
5674
- this.projection = projection;
5675
- }
5676
- async start(sessionId, request, identity) {
5677
- if (this.closed) throw new Error("The native Team run coordinator is closed.");
5678
- if (!sessionId.trim()) throw new Error("Native child runs require a session identity.");
5679
- const service = this.childSessions?.get();
5680
- if (!service) throw new Error("The in-process Pi child-session service is unavailable.");
5681
- const handle = await service.start(request);
5682
- if (this.closed) {
5683
- await handle.dispose();
5684
- throw new Error("The native Team run coordinator closed during child startup.");
5685
- }
5686
- const entry = {
5687
- sessionId,
5688
- scope: request.scope,
5689
- request,
5690
- ...identity ? { identity } : {},
5691
- handle,
5692
- terminal: false
5693
- };
5694
- const key = entryKey(sessionId, request.runId);
5695
- this.entries.set(key, entry);
5696
- try {
5697
- const unsubscribe = handle.subscribe((event) => this.onEvent(entry, event));
5698
- if (entry.terminal) unsubscribe();
5699
- else entry.unsubscribe = unsubscribe;
5700
- return handle;
5701
- } catch (error) {
5702
- this.entries.delete(key);
5703
- await handle.dispose().catch(() => void 0);
5704
- throw error;
5705
- }
5706
- }
5707
- get(sessionId, runId) {
5708
- return this.entries.get(entryKey(sessionId, runId))?.handle;
5709
- }
5710
- status(sessionId, runId) {
5711
- return this.tracker.getNative(sessionId, runId);
5712
- }
5713
- async steer(sessionId, runId, message, signal) {
5714
- const handle = this.get(sessionId, runId);
5715
- if (!handle) throw new Error(`No active native run matches '${runId}'.`);
5716
- await handle.steer(message, signal);
5717
- }
5718
- async stop(sessionId, runId, reason) {
5719
- const handle = this.get(sessionId, runId);
5720
- if (!handle) throw new Error(`No active native run matches '${runId}'.`);
5721
- await handle.stop(reason);
5722
- }
5723
- async close() {
5724
- this.closed = true;
5725
- this.closing ??= (async () => {
5726
- const active = [...this.entries.values()];
5727
- const outcomes = await Promise.allSettled(active.map((entry) => entry.handle.dispose()));
5728
- for (const entry of active) {
5729
- entry.unsubscribe?.();
5730
- this.entries.delete(entryKey(entry.sessionId, entry.request.runId));
5731
- }
5732
- const failures = outcomes.filter((outcome) => outcome.status === "rejected").map((outcome) => outcome.reason);
5733
- if (failures.length) throw new AggregateError(failures, "Native Team run shutdown failed.");
5734
- })();
5735
- return this.closing;
5736
- }
5737
- onEvent(entry, event) {
5738
- entry.startedAt ??= event.timestamp;
5739
- const status = terminalState(event);
5740
- const projection = {
5741
- runId: event.runId,
5742
- agent: entry.request.agent,
5743
- ...entry.identity ? {
5744
- identity: entry.identity.identity,
5745
- inline: entry.identity.inline
5746
- } : {},
5747
- task: entry.request.task,
5748
- cwd: entry.request.cwd,
5749
- runtime: "pi",
5750
- status: event.state === "starting" ? "queued" : event.state === "running" ? "running" : event.state,
5751
- startedAt: entry.startedAt,
5752
- updatedAt: event.timestamp,
5753
- ...event.cost === void 0 ? {} : { cost: event.cost },
5754
- ...event.sessionFile ? { sessionFile: event.sessionFile } : {},
5755
- ...event.message ? {
5756
- error: status === "failed" || status === "stopped" ? event.message : void 0,
5757
- summary: event.message
5758
- } : {}
5759
- };
5760
- this.tracker.upsertNative(entry.sessionId, entry.scope, projection);
5761
- this.projection?.publish(entry.sessionId, projection);
5762
- if (!status || entry.terminal) return;
5763
- entry.terminal = true;
5764
- entry.unsubscribe?.();
5765
- this.entries.delete(entryKey(entry.sessionId, entry.request.runId));
5766
- const result = {
5767
- runId: entry.request.runId,
5768
- agent: entry.request.agent,
5769
- ...entry.identity ? {
5770
- identity: entry.identity.identity,
5771
- inline: entry.identity.inline
5772
- } : {},
5773
- task: entry.request.task,
5774
- cwd: entry.request.cwd,
5775
- runtime: "pi",
5776
- state: status,
5777
- success: status === "completed",
5778
- summary: event.message ?? (status === "completed" ? "Native child run completed." : `Native child run ${status}.`),
5779
- durationMs: Math.max(0, event.timestamp - (this.tracker.getNative(entry.sessionId, entry.request.runId)?.startedAt ?? event.timestamp)),
5780
- sessionId: entry.sessionId,
5781
- ...event.sessionFile ? { sessionFile: event.sessionFile } : {}
5782
- };
5783
- if (this.notifier) this.notifier.deliver(result).then((delivered) => {
5784
- if (delivered) this.tracker.acknowledgeHandoff(entry.sessionId, entry.request.runId);
5785
- }).catch(() => void 0);
5786
- }
5787
- };
5788
- //#endregion
5789
5877
  //#region src/services/pollScheduler/index.ts
5790
5878
  /**
5791
5879
  * One master tick that drives every background subscriber in the runner
@@ -6099,16 +6187,16 @@ function createTeamExtensionRuntime(reportConcurrencyEvent, options) {
6099
6187
  const asyncJobTracker = new AsyncJobTracker();
6100
6188
  const admission = new AdmissionGate({ countLiveRuns: (scope) => asyncJobTracker.forSession(scope.rootSessionId, scope).list().filter((job) => job.status === void 0 || !TERMINAL_ASYNC_JOB_STATES.has(job.status)).length });
6101
6189
  const subagentWaiter = new SubagentWaiter(asyncJobTracker);
6102
- const externalProcesses = new require_externalProcessIpc.ExternalProcessIpc();
6190
+ const externalProcesses = new require_atomicJson.ExternalProcessIpc();
6103
6191
  const asyncSubagentSpawner = new AsyncSubagentSpawner(externalProcesses);
6104
- const discovery = new require_agentDiscovery.AgentDiscoveryService(options.environment);
6192
+ const discovery = new require_agentDiscovery.AgentDiscoveryService(options.discoveryIo, options.agentConfig);
6105
6193
  const skills = new SkillDiscoveryService();
6106
6194
  const capabilityPolicies = new require_capabilityCeiling.SubagentCapabilityPolicyStore();
6107
6195
  const mcpToolResolver = new McpDirectToolResolverBinding();
6108
6196
  const completionNotifier = new CompletionNotifier();
6109
6197
  const nativeRuns = new NativeRunCoordinator(options.childSessions, asyncJobTracker, completionNotifier, options.nativeRunProjection);
6110
6198
  const teamChannel = new NativeTeamChannelService();
6111
- const spawnPlanner = new SpawnPlanner(discovery, asyncSubagentSpawner, capabilityPolicies, skills, report, mcpToolResolver, admission, options.childSessions, nativeRuns, teamChannel, options.environment);
6199
+ const spawnPlanner = new SpawnPlanner(discovery, asyncSubagentSpawner, capabilityPolicies, skills, report, mcpToolResolver, admission, options.childSessions, nativeRuns, teamChannel, options.environment, options.agentConfig);
6112
6200
  const management = new ManagementActions(asyncJobTracker, nativeRuns, externalProcesses);
6113
6201
  const onExternalEvent = (event) => {
6114
6202
  const sessionId = event.scope.rootSessionId;
@@ -6165,6 +6253,7 @@ function createTeamExtensionRuntime(reportConcurrencyEvent, options) {
6165
6253
  subagentWaiter,
6166
6254
  asyncSubagentSpawner,
6167
6255
  discovery,
6256
+ agentConfig: options.agentConfig,
6168
6257
  skills,
6169
6258
  spawnPlanner,
6170
6259
  completionNotifier,
@@ -6246,12 +6335,16 @@ function presentTrackedRun(run) {
6246
6335
  state: runState(run.status),
6247
6336
  rawState: run.status,
6248
6337
  task: run.task ?? "",
6338
+ ...run.promptWithheld ? { promptWithheld: true } : {},
6249
6339
  cwd: run.cwd ?? "",
6250
6340
  startedAt: run.startedAt,
6251
6341
  ...TERMINAL_RUN_STATES.has(run.status) ? { endedAt: lastUpdate } : {},
6252
6342
  lastUpdate,
6253
6343
  tail: [],
6254
- ...run.sessionFile === void 0 ? {} : { sessionFile: run.sessionFile },
6344
+ canSteer: false,
6345
+ ...run.tokens === void 0 ? {} : { tokens: run.tokens },
6346
+ ...run.toolCount === void 0 ? {} : { toolCount: run.toolCount },
6347
+ ...run.cost === void 0 ? {} : { cost: run.cost },
6255
6348
  ...run.summary === void 0 ? {} : { summary: run.summary },
6256
6349
  ...run.error === void 0 ? {} : { error: run.error }
6257
6350
  };
@@ -6262,6 +6355,8 @@ function presentNativeRun(run) {
6262
6355
  agent: run.agent,
6263
6356
  ...run.identity === void 0 ? {} : { identity: run.identity },
6264
6357
  ...run.inline === void 0 ? {} : { inline: run.inline },
6358
+ ...run.agentDescription === void 0 ? {} : { agentDescription: run.agentDescription },
6359
+ ...run.agentFilePath === void 0 ? {} : { agentFilePath: run.agentFilePath },
6265
6360
  state: runState(run.status),
6266
6361
  rawState: run.status,
6267
6362
  task: run.task,
@@ -6270,7 +6365,14 @@ function presentNativeRun(run) {
6270
6365
  ...TERMINAL_RUN_STATES.has(run.status) ? { endedAt: run.updatedAt } : {},
6271
6366
  lastUpdate: run.updatedAt,
6272
6367
  tail: [],
6273
- ...run.sessionFile === void 0 ? {} : { sessionFile: run.sessionFile },
6368
+ ...run.model === void 0 ? {} : {
6369
+ model: run.model,
6370
+ modelSource: "runtime"
6371
+ },
6372
+ ...run.thinking === void 0 ? {} : { thinking: run.thinking },
6373
+ ...run.tokens === void 0 ? {} : { tokens: run.tokens },
6374
+ ...run.toolCount === void 0 ? {} : { toolCount: run.toolCount },
6375
+ ...run.cost === void 0 ? {} : { cost: run.cost },
6274
6376
  ...run.summary === void 0 ? {} : { summary: run.summary },
6275
6377
  ...run.error === void 0 ? {} : { error: run.error }
6276
6378
  };
@@ -6280,7 +6382,7 @@ function publishRuns(directEvents, sessionId, jobs, nativeRuns) {
6280
6382
  runs.push(...[...nativeRuns.values()].map(presentNativeRun));
6281
6383
  directEvents.publish(SUBAGENT_RUNS_TYPE, sessionId, { runs });
6282
6384
  }
6283
- const TEAM_COST_STATUS = "doom-team-cost";
6385
+ const TEAM_COST_STATUS = "po-team-cost";
6284
6386
  const COST_DECIMALS = 6;
6285
6387
  function updateTeamCost(client, jobs, nativeRuns, costs, previousText, attached, force = false) {
6286
6388
  const trackedCosts = /* @__PURE__ */ new Map();
@@ -6300,20 +6402,20 @@ function updateTeamCost(client, jobs, nativeRuns, costs, previousText, attached,
6300
6402
  function recordDelegationObservation(telemetry, observation) {
6301
6403
  if (observation.kind === "requested") {
6302
6404
  const { event } = observation;
6303
- telemetry.recordEvent("doom_team.delegation_requested", {
6405
+ telemetry.recordEvent("po_team.delegation_requested", {
6304
6406
  "agent.name": event.agent,
6305
6407
  "task.id": event.taskId,
6306
6408
  mode: event.runMode ?? "foreground"
6307
6409
  });
6308
6410
  } else if (observation.kind === "started") {
6309
6411
  const { event } = observation;
6310
- telemetry.recordEvent("doom_team.child_started", {
6412
+ telemetry.recordEvent("po_team.child_started", {
6311
6413
  "run.id": event.runId,
6312
6414
  outcome: "started"
6313
6415
  });
6314
6416
  } else if (observation.kind === "updated") {
6315
6417
  const { event } = observation;
6316
- telemetry.recordEvent("doom_team.delegation_updated", {
6418
+ telemetry.recordEvent("po_team.delegation_updated", {
6317
6419
  "run.id": event.runId,
6318
6420
  "team.tool_count": event.toolCount ?? 0,
6319
6421
  "team.duration_ms": event.durationMs ?? 0,
@@ -6322,43 +6424,61 @@ function recordDelegationObservation(telemetry, observation) {
6322
6424
  });
6323
6425
  } else if (observation.kind === "finished") {
6324
6426
  const { event } = observation;
6325
- telemetry.recordEvent("doom_team.delegation_finished", {
6427
+ telemetry.recordEvent("po_team.delegation_finished", {
6326
6428
  "run.id": event.runId,
6327
6429
  "team.tool_count": event.toolCount ?? 0,
6328
6430
  "team.duration_ms": event.durationMs ?? 0,
6329
6431
  outcome: event.status
6330
6432
  });
6331
- } else telemetry.recordEvent("doom_team.delegation_cancelled", { outcome: "cancelled" });
6433
+ } else telemetry.recordEvent("po_team.delegation_cancelled", { outcome: "cancelled" });
6332
6434
  }
6333
6435
  const root = (0, _agimon_ai_po_core_extensionFile.defineRoot)(({ context, host: serverHost, agent: host }) => {
6334
6436
  if (!host) throw new Error("Team session requires the headless host.");
6335
- if (serverHost.context.environment === void 0) throw new Error("Team headless facet requires an admitted session environment.");
6437
+ if (serverHost.context.environment === void 0) throw new Error("Team server plugin requires an admitted session environment.");
6336
6438
  const directEvents = serverHost.context.directEvents;
6337
- if (directEvents === void 0) throw new Error("Team headless facet requires host-owned direct events.");
6439
+ if (directEvents === void 0) throw new Error("Team server plugin requires host-owned direct events.");
6338
6440
  const execution = {
6339
6441
  ...host.context,
6340
6442
  get model() {
6341
6443
  return host.context.model;
6444
+ },
6445
+ get selection() {
6446
+ return host.context.selection;
6342
6447
  }
6343
6448
  };
6344
6449
  const sessionPeers = /* @__PURE__ */ new Set();
6345
6450
  const stopPeerDiscovery = serverHost.context.sessionCommunication?.onPeerReady((id) => sessionPeers.add(id));
6346
- const telemetry = (0, _agimon_ai_po_telemetry.createDoomTelemetry)({
6347
- serviceName: "doom-team",
6451
+ const telemetry = (0, _agimon_ai_po_telemetry.createPoTelemetry)({
6452
+ serviceName: "po-team",
6348
6453
  packageName: "@agimon-ai/po-team",
6349
6454
  cwd: execution.cwd,
6350
6455
  env: serverHost.context.environment,
6351
6456
  enableLogs: true,
6352
6457
  enableTraces: true
6353
6458
  });
6459
+ const environment = serverHost.context.environment;
6460
+ const fs = (0, _agimon_ai_po_core_platform.requirePoFs)(context);
6461
+ const homeDirectory = environment.HOME ?? _agimon_ai_po_core_platform.nodeHost.homeDirectory();
6354
6462
  const runtime = createTeamExtensionRuntime((event, attributes) => {
6355
6463
  telemetry.recordEvent(event, attributes);
6356
6464
  }, {
6357
- environment: serverHost.context.environment,
6358
- childSessions: { get: () => (0, _agimon_ai_po_core_childSession.readDoomChildSessionService)(context) },
6465
+ environment,
6466
+ discoveryIo: {
6467
+ fs,
6468
+ context: _agimon_ai_po_core_platform.BACKGROUND_CONTEXT,
6469
+ environment,
6470
+ homeDirectory,
6471
+ configDirName: require_agentDiscovery.getConfigDirName(environment)
6472
+ },
6473
+ agentConfig: new TeamAgentConfigService({
6474
+ fs,
6475
+ environment,
6476
+ homeDirectory
6477
+ }),
6478
+ childSessions: { get: () => (0, _agimon_ai_po_core_childSession.readPoChildSessionService)(context) },
6359
6479
  nativeRunProjection
6360
6480
  });
6361
- const scope = require_externalProcessIpc.createSessionScope(execution.sessionId);
6481
+ const scope = require_atomicJson.createSessionScope(execution.sessionId);
6362
6482
  runtime.management.bindSessionScope(scope);
6363
6483
  const jobs = runtime.asyncJobTracker.forSession(execution.sessionId, scope);
6364
6484
  const bridge = createDelegationBridge({
@@ -6378,9 +6498,6 @@ const root = (0, _agimon_ai_po_core_extensionFile.defineRoot)(({ context, host:
6378
6498
  telemetry.recordEvent(event, attributes);
6379
6499
  }
6380
6500
  });
6381
- let ownedReadiness;
6382
- let ready;
6383
- const startupAbort = new AbortController();
6384
6501
  const nativeRuns = /* @__PURE__ */ new Map();
6385
6502
  const childCosts = /* @__PURE__ */ new Map();
6386
6503
  let costText;
@@ -6418,7 +6535,8 @@ const root = (0, _agimon_ai_po_core_extensionFile.defineRoot)(({ context, host:
6418
6535
  });
6419
6536
  if (options?.triggerTurn === false) return;
6420
6537
  if (!execution.session.admitPrompt) throw new Error("The session cannot admit a completion prompt.");
6421
- await execution.session.admitPrompt(message.content, "steer");
6538
+ const runIds = details.map((detail) => detail.runId).toSorted();
6539
+ await execution.session.admitPrompt(message.content, "steer", void 0, runIds.length ? `subagent-report:${runIds.join(",")}` : void 0);
6422
6540
  });
6423
6541
  deliveries = delivery.catch(() => void 0);
6424
6542
  return delivery;
@@ -6431,16 +6549,26 @@ const root = (0, _agimon_ai_po_core_extensionFile.defineRoot)(({ context, host:
6431
6549
  });
6432
6550
  if (options?.triggerTurn === false) return;
6433
6551
  const delivery = deliveries.then(async () => {
6434
- if (!execution.session.admitPrompt) throw new Error("The session cannot admit an intercom message.");
6435
- await execution.session.admitPrompt(text, "steer");
6552
+ if (!execution.session.admitMessage) throw new Error("The session cannot admit an intercom message.");
6553
+ await execution.session.admitMessage({
6554
+ type: message.customType,
6555
+ text,
6556
+ display: message.display,
6557
+ details: message.details
6558
+ }, "steer");
6436
6559
  });
6437
6560
  deliveries = delivery.catch(() => void 0);
6438
6561
  return delivery;
6439
6562
  } });
6440
6563
  const intercom = createHeadlessIntercomTool(channel, {
6441
6564
  sessionId: execution.sessionId,
6442
- peers: () => [...sessionPeers].filter((id) => serverHost.context.sessionService?.canCommunicate?.(execution.sessionId, id) === true),
6443
- delivery: () => (0, _agimon_ai_po_session.readDoomSessionDelivery)(context)
6565
+ name: () => serverHost.context.sessionCommunication?.sessionName,
6566
+ peers: () => [...sessionPeers].filter((id) => serverHost.context.sessionService?.canCommunicate?.(execution.sessionId, id) === true).flatMap((id) => {
6567
+ const peer = serverHost.context.sessionCommunication?.describePeer?.(id);
6568
+ return peer === void 0 ? [] : [peer];
6569
+ }),
6570
+ canCommunicate: (id) => serverHost.context.sessionService?.canCommunicate?.(execution.sessionId, id) === true,
6571
+ delivery: () => (0, _agimon_ai_po_session.readPoSessionDelivery)(context)
6444
6572
  });
6445
6573
  const serverService = (ctx) => {
6446
6574
  ctx.plugin((providerContext) => {
@@ -6450,12 +6578,18 @@ const root = (0, _agimon_ai_po_core_extensionFile.defineRoot)(({ context, host:
6450
6578
  sessionScope: scope,
6451
6579
  cwd: execution.cwd,
6452
6580
  environment: serverHost.context.environment,
6453
- get availableModels() {
6454
- return execution.getAvailableModels?.().map(toModelInfo) ?? (execution.model ? [toModelInfo(execution.model)] : []);
6581
+ availableModels: () => availableModelInfos(execution),
6582
+ repoRoot: execution.repoRoot,
6583
+ get parentSelection() {
6584
+ return execution.selection;
6455
6585
  },
6456
6586
  get parentModel() {
6457
6587
  return execution.model;
6458
6588
  },
6589
+ reportWarning: (body) => execution.client.notify({
6590
+ body,
6591
+ level: "warning"
6592
+ }),
6459
6593
  captureForkSource: () => execution.session.forkSource?.()
6460
6594
  },
6461
6595
  directRunTracker: runtime.asyncJobTracker,
@@ -6464,9 +6598,16 @@ const root = (0, _agimon_ai_po_core_extensionFile.defineRoot)(({ context, host:
6464
6598
  policies: runtime.capabilityPolicies,
6465
6599
  observeDelegation: (observation) => recordDelegationObservation(telemetry, observation)
6466
6600
  });
6467
- providerContext.inject([_agimon_ai_po_core_mcpToolResolver.DOOM_MCP_TOOL_RESOLVER_SERVICE], (resolverContext) => runtime.mcpToolResolver.bind((0, _agimon_ai_po_core_mcpToolResolver.requireDoomMcpToolResolver)(resolverContext)));
6468
- providerContext.inject([_agimon_ai_po_core_contextContributions.DOOM_CONTEXT_CONTRIBUTIONS_SERVICE], (contributionContext) => {
6469
- const registration = (0, _agimon_ai_po_core_contextContributions.requireDoomContextContributions)(contributionContext).register({
6601
+ providerContext.inject([_agimon_ai_po_config.PO_CONFIG_SERVICE], (configContext) => {
6602
+ const config = configContext.get(_agimon_ai_po_config.PO_CONFIG_SERVICE);
6603
+ if (!config) throw new Error("Team requires the session Po config service.");
6604
+ const unbind = runtime.agentConfig.bind(() => config.getSnapshot());
6605
+ publishCatalog();
6606
+ return unbind;
6607
+ });
6608
+ providerContext.inject([_agimon_ai_po_core_mcpToolResolver.PO_MCP_TOOL_RESOLVER_SERVICE], (resolverContext) => runtime.mcpToolResolver.bind((0, _agimon_ai_po_core_mcpToolResolver.requirePoMcpToolResolver)(resolverContext)));
6609
+ providerContext.inject([_agimon_ai_po_core_contextContributions.PO_CONTEXT_CONTRIBUTIONS_SERVICE], (contributionContext) => {
6610
+ const registration = (0, _agimon_ai_po_core_contextContributions.requirePoContextContributions)(contributionContext).register({
6470
6611
  source: "@agimon-ai/po-team",
6471
6612
  id: "runtime",
6472
6613
  label: "Team",
@@ -6475,30 +6616,96 @@ const root = (0, _agimon_ai_po_core_extensionFile.defineRoot)(({ context, host:
6475
6616
  });
6476
6617
  return () => registration.dispose();
6477
6618
  });
6478
- ready = ((0, _agimon_ai_po_core_readiness.readDoomReadinessCoordinator)(providerContext) ?? (ownedReadiness = (0, _agimon_ai_po_core_readiness.createDoomReadinessCoordinator)({ notify: (notification) => execution.client.notify({
6479
- level: "warning",
6480
- body: notification.error?.message ?? notification.diagnostics.join("; ")
6481
- }) }))).start("@agimon-ai/po-team", `team:${execution.sessionId}:${crypto.randomUUID()}`, async (signal) => {
6482
- signal.throwIfAborted();
6483
- startupAbort.signal.throwIfAborted();
6484
- const opened = await openScopeAsync(scope);
6485
- signal.throwIfAborted();
6486
- startupAbort.signal.throwIfAborted();
6487
- if (opened.suspended.length) await execution.client.notify({
6488
- body: formatSuspendedRuns(opened.suspended),
6489
- level: "info"
6490
- });
6491
- telemetry.recordEvent("doom_team.runs_restored", {
6492
- "team.suspended_count": opened.suspended.length,
6493
- "team.pruned_count": opened.pruned.length,
6494
- "team.reaped_count": opened.reaped,
6495
- outcome: "reported"
6496
- });
6497
- return { value: void 0 };
6619
+ });
6620
+ };
6621
+ const publishCatalog = async () => {
6622
+ if (!activityAttached) return;
6623
+ try {
6624
+ const discovered = (await runtime.discovery.discover(execution.cwd, "both")).agents;
6625
+ const models = (await runtime.agentConfig.currentOrUndefined())?.models ?? [];
6626
+ if (!activityAttached) return;
6627
+ directEvents.publish(SUBAGENT_CATALOG_TYPE, execution.sessionId, {
6628
+ cwd: execution.cwd,
6629
+ agents: presentCatalog(discovered),
6630
+ models: catalogModels(discovered, [...models])
6498
6631
  });
6632
+ } catch (error) {
6633
+ if (!activityAttached) return;
6634
+ directEvents.publish(SUBAGENT_CATALOG_TYPE, execution.sessionId, {
6635
+ cwd: execution.cwd,
6636
+ agents: [],
6637
+ models: [],
6638
+ warning: error instanceof Error ? error.message : String(error)
6639
+ });
6640
+ }
6641
+ };
6642
+ const activity = {
6643
+ name: "@agimon-ai/po-team",
6644
+ async start(activityContext) {
6645
+ activityAttached = true;
6646
+ publishCost(true);
6647
+ publishRunSnapshot();
6648
+ await publishCatalog();
6649
+ try {
6650
+ channel.bindMainSession(activityContext.sessionId);
6651
+ return () => {
6652
+ if (!activityAttached) return;
6653
+ activityAttached = false;
6654
+ channel.dispose();
6655
+ execution.client.setStatus(TEAM_COST_STATUS, void 0);
6656
+ };
6657
+ } catch (error) {
6658
+ activityAttached = false;
6659
+ execution.client.setStatus(TEAM_COST_STATUS, void 0);
6660
+ throw error;
6661
+ }
6662
+ }
6663
+ };
6664
+ /**
6665
+ * Re-attaches the runs this session stored before a restart. Called from `session_start`, once the session can
6666
+ * take a completion and before its Harness resumes: a running child gets its lane and intercom back first, and
6667
+ * a finished one reports its completion now.
6668
+ */
6669
+ const restoreRuns = async () => {
6670
+ const report = (subject, error) => execution.client.notify({
6671
+ body: `${subject}: ${error instanceof Error ? error.message : String(error)}`,
6672
+ level: "warning"
6673
+ });
6674
+ let stored = [];
6675
+ try {
6676
+ stored = await (0, _agimon_ai_po_core_childSession.readPoChildSessionService)(context)?.stored?.() ?? [];
6677
+ } catch (error) {
6678
+ await report("Stored subagent runs could not be read", error);
6679
+ }
6680
+ let restored = 0;
6681
+ for (const run of stored) {
6682
+ const identity = storedRunIdentity(run);
6683
+ const intercom = run.settled ? void 0 : runtime.teamChannel.createNativeChildIntercom({
6684
+ rootSessionId: run.request.scope.rootSessionId,
6685
+ agent: run.request.agent,
6686
+ ...identity ? {
6687
+ identity: identity.identity,
6688
+ inline: identity.inline
6689
+ } : {},
6690
+ runId: run.request.runId,
6691
+ task: {
6692
+ id: run.request.runId,
6693
+ subject: run.request.task
6694
+ }
6695
+ });
6696
+ try {
6697
+ await runtime.nativeRuns.restore(run.request.parentSessionId, run, intercom);
6698
+ restored += 1;
6699
+ } catch (error) {
6700
+ intercom?.dispose?.();
6701
+ await report(`Subagent run ${run.request.runId} could not resume`, error);
6702
+ }
6703
+ }
6704
+ telemetry.recordEvent("po_team.runs_restored", {
6705
+ "team.restored_count": restored,
6706
+ outcome: "restored"
6499
6707
  });
6500
6708
  };
6501
- const environment = serverHost.context.environment;
6502
6709
  return {
6503
6710
  value: {
6504
6711
  runtime,
@@ -6509,96 +6716,63 @@ const root = (0, _agimon_ai_po_core_extensionFile.defineRoot)(({ context, host:
6509
6716
  channel,
6510
6717
  intercom,
6511
6718
  directEvents,
6512
- environment: serverHost.context.environment
6719
+ environment: serverHost.context.environment,
6720
+ restoreRuns
6513
6721
  },
6514
6722
  services: [
6515
6723
  (context) => {
6516
- if ((0, _agimon_ai_po_core_backgroundWork.readDoomBackgroundWorkService)(context) === void 0) (0, _agimon_ai_po_session.provideBackgroundWorkService)(context);
6724
+ if ((0, _agimon_ai_po_core_backgroundWork.readPoBackgroundWorkService)(context) === void 0) (0, _agimon_ai_po_session.provideBackgroundWorkService)(context);
6517
6725
  },
6518
6726
  serverService,
6727
+ (context) => context.provide(PO_TEAM_AGENT_CONFIG_SERVICE, runtime.agentConfig),
6728
+ (context) => context.provide(_agimon_ai_po_core_childSession.PO_CHILD_SESSION_LABELS_SERVICE, { labelFor: (runId) => nativeRuns.get(runId)?.identity }),
6519
6729
  mountMcpTools([intercom, createHeadlessSubagentTool(runtime, execution)])
6520
6730
  ],
6521
- activities: [{
6522
- name: "@agimon-ai/po-team",
6523
- async start(activityContext) {
6524
- activityAttached = true;
6525
- publishCost(true);
6526
- publishRunSnapshot();
6527
- try {
6528
- const discovered = runtime.discovery.discover(execution.cwd, "both").agents;
6529
- directEvents.publish(SUBAGENT_CATALOG_TYPE, execution.sessionId, {
6530
- cwd: execution.cwd,
6531
- agents: presentCatalog(discovered),
6532
- models: catalogModels(discovered, require_agentDiscovery.resolveActiveTeamModelSpecs(environment) ?? [])
6533
- });
6534
- } catch (error) {
6535
- directEvents.publish(SUBAGENT_CATALOG_TYPE, execution.sessionId, {
6536
- cwd: execution.cwd,
6537
- agents: [],
6538
- models: [],
6539
- warning: error instanceof Error ? error.message : String(error)
6540
- });
6541
- }
6542
- try {
6543
- channel.bindMainSession(activityContext.sessionId);
6544
- return () => {
6545
- if (!activityAttached) return;
6546
- activityAttached = false;
6547
- channel.dispose();
6548
- execution.client.setStatus(TEAM_COST_STATUS, void 0);
6549
- };
6550
- } catch (error) {
6551
- activityAttached = false;
6552
- execution.client.setStatus(TEAM_COST_STATUS, void 0);
6553
- throw error;
6554
- }
6555
- }
6556
- }],
6731
+ activities: [activity],
6557
6732
  async onStart() {
6558
6733
  runtime.pollScheduler.start();
6559
- telemetry.recordEvent("doom_team.session_started", { "team.root_session": (0, _agimon_ai_po_core_childProcess.resolveRootSessionId)(execution.sessionId, environment) === execution.sessionId });
6560
- if (!ready) throw new Error("Team readiness was not installed.");
6561
- await Promise.allSettled([ready.wait()]);
6734
+ telemetry.recordEvent("po_team.session_started", { "team.root_session": (0, _agimon_ai_po_core_childProcess.resolveRootSessionId)(execution.sessionId, environment) === execution.sessionId });
6562
6735
  },
6563
6736
  async onDispose() {
6564
6737
  disposing = true;
6565
- startupAbort.abort(/* @__PURE__ */ new Error("Team session ended."));
6566
- await Promise.allSettled([...ready ? [ready.wait()] : [], ...ownedReadiness ? [ownedReadiness.dispose()] : []]);
6567
6738
  activityAttached = false;
6568
- stopPeerDiscovery?.();
6569
- sessionPeers.clear();
6570
- execution.client.setStatus(TEAM_COST_STATUS, void 0);
6571
- channel.dispose();
6572
- runtime.completionNotifier.dispose();
6573
- const suspension = suspendScopeRuns({
6574
- scope,
6575
- reason: "headless session ended",
6576
- jobs: jobs.list(),
6577
- stop: (runId, reason) => runtime.management.stop(runId, reason)
6578
- });
6579
- const nativeShutdown = runtime.nativeRuns.close().finally(() => nativeRunProjection.dispose(execution.sessionId));
6580
- const outcomes = await Promise.allSettled([suspension, nativeShutdown]);
6581
- for (const outcome of outcomes) if (outcome.status === "rejected") process.emitWarning(`Could not shut down headless Team runs: ${String(outcome.reason)}`);
6582
- unsubscribeCostTracker();
6583
- unsubscribeCostNative();
6584
- nativeRuns.clear();
6585
- childCosts.clear();
6586
- costText = void 0;
6587
- bridge.abandonAll();
6588
- fablePlan.abandonAll();
6589
- runtime.capabilityPolicies.clear();
6590
- runtime.management.releaseSessionScope(scope);
6591
- runtime.dispose();
6592
- runtime.asyncJobTracker.stop();
6593
- runtime.pollScheduler.stop();
6594
- const suspended = outcomes[0];
6595
- await telemetry.recordEvent("doom_team.session_finished", {
6596
- reason: "headless session ended",
6597
- "team.suspended_count": suspended?.status === "fulfilled" ? suspended.value?.suspended.length ?? 0 : 0,
6598
- "team.unstoppable_count": suspended?.status === "fulfilled" ? suspended.value?.unstoppable.length ?? 0 : 0,
6599
- outcome: suspended?.status === "fulfilled" && !suspended.value?.unstoppable.length ? "suspended" : "degraded"
6600
- });
6601
- await telemetry.shutdown();
6739
+ let stoppedRuns;
6740
+ await (0, _agimon_ai_po_core_extensionFile.runCleanups)([
6741
+ () => stopPeerDiscovery?.(),
6742
+ () => sessionPeers.clear(),
6743
+ () => execution.client.setStatus(TEAM_COST_STATUS, void 0),
6744
+ () => channel.dispose(),
6745
+ () => runtime.completionNotifier.dispose(),
6746
+ async () => {
6747
+ stoppedRuns = await stopScopeRuns({
6748
+ reason: "headless session ended",
6749
+ jobs: jobs.list(),
6750
+ stop: (runId, reason) => runtime.management.stop(runId, reason)
6751
+ });
6752
+ },
6753
+ () => (0, _agimon_ai_po_core_extensionFile.runCleanups)([() => runtime.nativeRuns.close(), () => nativeRunProjection.dispose(execution.sessionId)], "Native Team runs cleanup failed."),
6754
+ unsubscribeCostTracker,
6755
+ unsubscribeCostNative,
6756
+ () => nativeRuns.clear(),
6757
+ () => childCosts.clear(),
6758
+ () => {
6759
+ costText = void 0;
6760
+ },
6761
+ () => bridge.abandonAll(),
6762
+ () => fablePlan.abandonAll(),
6763
+ () => runtime.capabilityPolicies.clear(),
6764
+ () => runtime.management.releaseSessionScope(scope),
6765
+ () => runtime.dispose(),
6766
+ () => runtime.asyncJobTracker.stop(),
6767
+ () => runtime.pollScheduler.stop(),
6768
+ () => telemetry.recordEvent("po_team.session_finished", {
6769
+ reason: "headless session ended",
6770
+ "team.stopped_count": stoppedRuns?.stopped.length ?? 0,
6771
+ "team.unstoppable_count": stoppedRuns?.unstoppable.length ?? 0,
6772
+ outcome: stoppedRuns && !stoppedRuns.unstoppable.length ? "stopped" : "degraded"
6773
+ }),
6774
+ () => telemetry.shutdown()
6775
+ ], "Team cleanup failed.");
6602
6776
  }
6603
6777
  };
6604
6778
  });
@@ -6664,13 +6838,9 @@ var subagent_catalog_default = (0, _agimon_ai_po_core_extensionFile.defineChanne
6664
6838
  var subagent_catalog_server_default = (0, _agimon_ai_po_core_extensionFile.defineChannel)(subagent_catalog_default);
6665
6839
  //#endregion
6666
6840
  //#region src/extensions/(backend)/channel/_lib/subagent-runs.ts
6667
- const RUN_ID_PATTERN = /^[\w.-]+$/;
6668
6841
  function isSubagentRunsPayload(value) {
6669
6842
  return typeof value === "object" && value !== null && Array.isArray(value.runs);
6670
6843
  }
6671
- function publicPayload(payload) {
6672
- return { runs: payload.runs.map(({ sessionFile: _sessionFile, ...run }) => run) };
6673
- }
6674
6844
  /**
6675
6845
  * The built-in subagents data channel consumes current state from the
6676
6846
  * host-owned direct event bus. Its bounded latest replay seeds late subscribers.
@@ -6685,16 +6855,34 @@ function createSubagentsChannel() {
6685
6855
  const publish = (scope, payload) => {
6686
6856
  if (scopes.get(scope.sessionId) !== scope) return;
6687
6857
  latest.set(scope.sessionId, payload);
6688
- host.publish(scope.sessionId, publicPayload(payload));
6858
+ host.publish(scope.sessionId, payload);
6689
6859
  };
6690
6860
  return {
6691
- payloadFor(scope) {
6692
- const payload = scopes.has(scope.sessionId) ? latest.get(scope.sessionId) : void 0;
6693
- return payload === void 0 ? void 0 : publicPayload(payload);
6861
+ homeFor(scope) {
6862
+ const payload = latest.get(scope.sessionId);
6863
+ if (!payload) return {
6864
+ coverage: "unavailable",
6865
+ entities: []
6866
+ };
6867
+ return {
6868
+ coverage: payload.runs.length > _agimon_ai_po_core_hubChannel.HOME_ENTITY_LIMIT ? "partial" : "ready",
6869
+ entities: payload.runs.slice(0, _agimon_ai_po_core_hubChannel.HOME_ENTITY_LIMIT).map((run) => ({
6870
+ id: (0, node_crypto.createHash)("sha256").update(JSON.stringify([
6871
+ scope.workspaceId ?? scope.cwd,
6872
+ scope.sessionId,
6873
+ run.runId,
6874
+ run.startedAt
6875
+ ])).digest("hex"),
6876
+ kind: run.state === "failed" ? "failure" : run.state === "done" ? "completed" : run.state === "stopped" ? "paused" : run.state,
6877
+ title: (run.taskRef || run.task || run.agent).slice(0, 160),
6878
+ ...(run.error || run.currentTool)?.trim() ? { detail: (run.error || run.currentTool).slice(0, 320) } : {},
6879
+ updatedAt: new Date(run.lastUpdate).toISOString(),
6880
+ sessionId: scope.sessionId
6881
+ }))
6882
+ };
6694
6883
  },
6695
- threadJournal(scope, runId) {
6696
- if (!RUN_ID_PATTERN.test(runId)) return void 0;
6697
- return (latest.get(scope.sessionId)?.runs.find((run) => run.runId === runId))?.sessionFile;
6884
+ payloadFor(scope) {
6885
+ return scopes.has(scope.sessionId) ? latest.get(scope.sessionId) : void 0;
6698
6886
  },
6699
6887
  sessionAdded(scope) {
6700
6888
  subscriptions.get(scope.sessionId)?.();
@@ -6750,16 +6938,11 @@ function isStopRequest(value) {
6750
6938
  }
6751
6939
  /** The typed error's text carries a recovery hint written for the model, so a missing run gets a sentence for people. */
6752
6940
  function controlFailure(error) {
6753
- if (error instanceof DoomTeamExpectedError && error.code === "run_not_found") return Response.json({ error: "This run is not active." }, { status: 404 });
6941
+ if (error instanceof PoTeamExpectedError && error.code === "run_not_found") return Response.json({ error: "This run is not active." }, { status: 404 });
6754
6942
  return Response.json({ error: error instanceof Error ? error.message : String(error) }, { status: 409 });
6755
6943
  }
6756
6944
  /** Serves catalog discovery, run launch, and run steer and stop from the selected session process, never through a parent prompt. */
6757
6945
  function createTeamApiHandler(options) {
6758
- const discovery = new require_agentDiscovery.AgentDiscoveryService(options.environment);
6759
- const read = options.read ?? ((cwd) => ({
6760
- agents: discovery.discover(cwd, "both").agents,
6761
- models: require_agentDiscovery.resolveActiveTeamModelSpecs(options.environment) ?? []
6762
- }));
6763
6946
  return {
6764
6947
  async fetch(request) {
6765
6948
  const url = new URL(request.url);
@@ -6810,8 +6993,8 @@ function createTeamApiHandler(options) {
6810
6993
  }
6811
6994
  if (request.method !== "GET" || url.pathname !== "/catalog") return Response.json({ error: "Not found." }, { status: 404 });
6812
6995
  try {
6813
- discovery.invalidate();
6814
- const snapshot = read(options.cwd);
6996
+ options.invalidate?.();
6997
+ const snapshot = await options.read(options.cwd);
6815
6998
  return Response.json({
6816
6999
  cwd: options.cwd,
6817
7000
  agents: presentCatalog(snapshot.agents),
@@ -6827,7 +7010,7 @@ function createTeamApiHandler(options) {
6827
7010
  }
6828
7011
  /** One mounted session API, backed by the Team runtime that owns the subagent tool. */
6829
7012
  function createTeamSessionApi(runtime, execution) {
6830
- const scope = require_externalProcessIpc.createSessionScope(execution.sessionId);
7013
+ const scope = require_atomicJson.createSessionScope(execution.sessionId);
6831
7014
  const jobs = runtime.asyncJobTracker.forSession(execution.sessionId, scope);
6832
7015
  const launch = async (request) => {
6833
7016
  const parentForkSource = request.fork ? await execution.session.forkSource?.() : void 0;
@@ -6844,9 +7027,11 @@ function createTeamSessionApi(runtime, execution) {
6844
7027
  sessionScope: scope,
6845
7028
  environment: execution.environment,
6846
7029
  parentSessionId: execution.sessionId,
7030
+ parentSelection: execution.selection,
6847
7031
  ...parentForkSource ? { parentForkSource } : {},
6848
- availableModels: execution.model ? [toModelInfo(execution.model)] : [],
6849
- ...execution.model ? { parentModel: execution.model } : {}
7032
+ availableModels: await availableModelInfos(execution),
7033
+ ...execution.model ? { parentModel: execution.model } : {},
7034
+ sender: HUMAN_SENDER
6850
7035
  }, loadConfig().config)).outcomes[0];
6851
7036
  if (!outcome?.runId) throw new Error(outcome?.error ?? "The agent did not start.");
6852
7037
  jobs.track(outcome.runId, outcome.identity ? {
@@ -6859,9 +7044,16 @@ function createTeamSessionApi(runtime, execution) {
6859
7044
  basePath: TEAM_API_BASE_PATH,
6860
7045
  start: () => createTeamApiHandler({
6861
7046
  cwd: execution.cwd,
6862
- environment: execution.environment,
7047
+ read: async (cwd) => ({
7048
+ agents: (await runtime.discovery.discover(cwd, "both")).agents,
7049
+ models: [...(await runtime.agentConfig.currentOrUndefined())?.models ?? []]
7050
+ }),
7051
+ invalidate: () => runtime.discovery.invalidate(),
6863
7052
  launch,
6864
- steer: (request, signal) => runtime.management.steer(request.runId, request.message, void 0, signal),
7053
+ steer: (request, signal) => runtime.management.steer(request.runId, {
7054
+ text: request.message,
7055
+ sender: HUMAN_SENDER
7056
+ }, void 0, signal),
6865
7057
  stop: (request) => runtime.management.stop(request.runId)
6866
7058
  })
6867
7059
  };
@@ -6871,6 +7063,12 @@ var route_server_default$1 = (context) => createTeamSessionApi(context.root.runt
6871
7063
  //#region src/extensions/workspaces/sessions/(backend)/api/route.server.ts
6872
7064
  var route_server_default = (0, _agimon_ai_po_core_extensionFile.defineRoute)(route_server_default$1);
6873
7065
  //#endregion
7066
+ //#region src/extensions/workspaces/sessions/(backend)/hook/sessionStart.server.ts
7067
+ var sessionStart_server_default = (0, _agimon_ai_po_core_extensionFile.defineHook)(({ root }) => ({
7068
+ event: "session_start",
7069
+ handle: () => root.restoreRuns()
7070
+ }));
7071
+ //#endregion
6874
7072
  //#region src/extensions/workspaces/sessions/(backend)/resource/_lib/team.server.ts
6875
7073
  /**
6876
7074
  * The roster the model is allowed to see.
@@ -6879,7 +7077,7 @@ var route_server_default = (0, _agimon_ai_po_core_extensionFile.defineRoute)(rou
6879
7077
  * `TeamMemberContext`, whose `token` is a session capability documented as never
6880
7078
  * leaving the direct context. A context resource is pasted into the system prompt,
6881
7079
  * sent to the provider and persisted, so the raw struct must not be serialized here.
6882
- * `formatTeamContextSnapshot` is the same projection the Pi facet renders.
7080
+ * `formatTeamContextSnapshot` is the same projection the Pi extension renders.
6883
7081
  */
6884
7082
  var team_server_default$1 = (context) => ({
6885
7083
  name: "po/team",
@@ -6901,21 +7099,24 @@ var subagent_server_default = (0, _agimon_ai_po_core_extensionFile.defineServerT
6901
7099
  //#endregion
6902
7100
  //#region generated/server.ts
6903
7101
  const at = (value, context) => typeof value === "function" ? value(context) : value;
7102
+ /* v8 ignore next -- generated normalization branch */
7103
+ const defined = (values) => values.filter((value) => value !== void 0);
6904
7104
  const via = (identity, value) => value === void 0 ? void 0 : {
6905
7105
  ...identity,
6906
7106
  ...value
6907
7107
  };
6908
- const facet = (0, _agimon_ai_po_core_serverFacet.defineServerPlugin)({
7108
+ const serverPlugin = (0, _agimon_ai_po_core_serverPlugin.defineServerPlugin)({
6909
7109
  name: "@agimon-ai/po-team",
6910
- providerOverrides: (0, _agimon_ai_po_core_serverFacet.composeServerProviderOverrides)(root_server_default),
7110
+ providerOverrides: (0, _agimon_ai_po_core_serverPlugin.composeServerProviderOverrides)(root_server_default),
7111
+ injects: (0, _agimon_ai_po_core_extensionFile.composeRootInjects)({ session: [root_server_default] }),
6911
7112
  global: () => ({ get channels() {
6912
7113
  return [() => via({ frameType: "subagent_catalog" }, subagent_catalog_server_default()), () => via({ frameType: "subagent_runs" }, subagent_runs_server_default())];
6913
7114
  } }),
6914
- workspace: () => ({ get channels() {
6915
- return [() => via({ frameType: "subagent_catalog" }, subagent_catalog_server_default()), () => via({ frameType: "subagent_runs" }, subagent_runs_server_default())];
7115
+ workspace: (context) => ({ get channels() {
7116
+ return defined([context.hosted("global") ? void 0 : () => via({ frameType: "subagent_catalog" }, subagent_catalog_server_default()), context.hosted("global") ? void 0 : () => via({ frameType: "subagent_runs" }, subagent_runs_server_default())]);
6916
7117
  } }),
6917
7118
  session: async (context) => {
6918
- const scopeSession = await root_server_default(context);
7119
+ const scopeSession = await context.scopeRoot("session", root_server_default, context);
6919
7120
  const contextSession = {
6920
7121
  ...context,
6921
7122
  root: scopeSession.value
@@ -6926,7 +7127,10 @@ const facet = (0, _agimon_ai_po_core_serverFacet.defineServerPlugin)({
6926
7127
  return [at(route_server_default, contextSession)];
6927
7128
  },
6928
7129
  get channels() {
6929
- return [() => via({ frameType: "subagent_catalog" }, subagent_catalog_server_default()), () => via({ frameType: "subagent_runs" }, subagent_runs_server_default())];
7130
+ return defined([context.hosted("global") ? void 0 : () => via({ frameType: "subagent_catalog" }, subagent_catalog_server_default()), context.hosted("global") ? void 0 : () => via({ frameType: "subagent_runs" }, subagent_runs_server_default())]);
7131
+ },
7132
+ get hooks() {
7133
+ return [via({ event: "session_start" }, at(sessionStart_server_default, contextSession))];
6930
7134
  },
6931
7135
  get resources() {
6932
7136
  return [at(team_server_default, contextSession)];
@@ -6942,7 +7146,7 @@ const facet = (0, _agimon_ai_po_core_serverFacet.defineServerPlugin)({
6942
7146
  }
6943
7147
  });
6944
7148
  //#endregion
6945
- exports.default = facet;
6946
- exports.facet = facet;
7149
+ exports.default = serverPlugin;
7150
+ exports.serverPlugin = serverPlugin;
6947
7151
 
6948
7152
  //# sourceMappingURL=server.cjs.map