@narumitw/pi-subagents 2.1.4 → 3.0.0

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 (312) hide show
  1. package/README.md +187 -1228
  2. package/dist/child-communication-bridge.ts +136 -0
  3. package/dist/child-communication-bridge.ts.map +7 -0
  4. package/dist/chunks/chunk-UKTWUQRM.js +667 -0
  5. package/dist/chunks/chunk-UKTWUQRM.js.map +7 -0
  6. package/dist/index.ts +1448 -1614
  7. package/dist/index.ts.map +4 -4
  8. package/docs/design-principles.md +31 -0
  9. package/docs/ipc-transport-idea.md +103 -0
  10. package/docs/tools.md +109 -0
  11. package/package.json +11 -19
  12. package/src/broker-credentials.ts +71 -0
  13. package/src/child-communication-bridge.ts +153 -0
  14. package/src/child-communication-tools.ts +147 -0
  15. package/src/completion-renderer.ts +60 -0
  16. package/src/index.ts +1 -1
  17. package/src/message-broker.ts +628 -0
  18. package/src/model-output.ts +42 -0
  19. package/src/process.ts +688 -0
  20. package/src/runtime.ts +538 -0
  21. package/src/subagents.ts +33 -34
  22. package/src/tools.ts +416 -0
  23. package/src/types.ts +85 -0
  24. package/src/widget.ts +130 -0
  25. package/dist/chunks/auto-transport-FUUKFDIG.ts +0 -109
  26. package/dist/chunks/auto-transport-FUUKFDIG.ts.map +0 -7
  27. package/dist/chunks/capability-grant-PR72SWWS.ts +0 -19
  28. package/dist/chunks/capability-grant-PR72SWWS.ts.map +0 -7
  29. package/dist/chunks/child-peer-bridge.ts +0 -108
  30. package/dist/chunks/child-peer-bridge.ts.map +0 -7
  31. package/dist/chunks/chunk-2LMJU25E.ts +0 -1641
  32. package/dist/chunks/chunk-2LMJU25E.ts.map +0 -7
  33. package/dist/chunks/chunk-47SK2QYC.ts +0 -56
  34. package/dist/chunks/chunk-47SK2QYC.ts.map +0 -7
  35. package/dist/chunks/chunk-4AQSF7AS.ts +0 -29
  36. package/dist/chunks/chunk-4AQSF7AS.ts.map +0 -7
  37. package/dist/chunks/chunk-5DGRMKNV.ts +0 -126
  38. package/dist/chunks/chunk-5DGRMKNV.ts.map +0 -7
  39. package/dist/chunks/chunk-6H6TBBED.ts +0 -108
  40. package/dist/chunks/chunk-6H6TBBED.ts.map +0 -7
  41. package/dist/chunks/chunk-6KJ34M6S.ts +0 -159
  42. package/dist/chunks/chunk-6KJ34M6S.ts.map +0 -7
  43. package/dist/chunks/chunk-6NSJVPXX.ts +0 -480
  44. package/dist/chunks/chunk-6NSJVPXX.ts.map +0 -7
  45. package/dist/chunks/chunk-7AAJEUSL.ts +0 -238
  46. package/dist/chunks/chunk-7AAJEUSL.ts.map +0 -7
  47. package/dist/chunks/chunk-BFK2Z4ZF.ts +0 -189
  48. package/dist/chunks/chunk-BFK2Z4ZF.ts.map +0 -7
  49. package/dist/chunks/chunk-BOAXY55Y.ts +0 -153
  50. package/dist/chunks/chunk-BOAXY55Y.ts.map +0 -7
  51. package/dist/chunks/chunk-D4CR7T73.ts +0 -353
  52. package/dist/chunks/chunk-D4CR7T73.ts.map +0 -7
  53. package/dist/chunks/chunk-FEVPWRMU.ts +0 -300
  54. package/dist/chunks/chunk-FEVPWRMU.ts.map +0 -7
  55. package/dist/chunks/chunk-G6VZTCFH.ts +0 -70
  56. package/dist/chunks/chunk-G6VZTCFH.ts.map +0 -7
  57. package/dist/chunks/chunk-H3FP6DLR.ts +0 -160
  58. package/dist/chunks/chunk-H3FP6DLR.ts.map +0 -7
  59. package/dist/chunks/chunk-HA36LPCO.ts +0 -130
  60. package/dist/chunks/chunk-HA36LPCO.ts.map +0 -7
  61. package/dist/chunks/chunk-HOP5FXDT.ts +0 -27
  62. package/dist/chunks/chunk-HOP5FXDT.ts.map +0 -7
  63. package/dist/chunks/chunk-IGAMVWFN.ts +0 -139
  64. package/dist/chunks/chunk-IGAMVWFN.ts.map +0 -7
  65. package/dist/chunks/chunk-ILEQ27AL.ts +0 -45
  66. package/dist/chunks/chunk-ILEQ27AL.ts.map +0 -7
  67. package/dist/chunks/chunk-ITVWPNU4.ts +0 -819
  68. package/dist/chunks/chunk-ITVWPNU4.ts.map +0 -7
  69. package/dist/chunks/chunk-IWC32VPY.ts +0 -172
  70. package/dist/chunks/chunk-IWC32VPY.ts.map +0 -7
  71. package/dist/chunks/chunk-JSZIP73U.ts +0 -362
  72. package/dist/chunks/chunk-JSZIP73U.ts.map +0 -7
  73. package/dist/chunks/chunk-JU6LUNLP.ts +0 -380
  74. package/dist/chunks/chunk-JU6LUNLP.ts.map +0 -7
  75. package/dist/chunks/chunk-KMGKCEO4.ts +0 -38
  76. package/dist/chunks/chunk-KMGKCEO4.ts.map +0 -7
  77. package/dist/chunks/chunk-LASD73CM.ts +0 -339
  78. package/dist/chunks/chunk-LASD73CM.ts.map +0 -7
  79. package/dist/chunks/chunk-LEOYDZI3.ts +0 -22
  80. package/dist/chunks/chunk-LEOYDZI3.ts.map +0 -7
  81. package/dist/chunks/chunk-LL4LP2T7.ts +0 -737
  82. package/dist/chunks/chunk-LL4LP2T7.ts.map +0 -7
  83. package/dist/chunks/chunk-N2T5IN4X.ts +0 -18
  84. package/dist/chunks/chunk-N2T5IN4X.ts.map +0 -7
  85. package/dist/chunks/chunk-N7BLVXKK.ts +0 -73
  86. package/dist/chunks/chunk-N7BLVXKK.ts.map +0 -7
  87. package/dist/chunks/chunk-NLT67IZS.ts +0 -322
  88. package/dist/chunks/chunk-NLT67IZS.ts.map +0 -7
  89. package/dist/chunks/chunk-NTRPLF46.ts +0 -63
  90. package/dist/chunks/chunk-NTRPLF46.ts.map +0 -7
  91. package/dist/chunks/chunk-ONDTY4EL.ts +0 -91
  92. package/dist/chunks/chunk-ONDTY4EL.ts.map +0 -7
  93. package/dist/chunks/chunk-OVPHFGKO.ts +0 -1769
  94. package/dist/chunks/chunk-OVPHFGKO.ts.map +0 -7
  95. package/dist/chunks/chunk-P7OH4XMF.ts +0 -60
  96. package/dist/chunks/chunk-P7OH4XMF.ts.map +0 -7
  97. package/dist/chunks/chunk-PBZMBTNJ.ts +0 -422
  98. package/dist/chunks/chunk-PBZMBTNJ.ts.map +0 -7
  99. package/dist/chunks/chunk-PGLSFLYW.ts +0 -52
  100. package/dist/chunks/chunk-PGLSFLYW.ts.map +0 -7
  101. package/dist/chunks/chunk-RRR66UWR.ts +0 -28
  102. package/dist/chunks/chunk-RRR66UWR.ts.map +0 -7
  103. package/dist/chunks/chunk-RSUXZD6S.ts +0 -275
  104. package/dist/chunks/chunk-RSUXZD6S.ts.map +0 -7
  105. package/dist/chunks/chunk-RTCVYIZA.ts +0 -221
  106. package/dist/chunks/chunk-RTCVYIZA.ts.map +0 -7
  107. package/dist/chunks/chunk-RY2AEGMZ.ts +0 -34
  108. package/dist/chunks/chunk-RY2AEGMZ.ts.map +0 -7
  109. package/dist/chunks/chunk-SWGQLFSD.ts +0 -60
  110. package/dist/chunks/chunk-SWGQLFSD.ts.map +0 -7
  111. package/dist/chunks/chunk-TM2R67J3.ts +0 -52
  112. package/dist/chunks/chunk-TM2R67J3.ts.map +0 -7
  113. package/dist/chunks/chunk-TMZRHIIK.ts +0 -497
  114. package/dist/chunks/chunk-TMZRHIIK.ts.map +0 -7
  115. package/dist/chunks/chunk-TZ34IQ3M.ts +0 -59
  116. package/dist/chunks/chunk-TZ34IQ3M.ts.map +0 -7
  117. package/dist/chunks/chunk-UMBPMVJW.ts +0 -22
  118. package/dist/chunks/chunk-UMBPMVJW.ts.map +0 -7
  119. package/dist/chunks/chunk-VDG7LTYE.ts +0 -80
  120. package/dist/chunks/chunk-VDG7LTYE.ts.map +0 -7
  121. package/dist/chunks/chunk-X4NMONPE.ts +0 -73
  122. package/dist/chunks/chunk-X4NMONPE.ts.map +0 -7
  123. package/dist/chunks/chunk-YPJEN6NU.ts +0 -65
  124. package/dist/chunks/chunk-YPJEN6NU.ts.map +0 -7
  125. package/dist/chunks/chunk-YU53SHA7.ts +0 -328
  126. package/dist/chunks/chunk-YU53SHA7.ts.map +0 -7
  127. package/dist/chunks/completion-delivery-RSJU6BXL.ts +0 -17
  128. package/dist/chunks/completion-delivery-RSJU6BXL.ts.map +0 -7
  129. package/dist/chunks/config-status-FKGDECZ3.ts +0 -35
  130. package/dist/chunks/config-status-FKGDECZ3.ts.map +0 -7
  131. package/dist/chunks/config-ui-ABHYNGQ7.ts +0 -1212
  132. package/dist/chunks/config-ui-ABHYNGQ7.ts.map +0 -7
  133. package/dist/chunks/consult-LJU3IQY5.ts +0 -519
  134. package/dist/chunks/consult-LJU3IQY5.ts.map +0 -7
  135. package/dist/chunks/context-QDKLVQXE.ts +0 -11
  136. package/dist/chunks/context-QDKLVQXE.ts.map +0 -7
  137. package/dist/chunks/create-stateful-transport-JWC2EFYL.ts +0 -130
  138. package/dist/chunks/create-stateful-transport-JWC2EFYL.ts.map +0 -7
  139. package/dist/chunks/cwd-policy-NB6XZ5GF.ts +0 -17
  140. package/dist/chunks/cwd-policy-NB6XZ5GF.ts.map +0 -7
  141. package/dist/chunks/delegation-contract-LA56I5DT.ts +0 -24
  142. package/dist/chunks/delegation-contract-LA56I5DT.ts.map +0 -7
  143. package/dist/chunks/discovery-MIFB2U4Y.ts +0 -12
  144. package/dist/chunks/discovery-MIFB2U4Y.ts.map +0 -7
  145. package/dist/chunks/execution-Q2JZLKJA.ts +0 -4037
  146. package/dist/chunks/execution-Q2JZLKJA.ts.map +0 -7
  147. package/dist/chunks/in-process-transport-HJ6TZXC3.ts +0 -39
  148. package/dist/chunks/in-process-transport-HJ6TZXC3.ts.map +0 -7
  149. package/dist/chunks/inspect-UH2TKH6E.ts +0 -634
  150. package/dist/chunks/inspect-UH2TKH6E.ts.map +0 -7
  151. package/dist/chunks/peer-communication-KL36Z6CO.ts +0 -294
  152. package/dist/chunks/peer-communication-KL36Z6CO.ts.map +0 -7
  153. package/dist/chunks/persistence-UY3PY6E5.ts +0 -348
  154. package/dist/chunks/persistence-UY3PY6E5.ts.map +0 -7
  155. package/dist/chunks/registry-BT54L6CY.ts +0 -1445
  156. package/dist/chunks/registry-BT54L6CY.ts.map +0 -7
  157. package/dist/chunks/retained-semantic-state-GM75FZGE.ts +0 -81
  158. package/dist/chunks/retained-semantic-state-GM75FZGE.ts.map +0 -7
  159. package/dist/chunks/rpc-transport-7R7DVCEB.ts +0 -1222
  160. package/dist/chunks/rpc-transport-7R7DVCEB.ts.map +0 -7
  161. package/dist/chunks/runtime-policy-5YELCOVC.ts +0 -15
  162. package/dist/chunks/runtime-policy-5YELCOVC.ts.map +0 -7
  163. package/dist/chunks/semantic-snapshot-WPJ3UAFW.ts +0 -19
  164. package/dist/chunks/semantic-snapshot-WPJ3UAFW.ts.map +0 -7
  165. package/dist/chunks/spawn-idempotency-BNHOSMZW.ts +0 -13
  166. package/dist/chunks/spawn-idempotency-BNHOSMZW.ts.map +0 -7
  167. package/dist/chunks/stateful-lifecycle-JAR6K55H.ts +0 -15
  168. package/dist/chunks/stateful-lifecycle-JAR6K55H.ts.map +0 -7
  169. package/dist/chunks/subprocess-transport-VHZJRBTW.ts +0 -160
  170. package/dist/chunks/subprocess-transport-VHZJRBTW.ts.map +0 -7
  171. package/dist/chunks/usage-recording-store-CW3EH2SZ.ts +0 -164
  172. package/dist/chunks/usage-recording-store-CW3EH2SZ.ts.map +0 -7
  173. package/dist/chunks/workspace-WDKLN72J.ts +0 -11
  174. package/dist/chunks/workspace-WDKLN72J.ts.map +0 -7
  175. package/docs/async-runtime-protocol.md +0 -84
  176. package/docs/implementation-notes/pi-subagents-capability-matrix.md +0 -62
  177. package/docs/implementation-notes/pi-subagents-current-direction.md +0 -99
  178. package/docs/implementation-notes/pi-subagents-rpc-v1.md +0 -139
  179. package/docs/pi-subagents-diagrams.md +0 -183
  180. package/src/adaptive-scheduler.ts +0 -224
  181. package/src/admission-policy.ts +0 -78
  182. package/src/agent-projection.ts +0 -53
  183. package/src/agents/built-ins.ts +0 -71
  184. package/src/agents/catalog.ts +0 -241
  185. package/src/agents/discovery.ts +0 -265
  186. package/src/agents/types.ts +0 -100
  187. package/src/agents.ts +0 -51
  188. package/src/auto-transport.ts +0 -121
  189. package/src/blocking-status.ts +0 -63
  190. package/src/cached-module-loader.ts +0 -18
  191. package/src/capabilities.ts +0 -145
  192. package/src/capability-grant.ts +0 -115
  193. package/src/capability-router.ts +0 -107
  194. package/src/child-peer-bridge.ts +0 -124
  195. package/src/child-peer-tools.ts +0 -132
  196. package/src/completion-delivery.ts +0 -409
  197. package/src/completion-render.ts +0 -190
  198. package/src/completion-requirement.ts +0 -479
  199. package/src/completion-routing.ts +0 -24
  200. package/src/config-registration.ts +0 -114
  201. package/src/config-status.ts +0 -217
  202. package/src/config-ui.ts +0 -983
  203. package/src/consult-policy.ts +0 -15
  204. package/src/consult-registration.ts +0 -125
  205. package/src/consult-render.ts +0 -194
  206. package/src/consult-resources.ts +0 -51
  207. package/src/consult-tool.ts +0 -95
  208. package/src/consult.ts +0 -566
  209. package/src/context.ts +0 -126
  210. package/src/create-stateful-transport.ts +0 -157
  211. package/src/cwd-policy.ts +0 -183
  212. package/src/delegation-contract.ts +0 -463
  213. package/src/execution/budget.ts +0 -56
  214. package/src/execution/runtime-policy.ts +0 -19
  215. package/src/execution-plan.ts +0 -322
  216. package/src/execution-ui.ts +0 -259
  217. package/src/execution.ts +0 -1679
  218. package/src/in-process-transport.ts +0 -941
  219. package/src/inspect-registration.ts +0 -64
  220. package/src/inspect-render.ts +0 -334
  221. package/src/inspect-tool.ts +0 -45
  222. package/src/inspect.ts +0 -769
  223. package/src/integration-controller.ts +0 -98
  224. package/src/limits.ts +0 -75
  225. package/src/orchestration-metrics.ts +0 -116
  226. package/src/outcome.ts +0 -61
  227. package/src/panel-child-group.ts +0 -35
  228. package/src/panel-contract.ts +0 -343
  229. package/src/panel-evidence.ts +0 -59
  230. package/src/panel-execution.ts +0 -769
  231. package/src/panel-failure.ts +0 -56
  232. package/src/panel-planning.ts +0 -175
  233. package/src/panel-presets.ts +0 -3
  234. package/src/panel-prompts.ts +0 -132
  235. package/src/panel-reconciliation.ts +0 -57
  236. package/src/panel-render.ts +0 -103
  237. package/src/parallel-limit-ui.ts +0 -113
  238. package/src/params.ts +0 -278
  239. package/src/peer-communication.ts +0 -352
  240. package/src/peer-transport.ts +0 -49
  241. package/src/persistence.ts +0 -522
  242. package/src/pi-args.ts +0 -43
  243. package/src/pi-invocation.ts +0 -168
  244. package/src/process-control.ts +0 -43
  245. package/src/prompt-resources.ts +0 -38
  246. package/src/prompt-source-safety.ts +0 -48
  247. package/src/protocol.ts +0 -76
  248. package/src/registry-types.ts +0 -204
  249. package/src/registry.ts +0 -1698
  250. package/src/render-common.ts +0 -252
  251. package/src/render.ts +0 -704
  252. package/src/result-contract.ts +0 -431
  253. package/src/retained-semantic-state.ts +0 -100
  254. package/src/rpc-timeout-finalization.ts +0 -207
  255. package/src/rpc-transport-metadata.ts +0 -65
  256. package/src/rpc-transport.ts +0 -1035
  257. package/src/rpc-turn-capture.ts +0 -217
  258. package/src/runner-outcome.ts +0 -31
  259. package/src/runner-result.ts +0 -55
  260. package/src/runner-types.ts +0 -102
  261. package/src/runner-usage.ts +0 -48
  262. package/src/runner.ts +0 -866
  263. package/src/safe-text.ts +0 -67
  264. package/src/semantic-snapshot.ts +0 -214
  265. package/src/session-guidance-contract.ts +0 -399
  266. package/src/settings/inspection.ts +0 -302
  267. package/src/settings/schema.ts +0 -195
  268. package/src/settings-reader.ts +0 -215
  269. package/src/settings.ts +0 -452
  270. package/src/spawn-idempotency.ts +0 -68
  271. package/src/stateful-agent-view.ts +0 -85
  272. package/src/stateful-config.ts +0 -13
  273. package/src/stateful-guidance.ts +0 -29
  274. package/src/stateful-lifecycle.ts +0 -74
  275. package/src/stateful-limit-ui.ts +0 -249
  276. package/src/stateful-limits.ts +0 -96
  277. package/src/stateful-prompt.ts +0 -49
  278. package/src/stateful-registration.ts +0 -1320
  279. package/src/stateful-render.ts +0 -318
  280. package/src/stateful-safety.ts +0 -47
  281. package/src/stateful-tool-params.ts +0 -215
  282. package/src/stateful.ts +0 -12
  283. package/src/subagent-details.ts +0 -43
  284. package/src/subagents-extension.ts +0 -372
  285. package/src/subprocess-transport.ts +0 -145
  286. package/src/supervision.ts +0 -104
  287. package/src/task-path.ts +0 -65
  288. package/src/timeout-checkpoint.ts +0 -305
  289. package/src/timeout-finalization.ts +0 -75
  290. package/src/tool-schema-compatibility.ts +0 -73
  291. package/src/transport-types.ts +0 -74
  292. package/src/transport-ui.ts +0 -135
  293. package/src/transport.ts +0 -43
  294. package/src/turn-budget.ts +0 -109
  295. package/src/usage-format.ts +0 -42
  296. package/src/usage-recording-config.ts +0 -13
  297. package/src/usage-recording-store.ts +0 -183
  298. package/src/usage-recording.ts +0 -478
  299. package/src/verification-harness.ts +0 -516
  300. package/src/verification-policy.ts +0 -67
  301. package/src/verification-receipt.ts +0 -275
  302. package/src/verified-execution-benchmark.ts +0 -86
  303. package/src/verified-execution-contract.ts +0 -191
  304. package/src/verified-execution-schema.ts +0 -32
  305. package/src/work-item-ledger.ts +0 -1404
  306. package/src/work-item-persistence.ts +0 -254
  307. package/src/workflow-completion-controller.ts +0 -397
  308. package/src/workflow-planning.ts +0 -172
  309. package/src/workflow-tree-identity.ts +0 -289
  310. package/src/workflow-ui.ts +0 -69
  311. package/src/workflow-verification.ts +0 -296
  312. package/src/workspace.ts +0 -174
@@ -1,1445 +0,0 @@
1
- // @generated by scripts/build-runtime.mjs; do not edit.
2
- // @ts-nocheck -- generated JavaScript uses a .ts extension for Pi's Jiti loader.
3
- import {
4
- classifyStructuredOutcome
5
- } from "./chunk-47SK2QYC.ts";
6
- import {
7
- isCapabilityGrantActive,
8
- revokeCapabilityGrant
9
- } from "./chunk-YPJEN6NU.ts";
10
- import {
11
- copyExecutionPlan,
12
- rotateExecutionPlanGeneration
13
- } from "./chunk-7AAJEUSL.ts";
14
- import {
15
- ROOT_TASK_PATH,
16
- deriveTaskName,
17
- joinTaskPath,
18
- resolveTaskPath,
19
- validateTaskName,
20
- validateTaskPath
21
- } from "./chunk-N7BLVXKK.ts";
22
- import {
23
- copyTurnTerminationReport
24
- } from "./chunk-RTCVYIZA.ts";
25
- import {
26
- validateTurnLimits
27
- } from "./chunk-ONDTY4EL.ts";
28
- import {
29
- parseAnyStructuredSubagentResult
30
- } from "./chunk-RSUXZD6S.ts";
31
- import {
32
- projectAgentRecords
33
- } from "./chunk-KMGKCEO4.ts";
34
- import {
35
- resolveStatefulLimits
36
- } from "./chunk-VDG7LTYE.ts";
37
- import "./chunk-4AQSF7AS.ts";
38
- import {
39
- MAX_UNRESOLVED_REQUIRED_COMPLETIONS,
40
- beginCompletionRequirement,
41
- cancelPendingCompletionRequirements,
42
- completionRequirementKey,
43
- makeCompletionAvailable,
44
- makeCompletionVisible,
45
- pendingRequiredCompletionCount
46
- } from "./chunk-NLT67IZS.ts";
47
- import {
48
- safeTerminalLine
49
- } from "./chunk-SWGQLFSD.ts";
50
- import {
51
- DEFAULT_MAX_CONTEXT_BYTES,
52
- DEFAULT_MAX_OUTPUT_BYTES,
53
- MAX_SUBAGENT_TIMEOUT_MS,
54
- MAX_TOOL_MESSAGE_BYTES,
55
- truncateUtf8
56
- } from "./chunk-H3FP6DLR.ts";
57
-
58
- // src/registry.ts
59
- import { randomUUID } from "node:crypto";
60
-
61
- // src/completion-routing.ts
62
- function resolveCompletionRecipient(agent, getAgent) {
63
- const visited = /* @__PURE__ */ new Set([agent.id]);
64
- let parentId = agent.parentId;
65
- while (parentId && !visited.has(parentId)) {
66
- visited.add(parentId);
67
- const parent = getAgent(parentId);
68
- if (!parent) break;
69
- if (parent.state !== "closed") {
70
- return { recipientId: parent.id, recipientPath: parent.taskPath ?? parent.id };
71
- }
72
- parentId = parent.parentId;
73
- }
74
- return { recipientId: "root", recipientPath: ROOT_TASK_PATH };
75
- }
76
-
77
- // src/transport.ts
78
- var FunctionTransport = class {
79
- constructor(runner) {
80
- this.runner = runner;
81
- }
82
- runner;
83
- kind = "fake";
84
- runTurn(agent, task, signal, onProgress) {
85
- return this.runner(agent, task, signal, onProgress);
86
- }
87
- };
88
- function normalizeTransport(transport) {
89
- return typeof transport === "function" ? new FunctionTransport(transport) : transport;
90
- }
91
-
92
- // src/registry.ts
93
- var DEFAULT_STATEFUL_LIMITS = resolveStatefulLimits();
94
- var MAX_PENDING_COMPLETIONS_PER_AGENT = 20;
95
- var INITIAL_PERSISTENCE_RETRY_DELAY_MS = 25;
96
- var MAX_PERSISTENCE_RETRY_DELAY_MS = 1e3;
97
- function positiveInteger(value, label) {
98
- if (!Number.isSafeInteger(value) || value < 1) {
99
- throw new Error(`${label} must be a positive safe integer`);
100
- }
101
- return value;
102
- }
103
- function nonNegativeInteger(value, label) {
104
- if (!Number.isSafeInteger(value) || value < 0) {
105
- throw new Error(`${label} must be a non-negative safe integer`);
106
- }
107
- return value;
108
- }
109
- function validateTurnTimeout(value) {
110
- if (!Number.isSafeInteger(value) || value < 1 || value > MAX_SUBAGENT_TIMEOUT_MS) {
111
- throw new Error(`Subagent timeoutMs must be between 1 and ${MAX_SUBAGENT_TIMEOUT_MS}`);
112
- }
113
- return value;
114
- }
115
- function clearCurrentTurn(agent) {
116
- agent.currentTask = void 0;
117
- agent.currentRunId = void 0;
118
- agent.currentTurnGeneration = void 0;
119
- agent.currentTimeoutMs = void 0;
120
- agent.currentIdleTimeoutMs = void 0;
121
- agent.currentMaxTurns = void 0;
122
- agent.currentMaxToolCalls = void 0;
123
- agent.currentMailboxMessageIds = void 0;
124
- }
125
- function waitAbortError() {
126
- const error = new Error("Subagent wait was aborted");
127
- error.name = "AbortError";
128
- return error;
129
- }
130
- function waitForPersistenceRetry(milliseconds, signal) {
131
- if (signal.aborted) return Promise.reject(signal.reason);
132
- return new Promise((resolve, reject) => {
133
- const onAbort = () => {
134
- clearTimeout(timer);
135
- reject(signal.reason);
136
- };
137
- const timer = setTimeout(() => {
138
- signal.removeEventListener("abort", onAbort);
139
- resolve();
140
- }, milliseconds);
141
- signal.addEventListener("abort", onAbort, { once: true });
142
- });
143
- }
144
- var AgentRegistry = class {
145
- constructor(transport, options = {}) {
146
- this.options = options;
147
- this.transport = normalizeTransport(transport);
148
- this.maxAgents = positiveInteger(
149
- options.maxAgents ?? DEFAULT_STATEFUL_LIMITS.maxAgents,
150
- "maxAgents"
151
- );
152
- this.maxActiveTurns = positiveInteger(
153
- options.maxActiveTurns ?? DEFAULT_STATEFUL_LIMITS.maxActiveTurns,
154
- "maxActiveTurns"
155
- );
156
- this.maxHistoryTurns = positiveInteger(options.maxHistoryTurns ?? 20, "maxHistoryTurns");
157
- this.maxDepth = nonNegativeInteger(
158
- options.maxDepth ?? DEFAULT_STATEFUL_LIMITS.maxDepth,
159
- "maxDepth"
160
- );
161
- this.maxChildrenPerAgent = positiveInteger(
162
- options.maxChildrenPerAgent ?? DEFAULT_STATEFUL_LIMITS.maxChildrenPerAgent,
163
- "maxChildrenPerAgent"
164
- );
165
- this.maxMailboxMessages = positiveInteger(
166
- options.maxMailboxMessages ?? 100,
167
- "maxMailboxMessages"
168
- );
169
- this.maxMailboxMessageBytes = positiveInteger(
170
- options.maxMailboxMessageBytes ?? 16 * 1024,
171
- "maxMailboxMessageBytes"
172
- );
173
- this.maxTaskBytes = positiveInteger(
174
- options.maxTaskBytes ?? DEFAULT_MAX_CONTEXT_BYTES,
175
- "maxTaskBytes"
176
- );
177
- this.maxTurnOutputBytes = positiveInteger(
178
- options.maxTurnOutputBytes ?? DEFAULT_MAX_OUTPUT_BYTES,
179
- "maxTurnOutputBytes"
180
- );
181
- this.idleTtlMs = positiveInteger(options.idleTtlMs ?? 60 * 60 * 1e3, "idleTtlMs");
182
- this.now = options.now ?? Date.now;
183
- }
184
- options;
185
- agents = /* @__PURE__ */ new Map();
186
- controllers = /* @__PURE__ */ new Map();
187
- running = /* @__PURE__ */ new Map();
188
- queue = [];
189
- changeQueue = Promise.resolve();
190
- shutdownController = new AbortController();
191
- maxAgents;
192
- maxActiveTurns;
193
- maxHistoryTurns;
194
- maxDepth;
195
- maxChildrenPerAgent;
196
- maxMailboxMessages;
197
- maxMailboxMessageBytes;
198
- maxTaskBytes;
199
- maxTurnOutputBytes;
200
- idleTtlMs;
201
- transport;
202
- now;
203
- lastCompletionAt = 0;
204
- restore(records) {
205
- const candidates = new Map(
206
- projectAgentRecords(
207
- records.filter((record) => record.id && record.state !== "closed"),
208
- { maxAgents: this.maxAgents, maxDepth: this.maxDepth }
209
- ).map((record) => [record.id, record])
210
- );
211
- const restorable = [];
212
- for (const record of candidates.values()) {
213
- if (record.parentId && !candidates.has(record.parentId)) continue;
214
- if (record.parentId === record.id) continue;
215
- const seen = /* @__PURE__ */ new Set([record.id]);
216
- let parentId = record.parentId;
217
- let rootId = record.id;
218
- let cyclic = false;
219
- while (parentId) {
220
- if (seen.has(parentId)) {
221
- cyclic = true;
222
- break;
223
- }
224
- seen.add(parentId);
225
- rootId = parentId;
226
- parentId = candidates.get(parentId)?.parentId;
227
- }
228
- const depth = seen.size - 1;
229
- if (!cyclic && depth <= this.maxDepth) restorable.push({ record, rootId, depth });
230
- }
231
- restorable.sort(
232
- (left, right) => left.depth - right.depth || left.record.createdAt - right.record.createdAt || left.record.id.localeCompare(right.record.id)
233
- );
234
- const reservedPaths = new Set(
235
- [...this.agents.values()].flatMap(
236
- (agent) => agent.state !== "closed" && agent.taskPath ? [agent.taskPath] : []
237
- )
238
- );
239
- for (const { record, rootId, depth } of restorable) {
240
- const parentPath = record.parentId ? this.agents.get(record.parentId)?.taskPath : ROOT_TASK_PATH;
241
- if (!parentPath) continue;
242
- const identity = this.reserveRestoredIdentity(record, parentPath, reservedPaths);
243
- for (const completion of record.pendingCompletions ?? []) {
244
- this.lastCompletionAt = Math.max(this.lastCompletionAt, completion.createdAt);
245
- }
246
- this.agents.set(record.id, {
247
- ...record,
248
- ...identity,
249
- state: record.state === "running" || record.state === "starting" ? "interrupted" : record.state,
250
- rootId,
251
- depth,
252
- currentTask: void 0,
253
- turnGeneration: record.turnGeneration ?? 0,
254
- currentRunId: void 0,
255
- currentTurnGeneration: void 0,
256
- pendingCompletions: (record.pendingCompletions ?? []).map((completion) => ({
257
- ...completion
258
- })),
259
- currentTimeoutMs: void 0,
260
- currentIdleTimeoutMs: void 0,
261
- currentMaxTurns: void 0,
262
- currentMaxToolCalls: void 0,
263
- currentMailboxMessageIds: void 0,
264
- children: [],
265
- contextSourceIds: [...record.contextSourceIds ?? []],
266
- capabilityGrant: record.capabilityGrant?.state === "active" ? revokeCapabilityGrant(record.capabilityGrant, "restore-boundary", this.now()) : record.capabilityGrant,
267
- mailbox: (record.mailbox ?? []).slice(-this.maxMailboxMessages).map((message) => ({ ...message, recipientId: record.id })),
268
- completionRequirements: (record.completionRequirements ?? []).map((item) => ({
269
- ...item
270
- })),
271
- history: record.history.slice(-this.maxHistoryTurns).map((turn) => ({ ...turn }))
272
- });
273
- const restored = this.agents.get(record.id);
274
- if (restored && restored.state !== "running" && restored.state !== "starting") {
275
- restored.completionRequirements = cancelPendingCompletionRequirements(
276
- restored.completionRequirements,
277
- restored.state,
278
- this.now()
279
- );
280
- }
281
- }
282
- for (const agent of this.agents.values()) {
283
- if (agent.parentId) {
284
- const parent = this.agents.get(agent.parentId);
285
- if (parent && !parent.children.includes(agent.id)) parent.children.push(agent.id);
286
- }
287
- for (const completion of agent.pendingCompletions ?? []) {
288
- if (!completion.recipientId || !completion.recipientPath) {
289
- Object.assign(completion, this.completionRecipient(agent));
290
- }
291
- this.enqueueCompletionMessage(
292
- agent,
293
- completion,
294
- completion.output || completion.error || "(no output)"
295
- );
296
- }
297
- }
298
- }
299
- async spawn(input) {
300
- if (!input.task.trim()) throw new Error("Subagent tasks cannot be empty");
301
- if (input.timeoutMs !== void 0) validateTurnTimeout(input.timeoutMs);
302
- validateTurnLimits(input);
303
- const existing = this.findBySpawnIdempotencyKey(
304
- input.spawnIdempotencyKey,
305
- input.spawnRequestHash
306
- );
307
- if (existing) return existing;
308
- this.assertRequiredCompletionCapacity(input.completionRequirement);
309
- const task = truncateUtf8(input.task, this.maxTaskBytes).text;
310
- const expired = this.evictExpired();
311
- let expiryReleaseError;
312
- try {
313
- await this.releaseAgents(expired);
314
- } catch (error) {
315
- expiryReleaseError = error;
316
- }
317
- if (expired.length > 0) await this.changed();
318
- if (expiryReleaseError) throw expiryReleaseError;
319
- if (this.retainedCount() >= this.maxAgents) {
320
- throw new Error(`Subagent capacity reached (${this.maxAgents})`);
321
- }
322
- const parent = input.parentId ? this.require(input.parentId) : void 0;
323
- if (parent?.state === "closed") throw new Error(`Cannot spawn under closed agent ${parent.id}`);
324
- if (parent && parent.children.length >= this.maxChildrenPerAgent) {
325
- throw new Error(`Agent ${parent.id} child capacity reached (${this.maxChildrenPerAgent})`);
326
- }
327
- const depth = parent ? parent.depth + 1 : 0;
328
- if (depth > this.maxDepth) throw new Error(`Subagent depth limit reached (${this.maxDepth})`);
329
- const now = this.now();
330
- const id = `sa_${randomUUID()}`;
331
- const taskName = input.taskName ? validateTaskName(input.taskName) : deriveTaskName(id);
332
- const taskPath = joinTaskPath(parent?.taskPath ?? ROOT_TASK_PATH, taskName);
333
- if (this.findByTaskPath(taskPath)) {
334
- throw new Error(`Canonical subagent task path is already retained: ${taskPath}`);
335
- }
336
- const record = {
337
- id,
338
- taskName,
339
- taskPath,
340
- agent: input.agent,
341
- parentId: parent?.id,
342
- rootId: parent?.rootId ?? id,
343
- depth,
344
- children: [],
345
- state: "starting",
346
- createdAt: now,
347
- updatedAt: now,
348
- cwd: input.cwd,
349
- agentScope: input.agentScope,
350
- thinkingLevel: input.thinkingLevel,
351
- timeoutMs: input.timeoutMs,
352
- currentTimeoutMs: input.timeoutMs,
353
- idleTimeoutMs: input.idleTimeoutMs,
354
- currentIdleTimeoutMs: input.idleTimeoutMs,
355
- maxTurns: input.maxTurns,
356
- currentMaxTurns: input.maxTurns,
357
- maxToolCalls: input.maxToolCalls,
358
- currentMaxToolCalls: input.maxToolCalls,
359
- currentTask: task,
360
- turnGeneration: 0,
361
- pendingCompletions: [],
362
- completionRequirements: [],
363
- history: [],
364
- mailbox: [],
365
- context: input.context,
366
- contextSourceIds: input.contextSourceIds,
367
- contextTruncated: input.contextTruncated,
368
- contextTurns: input.contextTurns,
369
- contextBytes: input.contextBytes,
370
- workspaceMode: input.workspaceMode,
371
- spawnIdempotencyKey: input.spawnIdempotencyKey,
372
- spawnRequestHash: input.spawnRequestHash,
373
- contract: input.contract,
374
- resultFormat: input.resultFormat,
375
- executionPlan: input.executionPlan,
376
- capabilityGrant: input.capabilityGrant,
377
- semanticSnapshot: input.semanticSnapshot,
378
- semanticCompatibility: input.semanticCompatibility,
379
- target: input.target
380
- };
381
- this.agents.set(record.id, record);
382
- if (parent) {
383
- parent.children.push(record.id);
384
- parent.updatedAt = now;
385
- }
386
- await this.changed();
387
- this.startTurn(record, task, input, input.completionRequirement);
388
- return this.copy(record);
389
- }
390
- findBySpawnIdempotencyKey(key, requestHash) {
391
- if (!key) return void 0;
392
- const existing = [...this.agents.values()].find(
393
- (agent) => agent.state !== "closed" && agent.spawnIdempotencyKey === key
394
- );
395
- if (!existing) return void 0;
396
- if (!requestHash || existing.spawnRequestHash !== requestHash) {
397
- throw new Error(
398
- "The subagent_spawn idempotencyKey was already used with different parameters"
399
- );
400
- }
401
- return this.copy(existing);
402
- }
403
- async followUp(id, task, options = {}) {
404
- if (!task.trim()) throw new Error("Subagent tasks cannot be empty");
405
- if (options.timeoutMs !== void 0) validateTurnTimeout(options.timeoutMs);
406
- validateTurnLimits(options);
407
- const boundedTask = truncateUtf8(task, this.maxTaskBytes).text;
408
- const agent = this.require(id);
409
- if (![
410
- "idle",
411
- "completed",
412
- "partial",
413
- "blocked",
414
- "needs-input",
415
- "abstained",
416
- "stale",
417
- "interrupted",
418
- "failed"
419
- ].includes(agent.state)) {
420
- throw new Error(`Agent ${id} cannot accept follow-up while ${agent.state}`);
421
- }
422
- this.assertRequiredCompletionCapacity(options.completionRequirement);
423
- const unread = agent.mailbox.filter((message) => !message.readAt).slice(-20);
424
- agent.currentMailboxMessageIds = unread.map((message) => message.id);
425
- this.startTurn(agent, boundedTask, options, options.completionRequirement);
426
- return this.copy(agent);
427
- }
428
- async updateSemanticState(id, executionPlan, capabilityGrant, snapshot, compatibility) {
429
- const agent = this.require(id);
430
- if (agent.state === "running" || agent.state === "starting" || agent.state === "closed") {
431
- throw new Error(`Agent ${id} cannot update semantic state while ${agent.state}`);
432
- }
433
- agent.executionPlan = copyExecutionPlan(executionPlan);
434
- agent.capabilityGrant = structuredClone(capabilityGrant);
435
- agent.semanticSnapshot = structuredClone(snapshot);
436
- agent.semanticCompatibility = structuredClone(compatibility);
437
- agent.updatedAt = this.now();
438
- await this.changed();
439
- return this.copy(agent);
440
- }
441
- async sendMessage(recipientId, content, senderId = "root", deduplicationKey) {
442
- if (!content.trim()) throw new Error("Subagent mailbox messages cannot be empty");
443
- if (deduplicationKey && deduplicationKey.length > 256) {
444
- throw new Error("Subagent mailbox deduplication keys cannot exceed 256 characters");
445
- }
446
- const sender = senderId === "root" ? void 0 : this.require(senderId);
447
- if (sender?.state === "closed")
448
- throw new Error(`Closed agent ${sender.id} cannot send messages`);
449
- const recipient = this.require(recipientId, sender?.id);
450
- if (recipient.state === "closed")
451
- throw new Error(`Cannot message closed agent ${recipient.id}`);
452
- const message = this.enqueueMessage(recipient, content, sender?.id ?? "root", deduplicationKey);
453
- await this.changed();
454
- return { ...message };
455
- }
456
- async readMessages(id, acknowledge = true, limit = this.maxMailboxMessages) {
457
- if (!Number.isSafeInteger(limit) || limit < 1) {
458
- throw new Error("Subagent mailbox read limit must be a positive safe integer");
459
- }
460
- const agent = this.require(id);
461
- const unread = agent.mailbox.filter((message) => !message.readAt).slice(0, limit);
462
- if (acknowledge && unread.length > 0) {
463
- const readAt = this.now();
464
- for (const message of unread) message.readAt = readAt;
465
- await this.changed();
466
- }
467
- return unread.map((message) => ({ ...message }));
468
- }
469
- async acknowledgeVisibleMessages(id, messageIds, completionIds = [], visibleAt = this.now()) {
470
- const agent = this.require(id);
471
- const visibleMessageIds = new Set(messageIds);
472
- const visibleCompletionIds = new Set(completionIds);
473
- const changedMessages = [];
474
- const removedCompletions = [];
475
- for (const message of agent.mailbox) {
476
- if (message.readAt === void 0 && visibleMessageIds.has(message.id)) {
477
- message.readAt = visibleAt;
478
- changedMessages.push(message);
479
- }
480
- if (message.completionId && visibleMessageIds.has(message.id)) {
481
- visibleCompletionIds.add(message.completionId);
482
- }
483
- }
484
- for (const owner of this.agents.values()) {
485
- for (const completion of owner.pendingCompletions ?? []) {
486
- if (!visibleCompletionIds.has(completion.completionId)) continue;
487
- if (completion.recipientId !== agent.id && completion.recipientPath !== agent.taskPath) {
488
- continue;
489
- }
490
- removedCompletions.push({ owner, completion });
491
- }
492
- }
493
- if (changedMessages.length === 0 && removedCompletions.length === 0) return;
494
- for (const { owner, completion } of removedCompletions) {
495
- owner.pendingCompletions = (owner.pendingCompletions ?? []).filter(
496
- (candidate) => candidate.completionId !== completion.completionId
497
- );
498
- }
499
- agent.updatedAt = Math.max(agent.updatedAt, visibleAt);
500
- try {
501
- await this.changed(true);
502
- } catch (error) {
503
- for (const message of changedMessages) message.readAt = void 0;
504
- for (const { owner, completion } of removedCompletions) {
505
- owner.pendingCompletions = [...owner.pendingCompletions ?? [], completion].sort(
506
- (left, right) => left.createdAt - right.createdAt || left.generation - right.generation
507
- );
508
- }
509
- throw error;
510
- }
511
- }
512
- async wait(id, timeoutMs = 3e4, signal) {
513
- if (!Number.isFinite(timeoutMs) || timeoutMs < 1) {
514
- throw new Error("Subagent wait timeout must be a positive finite number");
515
- }
516
- if (signal?.aborted) throw waitAbortError();
517
- const agent = this.require(id);
518
- const agentId = agent.id;
519
- const running = this.running.get(agentId);
520
- if (!running) return { timedOut: false, agent: this.copy(agent) };
521
- let timer;
522
- let onAbort;
523
- const timeout = new Promise((resolve) => {
524
- timer = setTimeout(() => resolve("timeout"), Math.max(1, timeoutMs));
525
- });
526
- const aborted = new Promise((resolve) => {
527
- onAbort = () => resolve("aborted");
528
- signal?.addEventListener("abort", onAbort, { once: true });
529
- });
530
- const result = await Promise.race([running, timeout, aborted]);
531
- if (timer) clearTimeout(timer);
532
- if (onAbort) signal?.removeEventListener("abort", onAbort);
533
- if (result === "aborted") throw waitAbortError();
534
- return result === "timeout" ? { timedOut: true, agent: this.copy(this.require(agentId)) } : { timedOut: false, agent: this.copy(result) };
535
- }
536
- async interruptTree(id) {
537
- const results = [];
538
- for (const target of this.descendants(id).reverse()) {
539
- const agent = this.require(target);
540
- if (agent.state === "running" || agent.state === "starting") {
541
- results.push(await this.interrupt(target));
542
- }
543
- }
544
- return results;
545
- }
546
- async interrupt(id) {
547
- const agent = this.require(id);
548
- const agentId = agent.id;
549
- if (agent.state !== "running" && agent.state !== "starting")
550
- throw new Error(`Agent ${id} is not running`);
551
- if (agent.capabilityGrant?.state === "active") {
552
- agent.capabilityGrant = revokeCapabilityGrant(
553
- agent.capabilityGrant,
554
- "interrupted",
555
- this.now()
556
- );
557
- }
558
- if (agent.executionPlan) {
559
- agent.executionPlan = rotateExecutionPlanGeneration(agent.executionPlan);
560
- }
561
- if (agent.state === "starting") {
562
- const index = this.queue.findIndex((entry) => entry.agent.id === agentId);
563
- if (index >= 0) {
564
- const [entry] = this.queue.splice(index, 1);
565
- const recipient = this.completionRecipient(agent);
566
- const persistedCompletion = {
567
- completionId: `completion:${agent.id}:${randomUUID()}`,
568
- ...recipient,
569
- runId: agent.currentRunId ?? `run:${agent.id}:${randomUUID()}`,
570
- generation: agent.currentTurnGeneration ?? agent.turnGeneration ?? 1,
571
- task: truncateUtf8(entry.task, 256).text,
572
- output: "",
573
- error: "Interrupted before execution",
574
- createdAt: this.completionCreatedAt()
575
- };
576
- agent.state = "interrupted";
577
- agent.completionRequirements = makeCompletionAvailable(agent.completionRequirements, {
578
- runId: persistedCompletion.runId,
579
- generation: persistedCompletion.generation,
580
- completionId: persistedCompletion.completionId,
581
- terminalState: agent.state,
582
- updatedAt: persistedCompletion.createdAt
583
- });
584
- agent.pendingCompletions = [...agent.pendingCompletions ?? [], persistedCompletion];
585
- this.enqueueCompletionMessage(agent, persistedCompletion, persistedCompletion.error);
586
- clearCurrentTurn(agent);
587
- agent.updatedAt = this.now();
588
- const persisted = await this.persistTerminalState().then(
589
- () => true,
590
- () => false
591
- );
592
- const completion = {
593
- ...persistedCompletion,
594
- agent: this.copy(agent)
595
- };
596
- entry.resolve(agent);
597
- this.running.delete(agentId);
598
- if (persisted) await this.notifyTurnComplete(completion);
599
- return this.copy(agent);
600
- }
601
- }
602
- this.controllers.get(agentId)?.abort();
603
- await this.running.get(agentId);
604
- return this.copy(this.require(agentId));
605
- }
606
- async closeTree(id) {
607
- const results = [];
608
- const failures = [];
609
- for (const target of this.descendants(id).reverse()) {
610
- const agent = this.require(target);
611
- if (agent.state === "closed") continue;
612
- try {
613
- results.push(await this.close(target));
614
- } catch (error) {
615
- failures.push(error);
616
- const closed = this.get(target);
617
- if (closed?.state === "closed") results.push(closed);
618
- }
619
- }
620
- if (failures.length > 0) {
621
- throw new AggregateError(failures, `Failed to release ${failures.length} subagent(s)`);
622
- }
623
- return results;
624
- }
625
- async close(id) {
626
- const agent = this.require(id);
627
- const agentId = agent.id;
628
- if (agent.state === "closed") throw new Error(`Agent ${id} is already closed`);
629
- if (agent.children.some((childId) => this.agents.get(childId)?.state !== "closed")) {
630
- throw new Error(`Agent ${id} has active descendants; close the subtree instead`);
631
- }
632
- if (agent.state === "starting" || agent.state === "running") {
633
- if (agent.capabilityGrant?.state === "active") {
634
- agent.capabilityGrant = revokeCapabilityGrant(agent.capabilityGrant, "closed", this.now());
635
- }
636
- if (agent.executionPlan) {
637
- agent.executionPlan = rotateExecutionPlanGeneration(agent.executionPlan);
638
- }
639
- }
640
- if (agent.state === "starting") {
641
- const index = this.queue.findIndex((entry) => entry.agent.id === agentId);
642
- if (index >= 0) {
643
- const [entry] = this.queue.splice(index, 1);
644
- entry.resolve(agent);
645
- this.running.delete(agentId);
646
- }
647
- }
648
- this.controllers.get(agentId)?.abort();
649
- await this.running.get(agentId)?.catch(() => void 0);
650
- agent.state = "closed";
651
- agent.updatedAt = this.now();
652
- agent.completionRequirements = cancelPendingCompletionRequirements(
653
- agent.completionRequirements,
654
- agent.state,
655
- agent.updatedAt
656
- );
657
- if (agent.parentId) {
658
- const parent = this.agents.get(agent.parentId);
659
- if (parent) parent.children = parent.children.filter((childId) => childId !== agentId);
660
- }
661
- clearCurrentTurn(agent);
662
- let releaseError;
663
- try {
664
- await this.transport.release?.(this.copy(agent));
665
- } catch (error) {
666
- releaseError = error;
667
- }
668
- this.pruneClosedAgents();
669
- await this.changed();
670
- if (releaseError) throw releaseError;
671
- return this.copy(agent);
672
- }
673
- async closeAll() {
674
- const roots = [...this.agents.values()].filter((agent) => agent.state !== "closed" && !agent.parentId).map((agent) => agent.id);
675
- const results = await Promise.allSettled(roots.map((id) => this.closeTree(id)));
676
- const failures = results.flatMap(
677
- (result) => result.status === "rejected" ? [result.reason] : []
678
- );
679
- if (failures.length > 0) {
680
- throw new AggregateError(failures, `Failed to close ${failures.length} subagent tree(s)`);
681
- }
682
- }
683
- async shutdown() {
684
- this.shutdownController.abort(new Error("Subagent registry is shutting down"));
685
- for (const entry of this.queue.splice(0)) {
686
- if (entry.agent.capabilityGrant?.state === "active") {
687
- entry.agent.capabilityGrant = revokeCapabilityGrant(
688
- entry.agent.capabilityGrant,
689
- "shutdown",
690
- this.now()
691
- );
692
- }
693
- if (entry.agent.executionPlan) {
694
- entry.agent.executionPlan = rotateExecutionPlanGeneration(entry.agent.executionPlan);
695
- }
696
- entry.agent.state = "interrupted";
697
- clearCurrentTurn(entry.agent);
698
- entry.resolve(entry.agent);
699
- this.running.delete(entry.agent.id);
700
- }
701
- for (const id of this.controllers.keys()) {
702
- const agent = this.agents.get(id);
703
- if (agent?.capabilityGrant?.state === "active") {
704
- agent.capabilityGrant = revokeCapabilityGrant(
705
- agent.capabilityGrant,
706
- "shutdown",
707
- this.now()
708
- );
709
- }
710
- if (agent?.executionPlan) {
711
- agent.executionPlan = rotateExecutionPlanGeneration(agent.executionPlan);
712
- }
713
- }
714
- for (const controller of this.controllers.values()) controller.abort();
715
- await Promise.all([...this.running.values()].map((turn) => turn.catch(() => void 0)));
716
- for (const agent of this.agents.values()) {
717
- if (agent.state !== "closed") {
718
- if (agent.state === "running" || agent.state === "starting") {
719
- agent.state = "interrupted";
720
- }
721
- agent.completionRequirements = cancelPendingCompletionRequirements(
722
- agent.completionRequirements,
723
- agent.state,
724
- this.now()
725
- );
726
- clearCurrentTurn(agent);
727
- }
728
- }
729
- let shutdownError;
730
- try {
731
- await this.transport.shutdown?.();
732
- } catch (error) {
733
- shutdownError = error;
734
- }
735
- await this.changed(true);
736
- if (shutdownError) throw shutdownError;
737
- }
738
- inspectionCounts() {
739
- let activeAgents = 0;
740
- let retainedAgents = 0;
741
- for (const agent of this.agents.values()) {
742
- if (agent.state === "starting" || agent.state === "running") activeAgents++;
743
- if (agent.state !== "closed") retainedAgents++;
744
- }
745
- return { activeAgents, retainedAgents };
746
- }
747
- listInspection(includeClosed = false) {
748
- return [...this.agents.values()].filter((agent) => includeClosed || agent.state !== "closed").sort((left, right) => left.createdAt - right.createdAt).map((agent) => this.inspectSummary(agent));
749
- }
750
- getInspection(id) {
751
- const agent = this.findReference(id);
752
- if (!agent) return void 0;
753
- return {
754
- ...this.inspectSummary(agent),
755
- cwd: agent.cwd,
756
- thinkingLevel: agent.thinkingLevel,
757
- timeoutMs: agent.timeoutMs,
758
- currentTimeoutMs: agent.currentTimeoutMs,
759
- idleTimeoutMs: agent.idleTimeoutMs,
760
- currentIdleTimeoutMs: agent.currentIdleTimeoutMs,
761
- maxTurns: agent.maxTurns,
762
- currentMaxTurns: agent.currentMaxTurns,
763
- maxToolCalls: agent.maxToolCalls,
764
- currentMaxToolCalls: agent.currentMaxToolCalls,
765
- currentTask: agent.currentTask,
766
- currentRunId: agent.currentRunId,
767
- currentTurnGeneration: agent.currentTurnGeneration,
768
- completionRequirements: (agent.completionRequirements ?? []).map((record) => ({
769
- ...record
770
- })),
771
- error: agent.error,
772
- workspaceMode: agent.workspaceMode,
773
- contextTurns: agent.contextTurns,
774
- contextBytes: agent.contextBytes,
775
- contextSources: agent.contextSourceIds?.length,
776
- contextTruncated: agent.contextTruncated,
777
- contract: agent.contract ? structuredClone(agent.contract) : void 0,
778
- resultFormat: agent.resultFormat,
779
- target: agent.target ? { ...agent.target, trust: { ...agent.target.trust } } : void 0,
780
- policy: agent.policy ? {
781
- inherited: [...agent.policy.inherited],
782
- overridden: [...agent.policy.overridden],
783
- unsupported: [...agent.policy.unsupported]
784
- } : void 0,
785
- structuredResult: agent.structuredResult ? copyStructuredResult(agent.structuredResult) : void 0,
786
- termination: agent.termination ? copyTurnTerminationReport(agent.termination) : void 0,
787
- outcome: agent.outcome ? structuredClone(agent.outcome) : void 0,
788
- executionPlan: agent.executionPlan ? copyExecutionPlan(agent.executionPlan) : void 0,
789
- capabilityGrant: agent.capabilityGrant ? structuredClone(agent.capabilityGrant) : void 0,
790
- semanticSnapshot: agent.semanticSnapshot ? structuredClone(agent.semanticSnapshot) : void 0,
791
- semanticCompatibility: agent.semanticCompatibility ? structuredClone(agent.semanticCompatibility) : void 0,
792
- telemetry: agent.telemetry ? copyTelemetry(agent.telemetry) : void 0
793
- };
794
- }
795
- list(includeClosed = false, rootId) {
796
- return [...this.agents.values()].filter((agent) => !rootId || agent.rootId === rootId).filter((agent) => includeClosed || agent.state !== "closed").sort((a, b) => a.createdAt - b.createdAt).map((agent) => this.copy(agent));
797
- }
798
- get(reference) {
799
- return this.resolveAgent(reference);
800
- }
801
- resolveAgent(reference, senderId = "root") {
802
- const agent = this.findReference(reference, senderId);
803
- return agent ? this.copy(agent) : void 0;
804
- }
805
- reconcileCompletionRequirements(activeRecords, observedState) {
806
- if (!observedState) return;
807
- for (const agent of this.agents.values()) {
808
- agent.completionRequirements = (agent.completionRequirements ?? []).flatMap((record) => {
809
- const restored = activeRecords.get(completionRequirementKey(record));
810
- if (!restored) return [];
811
- if (restored.state === "pending" && agent.state !== "running" && agent.state !== "starting") {
812
- return [
813
- {
814
- ...restored,
815
- state: "cancelled",
816
- terminalState: "interrupted",
817
- updatedAt: Math.max(restored.updatedAt, this.now())
818
- }
819
- ];
820
- }
821
- return [{ ...restored }];
822
- });
823
- }
824
- }
825
- listPendingCompletions() {
826
- return [...this.agents.values()].flatMap(
827
- (agent) => (agent.pendingCompletions ?? []).map((completion) => ({
828
- ...completion,
829
- agent: this.copy(agent)
830
- }))
831
- ).sort(
832
- (left, right) => left.createdAt - right.createdAt || left.generation - right.generation || left.completionId.localeCompare(right.completionId)
833
- );
834
- }
835
- async markCompletionDelivered(completionId, deliveredAt) {
836
- const agent = [...this.agents.values()].find(
837
- (candidate) => candidate.pendingCompletions?.some((completion) => completion.completionId === completionId)
838
- );
839
- if (!agent) return;
840
- const acknowledged = (agent.pendingCompletions ?? []).find(
841
- (completion) => completion.completionId === completionId
842
- );
843
- if (!acknowledged) return;
844
- agent.completionRequirements = makeCompletionVisible(
845
- agent.completionRequirements,
846
- completionId,
847
- deliveredAt
848
- );
849
- agent.pendingCompletions = (agent.pendingCompletions ?? []).filter(
850
- (completion) => completion.completionId !== completionId
851
- );
852
- if (agent.telemetry) {
853
- agent.telemetry = {
854
- ...agent.telemetry,
855
- updatedAt: deliveredAt,
856
- timing: { ...agent.telemetry.timing, completionDeliveredAt: deliveredAt }
857
- };
858
- }
859
- agent.updatedAt = Math.max(agent.updatedAt, deliveredAt);
860
- try {
861
- await this.changed(true);
862
- } catch (error) {
863
- agent.completionRequirements = (agent.completionRequirements ?? []).map(
864
- (record) => record.completionId === completionId && record.state === "visible" ? { ...record, state: "available", updatedAt: acknowledged.createdAt } : record
865
- );
866
- if (!agent.pendingCompletions?.some(
867
- (completion) => completion.completionId === acknowledged.completionId
868
- )) {
869
- agent.pendingCompletions = [...agent.pendingCompletions ?? [], acknowledged].sort(
870
- (left, right) => left.createdAt - right.createdAt || left.generation - right.generation
871
- );
872
- }
873
- if (agent.telemetry?.timing.completionDeliveredAt === deliveredAt) {
874
- const { completionDeliveredAt: _discarded, ...timing } = agent.telemetry.timing;
875
- agent.telemetry = { ...agent.telemetry, timing };
876
- }
877
- throw error;
878
- }
879
- }
880
- async sweepExpired() {
881
- const removed = this.evictExpired();
882
- let releaseError;
883
- try {
884
- await this.releaseAgents(removed);
885
- } catch (error) {
886
- releaseError = error;
887
- }
888
- if (removed.length > 0) await this.changed();
889
- if (releaseError) throw releaseError;
890
- return removed.length;
891
- }
892
- startTurn(agent, task, limits = {}, completionRequirement = "background") {
893
- if ((agent.pendingCompletions?.length ?? 0) >= MAX_PENDING_COMPLETIONS_PER_AGENT) {
894
- throw new Error(
895
- `Agent ${agent.id} has ${MAX_PENDING_COMPLETIONS_PER_AGENT} undelivered completions; wait for delivery before another turn`
896
- );
897
- }
898
- agent.turnGeneration = (agent.turnGeneration ?? 0) + 1;
899
- agent.currentTurnGeneration = agent.turnGeneration;
900
- agent.currentRunId = `run:${agent.id}:${randomUUID()}`;
901
- if (completionRequirement === "required") {
902
- agent.completionRequirements = beginCompletionRequirement(agent.completionRequirements, {
903
- runId: agent.currentRunId,
904
- generation: agent.currentTurnGeneration,
905
- createdAt: this.now()
906
- });
907
- }
908
- agent.state = "starting";
909
- agent.error = void 0;
910
- agent.currentTask = task;
911
- agent.currentTimeoutMs = limits.timeoutMs ?? agent.timeoutMs;
912
- agent.currentIdleTimeoutMs = limits.idleTimeoutMs ?? agent.idleTimeoutMs;
913
- agent.currentMaxTurns = limits.maxTurns ?? agent.maxTurns;
914
- agent.currentMaxToolCalls = limits.maxToolCalls ?? agent.maxToolCalls;
915
- agent.structuredResult = void 0;
916
- agent.termination = void 0;
917
- agent.outcome = void 0;
918
- agent.updatedAt = this.now();
919
- agent.telemetry = {
920
- phase: "queued",
921
- queuePosition: this.queue.length + 1,
922
- updatedAt: agent.updatedAt,
923
- timing: { queuedAt: agent.updatedAt },
924
- budgetSource: {
925
- timeout: agent.currentTimeoutMs === void 0 ? "runtime" : "explicit",
926
- idleTimeout: agent.currentIdleTimeoutMs === void 0 ? "runtime" : "explicit",
927
- turnLimit: agent.currentMaxTurns === void 0 ? "runtime" : "explicit",
928
- toolCallLimit: agent.currentMaxToolCalls === void 0 ? "runtime" : "explicit"
929
- }
930
- };
931
- let resolveQueued;
932
- const completion = new Promise((resolve) => {
933
- resolveQueued = resolve;
934
- });
935
- this.running.set(agent.id, completion);
936
- this.queue.push({ agent, task, resolve: resolveQueued });
937
- this.updateQueuePositions();
938
- void this.changed();
939
- this.pumpQueue();
940
- }
941
- pumpQueue() {
942
- while (this.controllers.size < this.maxActiveTurns && this.queue.length > 0) {
943
- const next = this.queue.shift();
944
- if (!next) return;
945
- this.runQueuedTurn(next.agent, next.task, next.resolve);
946
- this.updateQueuePositions();
947
- }
948
- }
949
- runQueuedTurn(agent, task, resolveQueued) {
950
- if (agent.capabilityGrant && agent.executionPlan && !isCapabilityGrantActive(agent.capabilityGrant, agent.executionPlan, this.now())) {
951
- agent.state = "failed";
952
- agent.error = "Capability grant expired or no longer matches the accepted plan";
953
- agent.outcome = classifyStructuredOutcome("failed", "capability-grant-invalid");
954
- const recipient = this.completionRecipient(agent);
955
- const persistedCompletion = {
956
- completionId: `completion:${agent.id}:${randomUUID()}`,
957
- ...recipient,
958
- runId: agent.currentRunId ?? `run:${agent.id}:${randomUUID()}`,
959
- generation: agent.currentTurnGeneration ?? agent.turnGeneration ?? 1,
960
- task: truncateUtf8(task, 256).text,
961
- output: "",
962
- error: truncateUtf8(agent.error, 512).text,
963
- createdAt: this.completionCreatedAt()
964
- };
965
- agent.completionRequirements = makeCompletionAvailable(agent.completionRequirements, {
966
- runId: persistedCompletion.runId,
967
- generation: persistedCompletion.generation,
968
- completionId: persistedCompletion.completionId,
969
- terminalState: agent.state,
970
- updatedAt: persistedCompletion.createdAt
971
- });
972
- agent.pendingCompletions = [...agent.pendingCompletions ?? [], persistedCompletion];
973
- this.enqueueCompletionMessage(agent, persistedCompletion, persistedCompletion.error ?? "");
974
- clearCurrentTurn(agent);
975
- agent.updatedAt = this.now();
976
- void this.persistTerminalState().then(
977
- () => this.notifyTurnComplete({
978
- ...persistedCompletion,
979
- agent: this.copy(agent)
980
- })
981
- ).catch(() => void 0).finally(() => {
982
- resolveQueued(agent);
983
- this.running.delete(agent.id);
984
- });
985
- return;
986
- }
987
- const controller = new AbortController();
988
- this.controllers.set(agent.id, controller);
989
- agent.state = "running";
990
- agent.updatedAt = this.now();
991
- const startedAt = this.now();
992
- const runId = agent.currentRunId ?? `run:${agent.id}:${randomUUID()}`;
993
- const turnGeneration = agent.currentTurnGeneration ?? agent.turnGeneration ?? 1;
994
- const completionKey = `completion:${agent.id}:${randomUUID()}`;
995
- const acceptedPlanId = agent.executionPlan?.id;
996
- let completionContent = "";
997
- let completionOutput = "";
998
- let completionError;
999
- const visibleMailboxMessageIds = [...agent.currentMailboxMessageIds ?? []];
1000
- void this.transport.runTurn(this.copy(agent), task, controller.signal, (progress) => {
1001
- agent.telemetry = {
1002
- ...progress,
1003
- queuePosition: void 0,
1004
- timing: {
1005
- queuedAt: agent.telemetry?.timing.queuedAt,
1006
- ...progress.timing
1007
- }
1008
- };
1009
- }).then(async (outcome) => {
1010
- if (visibleMailboxMessageIds.length > 0) {
1011
- await this.acknowledgeVisibleMessages(
1012
- agent.id,
1013
- visibleMailboxMessageIds,
1014
- [],
1015
- this.now()
1016
- ).catch(() => void 0);
1017
- }
1018
- const output = truncateUtf8(outcome.output, this.maxTurnOutputBytes).text;
1019
- const error = outcome.error ? truncateUtf8(outcome.error, this.maxTurnOutputBytes).text : void 0;
1020
- agent.history.push({
1021
- runId,
1022
- generation: turnGeneration,
1023
- task,
1024
- output,
1025
- startedAt,
1026
- completedAt: this.now(),
1027
- exitCode: outcome.exitCode,
1028
- truncated: outcome.truncated,
1029
- termination: outcome.termination ? copyTurnTerminationReport(outcome.termination) : void 0
1030
- });
1031
- agent.history = agent.history.slice(-this.maxHistoryTurns);
1032
- agent.structuredResult = outcome.structuredResult ?? parseAnyStructuredSubagentResult(output, agent.resultFormat);
1033
- const malformedStructuredResult = agent.resultFormat !== void 0 && agent.resultFormat !== "text" && agent.structuredResult === void 0;
1034
- const finalizedPartial = outcome.termination?.finalization.status === "completed" && output.trim().length > 0;
1035
- agent.outcome = outcome.aborted ? classifyStructuredOutcome("interrupted", "transport-aborted") : malformedStructuredResult ? classifyStructuredOutcome("contract-invalid", "malformed-structured-result") : finalizedPartial ? classifyStructuredOutcome("partial", outcome.termination?.reason) : outcome.outcome ?? (agent.structuredResult?.version === "pi-subagents:result:v2" ? classifyStructuredOutcome(
1036
- agent.structuredResult.status,
1037
- agent.structuredResult.reasonCode
1038
- ) : void 0);
1039
- const staleGeneration = Boolean(
1040
- acceptedPlanId && agent.executionPlan?.id !== acceptedPlanId
1041
- );
1042
- if (staleGeneration) {
1043
- agent.outcome = classifyStructuredOutcome("stale", "cancelled-generation");
1044
- }
1045
- agent.state = staleGeneration ? "stale" : outcome.aborted ? "interrupted" : outcome.exitCode !== 0 && agent.outcome?.status !== "partial" ? "failed" : lifecycleStateForOutcome(agent.outcome?.status);
1046
- agent.error = error;
1047
- if (agent.capabilityGrant?.state === "active") {
1048
- agent.capabilityGrant = revokeCapabilityGrant(
1049
- agent.capabilityGrant,
1050
- "turn-settled",
1051
- this.now()
1052
- );
1053
- }
1054
- agent.policy = outcome.policy;
1055
- agent.telemetry = outcome.telemetry ? {
1056
- ...outcome.telemetry,
1057
- timing: {
1058
- queuedAt: agent.telemetry?.timing.queuedAt,
1059
- ...outcome.telemetry.timing
1060
- },
1061
- budgetSource: outcome.telemetry.budgetSource ?? agent.telemetry?.budgetSource
1062
- } : agent.telemetry;
1063
- agent.termination = outcome.termination ? copyTurnTerminationReport(outcome.termination) : void 0;
1064
- completionOutput = output;
1065
- completionError = error;
1066
- completionContent = output || error || `${agent.id} ${agent.state}`;
1067
- return agent;
1068
- }).catch((error) => {
1069
- const staleGeneration = Boolean(
1070
- acceptedPlanId && agent.executionPlan?.id !== acceptedPlanId
1071
- );
1072
- agent.state = staleGeneration ? "stale" : controller.signal.aborted ? "interrupted" : "failed";
1073
- agent.outcome = classifyStructuredOutcome(
1074
- staleGeneration ? "stale" : controller.signal.aborted ? "interrupted" : "failed",
1075
- staleGeneration ? "cancelled-generation" : controller.signal.aborted ? "transport-aborted" : "transport-error"
1076
- );
1077
- if (agent.capabilityGrant?.state === "active") {
1078
- agent.capabilityGrant = revokeCapabilityGrant(
1079
- agent.capabilityGrant,
1080
- "turn-failed",
1081
- this.now()
1082
- );
1083
- }
1084
- agent.error = truncateUtf8(
1085
- error instanceof Error ? error.message : String(error),
1086
- this.maxTurnOutputBytes
1087
- ).text;
1088
- agent.history.push({
1089
- runId,
1090
- generation: turnGeneration,
1091
- task,
1092
- output: "",
1093
- startedAt,
1094
- completedAt: this.now(),
1095
- exitCode: controller.signal.aborted ? 130 : 1
1096
- });
1097
- agent.history = agent.history.slice(-this.maxHistoryTurns);
1098
- agent.telemetry = {
1099
- ...agent.telemetry ?? {
1100
- phase: "failed",
1101
- updatedAt: this.now(),
1102
- timing: { queuedAt: startedAt }
1103
- },
1104
- phase: controller.signal.aborted ? "interrupted" : "failed",
1105
- failurePhase: agent.telemetry?.phase ?? "running",
1106
- updatedAt: this.now()
1107
- };
1108
- completionError = agent.error;
1109
- completionContent = agent.error;
1110
- return agent;
1111
- }).finally(async () => {
1112
- const recipient = this.completionRecipient(agent);
1113
- const persistedCompletion = {
1114
- completionId: completionKey,
1115
- ...recipient,
1116
- runId,
1117
- generation: turnGeneration,
1118
- task: truncateUtf8(task, 256).text,
1119
- output: truncateUtf8(completionOutput, MAX_TOOL_MESSAGE_BYTES).text,
1120
- error: completionError ? truncateUtf8(completionError, 512).text : void 0,
1121
- createdAt: this.completionCreatedAt()
1122
- };
1123
- agent.completionRequirements = makeCompletionAvailable(agent.completionRequirements, {
1124
- runId,
1125
- generation: turnGeneration,
1126
- completionId: persistedCompletion.completionId,
1127
- terminalState: agent.state,
1128
- updatedAt: persistedCompletion.createdAt
1129
- });
1130
- agent.pendingCompletions = [...agent.pendingCompletions ?? [], persistedCompletion];
1131
- this.enqueueCompletionMessage(agent, persistedCompletion, completionContent);
1132
- clearCurrentTurn(agent);
1133
- agent.updatedAt = this.now();
1134
- const persisted = await this.persistTerminalState().then(
1135
- () => true,
1136
- () => false
1137
- );
1138
- this.controllers.delete(agent.id);
1139
- const turnCompletion = {
1140
- ...persistedCompletion,
1141
- agent: this.copy(agent)
1142
- };
1143
- this.running.delete(agent.id);
1144
- resolveQueued(agent);
1145
- this.pumpQueue();
1146
- if (persisted) await this.notifyTurnComplete(turnCompletion);
1147
- });
1148
- }
1149
- updateQueuePositions() {
1150
- for (const [index, entry] of this.queue.entries()) {
1151
- if (!entry.agent.telemetry) continue;
1152
- entry.agent.telemetry = {
1153
- ...entry.agent.telemetry,
1154
- queuePosition: index + 1,
1155
- updatedAt: this.now()
1156
- };
1157
- }
1158
- }
1159
- completionRecipient(agent) {
1160
- return resolveCompletionRecipient(agent, (id) => this.agents.get(id));
1161
- }
1162
- enqueueCompletionMessage(agent, completion, content) {
1163
- if (!completion.recipientId || completion.recipientId === "root") return;
1164
- const recipient = this.agents.get(completion.recipientId);
1165
- if (!recipient || recipient.state === "closed") return;
1166
- this.enqueueMessage(
1167
- recipient,
1168
- content || "(no output)",
1169
- agent.id,
1170
- completion.completionId,
1171
- completion.completionId
1172
- );
1173
- }
1174
- enqueueMessage(recipient, content, senderId, deduplicationKey, completionId) {
1175
- if (deduplicationKey) {
1176
- const existing = recipient.mailbox.find(
1177
- (message2) => message2.deduplicationKey === deduplicationKey && message2.senderId === senderId
1178
- );
1179
- if (existing) return existing;
1180
- }
1181
- const bounded = truncateUtf8(content, this.maxMailboxMessageBytes);
1182
- const message = {
1183
- id: `msg_${randomUUID()}`,
1184
- senderId,
1185
- recipientId: recipient.id,
1186
- content: bounded.text,
1187
- createdAt: this.now(),
1188
- deduplicationKey,
1189
- completionId
1190
- };
1191
- recipient.mailbox.push(message);
1192
- recipient.mailbox = recipient.mailbox.slice(-this.maxMailboxMessages);
1193
- recipient.updatedAt = this.now();
1194
- return message;
1195
- }
1196
- descendants(id) {
1197
- const root = this.require(id);
1198
- const result = [];
1199
- const visit = (agent) => {
1200
- result.push(agent.id);
1201
- for (const childId of agent.children) {
1202
- const child = this.agents.get(childId);
1203
- if (child) visit(child);
1204
- }
1205
- };
1206
- visit(root);
1207
- return result;
1208
- }
1209
- require(reference, senderId = "root") {
1210
- const agent = this.findReference(reference, senderId);
1211
- if (!agent) throw new Error(`Unknown subagent: ${safeTerminalLine(reference, 256)}`);
1212
- return agent;
1213
- }
1214
- findReference(reference, senderId = "root") {
1215
- const direct = this.agents.get(reference);
1216
- if (direct) return direct;
1217
- const sender = senderId === "root" ? void 0 : this.agents.get(senderId) ?? this.findByTaskPath(senderId);
1218
- if (senderId !== "root" && !sender) return void 0;
1219
- let taskPath;
1220
- try {
1221
- taskPath = resolveTaskPath(sender?.taskPath ?? ROOT_TASK_PATH, reference);
1222
- } catch {
1223
- return void 0;
1224
- }
1225
- return this.findByTaskPath(taskPath);
1226
- }
1227
- findByTaskPath(taskPath) {
1228
- return [...this.agents.values()].find(
1229
- (agent) => agent.state !== "closed" && agent.taskPath === taskPath
1230
- );
1231
- }
1232
- reserveRestoredIdentity(record, parentPath, reservedPaths) {
1233
- let taskName;
1234
- try {
1235
- taskName = record.taskName ? validateTaskName(record.taskName) : void 0;
1236
- } catch {
1237
- taskName = void 0;
1238
- }
1239
- if (!taskName && record.taskPath) {
1240
- try {
1241
- const storedPath = validateTaskPath(record.taskPath);
1242
- const storedName = storedPath.slice(storedPath.lastIndexOf("/") + 1);
1243
- taskName = validateTaskName(storedName);
1244
- } catch {
1245
- taskName = void 0;
1246
- }
1247
- }
1248
- taskName ??= deriveTaskName(record.id);
1249
- let taskPath = joinTaskPath(parentPath, taskName);
1250
- if (reservedPaths.has(taskPath)) {
1251
- taskName = deriveTaskName(record.id);
1252
- taskPath = joinTaskPath(parentPath, taskName);
1253
- }
1254
- if (reservedPaths.has(taskPath)) {
1255
- throw new Error(`Cannot restore duplicate canonical subagent task path: ${taskPath}`);
1256
- }
1257
- reservedPaths.add(taskPath);
1258
- return { taskName, taskPath };
1259
- }
1260
- assertRequiredCompletionCapacity(mode) {
1261
- if (mode !== "required") return;
1262
- const unresolved = [...this.agents.values()].reduce(
1263
- (sum, agent) => sum + pendingRequiredCompletionCount(agent),
1264
- 0
1265
- );
1266
- if (unresolved >= MAX_UNRESOLVED_REQUIRED_COMPLETIONS) {
1267
- throw new Error(
1268
- `Required subagent completion capacity reached (${MAX_UNRESOLVED_REQUIRED_COMPLETIONS}); wait for exact completion visibility or terminalize an existing requirement`
1269
- );
1270
- }
1271
- }
1272
- retainedCount() {
1273
- return [...this.agents.values()].filter((agent) => agent.state !== "closed").length;
1274
- }
1275
- completionCreatedAt() {
1276
- this.lastCompletionAt = Math.max(this.now(), this.lastCompletionAt + 1);
1277
- return this.lastCompletionAt;
1278
- }
1279
- evictExpired() {
1280
- const cutoff = this.now() - this.idleTtlMs;
1281
- const protectedIds = /* @__PURE__ */ new Set();
1282
- for (const agent of this.agents.values()) {
1283
- if (agent.state !== "running" && agent.state !== "starting" && (agent.pendingCompletions?.length ?? 0) === 0) {
1284
- continue;
1285
- }
1286
- let current = agent;
1287
- while (current) {
1288
- protectedIds.add(current.id);
1289
- current = current.parentId ? this.agents.get(current.parentId) : void 0;
1290
- }
1291
- }
1292
- const removed = [];
1293
- const candidates = [...this.agents.values()].sort((left, right) => right.depth - left.depth);
1294
- for (const agent of candidates) {
1295
- if (protectedIds.has(agent.id) || agent.updatedAt >= cutoff) continue;
1296
- if (agent.children.some((childId) => this.agents.get(childId)?.state !== "closed")) continue;
1297
- this.agents.delete(agent.id);
1298
- if (agent.parentId) {
1299
- const parent = this.agents.get(agent.parentId);
1300
- if (parent) parent.children = parent.children.filter((childId) => childId !== agent.id);
1301
- }
1302
- removed.push(this.copy(agent));
1303
- }
1304
- return removed;
1305
- }
1306
- async releaseAgents(agents) {
1307
- if (!this.transport.release || agents.length === 0) return;
1308
- const results = await Promise.allSettled(
1309
- agents.map((agent) => this.transport.release?.(agent))
1310
- );
1311
- const failures = results.flatMap(
1312
- (result) => result.status === "rejected" ? [result.reason] : []
1313
- );
1314
- if (failures.length > 0) {
1315
- throw new AggregateError(
1316
- failures,
1317
- `Failed to release ${failures.length} subagent transport session(s)`
1318
- );
1319
- }
1320
- }
1321
- pruneClosedAgents() {
1322
- const closed = [...this.agents.values()].filter((agent) => agent.state === "closed").sort((left, right) => right.updatedAt - left.updatedAt);
1323
- for (const agent of closed.slice(this.maxAgents)) this.agents.delete(agent.id);
1324
- }
1325
- async persistTerminalState() {
1326
- let failures = 0;
1327
- for (; ; ) {
1328
- try {
1329
- await this.changed(true);
1330
- return;
1331
- } catch (error) {
1332
- if (this.shutdownController.signal.aborted) throw error;
1333
- failures++;
1334
- if (failures === 1) continue;
1335
- const delay = Math.min(
1336
- INITIAL_PERSISTENCE_RETRY_DELAY_MS * 2 ** (failures - 2),
1337
- MAX_PERSISTENCE_RETRY_DELAY_MS
1338
- );
1339
- await waitForPersistenceRetry(delay, this.shutdownController.signal);
1340
- }
1341
- }
1342
- }
1343
- async notifyTurnComplete(completion) {
1344
- try {
1345
- await this.options.onTurnComplete?.(completion);
1346
- } catch {
1347
- }
1348
- }
1349
- changed(propagateError = false) {
1350
- const snapshot = this.list(true);
1351
- const next = this.changeQueue.then(async () => {
1352
- try {
1353
- await this.options.onChange?.(snapshot);
1354
- } catch (error) {
1355
- if (propagateError) throw error;
1356
- }
1357
- });
1358
- this.changeQueue = next.catch(() => void 0);
1359
- return next;
1360
- }
1361
- inspectSummary(agent) {
1362
- let unreadMessages = 0;
1363
- for (const message of agent.mailbox) {
1364
- if (message.readAt === void 0) unreadMessages++;
1365
- }
1366
- return {
1367
- id: agent.id,
1368
- taskName: agent.taskName,
1369
- taskPath: agent.taskPath,
1370
- agent: agent.agent,
1371
- state: agent.state,
1372
- createdAt: agent.createdAt,
1373
- updatedAt: agent.updatedAt,
1374
- historyCount: agent.history.length,
1375
- unreadMessages,
1376
- turnGeneration: agent.turnGeneration ?? 0,
1377
- pendingCompletionCount: agent.pendingCompletions?.length ?? 0,
1378
- pendingRequiredCompletionCount: pendingRequiredCompletionCount(agent)
1379
- };
1380
- }
1381
- copy(agent) {
1382
- return {
1383
- ...agent,
1384
- children: [...agent.children],
1385
- contextSourceIds: [...agent.contextSourceIds ?? []],
1386
- currentMailboxMessageIds: agent.currentMailboxMessageIds ? [...agent.currentMailboxMessageIds] : void 0,
1387
- pendingCompletions: (agent.pendingCompletions ?? []).map((completion) => ({
1388
- ...completion
1389
- })),
1390
- completionRequirements: (agent.completionRequirements ?? []).map((record) => ({
1391
- ...record
1392
- })),
1393
- history: agent.history.map((turn) => ({ ...turn })),
1394
- mailbox: agent.mailbox.map((message) => ({ ...message })),
1395
- contract: agent.contract ? structuredClone(agent.contract) : void 0,
1396
- target: agent.target ? { ...agent.target, trust: { ...agent.target.trust } } : void 0,
1397
- policy: agent.policy ? {
1398
- inherited: [...agent.policy.inherited],
1399
- overridden: [...agent.policy.overridden],
1400
- unsupported: [...agent.policy.unsupported]
1401
- } : void 0,
1402
- structuredResult: agent.structuredResult ? copyStructuredResult(agent.structuredResult) : void 0,
1403
- termination: agent.termination ? copyTurnTerminationReport(agent.termination) : void 0,
1404
- outcome: agent.outcome ? structuredClone(agent.outcome) : void 0,
1405
- executionPlan: agent.executionPlan ? copyExecutionPlan(agent.executionPlan) : void 0,
1406
- capabilityGrant: agent.capabilityGrant ? structuredClone(agent.capabilityGrant) : void 0,
1407
- semanticSnapshot: agent.semanticSnapshot ? structuredClone(agent.semanticSnapshot) : void 0,
1408
- semanticCompatibility: agent.semanticCompatibility ? structuredClone(agent.semanticCompatibility) : void 0,
1409
- telemetry: agent.telemetry ? copyTelemetry(agent.telemetry) : void 0
1410
- };
1411
- }
1412
- };
1413
- function lifecycleStateForOutcome(status) {
1414
- switch (status) {
1415
- case "partial":
1416
- return "partial";
1417
- case "blocked":
1418
- case "needs-input":
1419
- case "abstained":
1420
- case "stale":
1421
- return status;
1422
- case "failed":
1423
- case "contract-invalid":
1424
- return "failed";
1425
- case "interrupted":
1426
- return "interrupted";
1427
- default:
1428
- return "completed";
1429
- }
1430
- }
1431
- function copyStructuredResult(value) {
1432
- return structuredClone(value);
1433
- }
1434
- function copyTelemetry(value) {
1435
- return {
1436
- ...value,
1437
- timing: { ...value.timing },
1438
- usage: value.usage ? { ...value.usage } : void 0,
1439
- budgetSource: value.budgetSource ? { ...value.budgetSource } : void 0
1440
- };
1441
- }
1442
- export {
1443
- AgentRegistry
1444
- };
1445
- //# sourceMappingURL=registry-BT54L6CY.ts.map