@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
@@ -0,0 +1,667 @@
1
+ // @generated by scripts/build-runtime.mjs; do not edit.
2
+ // @ts-nocheck -- generated entries use .ts extensions for Pi's Jiti loader.
3
+
4
+ // src/message-broker.ts
5
+ import { randomBytes, randomUUID } from "node:crypto";
6
+ import net from "node:net";
7
+ var BROKER_HOST = "127.0.0.1";
8
+ var MAX_MESSAGE_BYTES = 48 * 1024;
9
+ var MAX_MESSAGE_LINES = 1992;
10
+ var MAX_FRAME_BYTES = 384 * 1024;
11
+ var MAX_ERROR_BYTES = 8 * 1024;
12
+ var MAX_OUTSTANDING_REQUESTS = 4;
13
+ var MAX_IDENTIFIER_LENGTH = 128;
14
+ var MAX_CONNECTIONS = 32;
15
+ var REQUEST_FRAME_TIMEOUT_MS = 2e3;
16
+ var MAX_TIMEOUT_MS = 2147483647;
17
+ var MAX_RETAINED_CONSUMED_REQUESTS = 4;
18
+ var CHILD_WAIT_INTERRUPTED_ERROR = "Subagent wait was interrupted by an incoming main-agent request. The original request remains active.";
19
+ var MessageBroker = class {
20
+ constructor(options) {
21
+ this.options = options;
22
+ this.createServer = options.createServer ?? ((listener) => net.createServer(listener));
23
+ this.now = options.now ?? Date.now;
24
+ this.requestFrameTimeoutMs = options.requestFrameTimeoutMs ?? REQUEST_FRAME_TIMEOUT_MS;
25
+ if (!Number.isFinite(this.requestFrameTimeoutMs) || this.requestFrameTimeoutMs <= 0) {
26
+ throw new Error("Subagent broker frame timeout must be positive.");
27
+ }
28
+ }
29
+ options;
30
+ server;
31
+ starting;
32
+ address;
33
+ failure;
34
+ generation = 0;
35
+ sockets = /* @__PURE__ */ new Set();
36
+ jobsByToken = /* @__PURE__ */ new Map();
37
+ tokenByJob = /* @__PURE__ */ new Map();
38
+ requests = /* @__PURE__ */ new Map();
39
+ inboundMessageListeners = /* @__PURE__ */ new Set();
40
+ pendingInboundResponse = false;
41
+ createServer;
42
+ now;
43
+ requestFrameTimeoutMs;
44
+ async start() {
45
+ if (this.server && this.address && !this.failure) return;
46
+ if (this.starting) return this.starting;
47
+ const ownerGeneration = ++this.generation;
48
+ this.failure = void 0;
49
+ this.starting = new Promise((resolve, reject) => {
50
+ const server = this.createServer((socket) => this.accept(socket));
51
+ server.maxConnections = MAX_CONNECTIONS;
52
+ const onStartError = (error) => {
53
+ server.close(() => void 0);
54
+ reject(error);
55
+ };
56
+ server.once("error", onStartError);
57
+ server.listen({ host: BROKER_HOST, port: 0 }, () => {
58
+ server.off("error", onStartError);
59
+ if (ownerGeneration !== this.generation) {
60
+ server.close(() => void 0);
61
+ reject(new Error("Subagent message broker start was superseded."));
62
+ return;
63
+ }
64
+ const address = server.address();
65
+ if (!isLoopbackAddress(address)) {
66
+ server.close(() => void 0);
67
+ reject(new Error("Subagent message broker did not bind to loopback."));
68
+ return;
69
+ }
70
+ this.server = server;
71
+ this.address = { host: BROKER_HOST, port: address.port };
72
+ server.on("error", (error) => this.fail(error));
73
+ server.unref();
74
+ resolve();
75
+ });
76
+ }).catch((error) => {
77
+ const message = truncateError(error instanceof Error ? error.message : String(error));
78
+ this.failure = message;
79
+ throw new Error(`Subagent message broker failed to start: ${message}`);
80
+ }).finally(() => {
81
+ this.starting = void 0;
82
+ });
83
+ return this.starting;
84
+ }
85
+ assertReady() {
86
+ if (this.server && this.address && !this.failure) return;
87
+ throw new Error(
88
+ this.failure ? `Subagent messaging is unavailable: ${this.failure}` : "Subagent messaging is unavailable because the session broker is not ready."
89
+ );
90
+ }
91
+ issueCredentials(input) {
92
+ this.assertReady();
93
+ if (this.tokenByJob.has(input.jobId)) {
94
+ throw new Error(`Subagent messaging credentials already exist for ${input.jobId}.`);
95
+ }
96
+ const token = randomBytes(32).toString("hex");
97
+ const record = { ...input, token };
98
+ this.jobsByToken.set(token, record);
99
+ this.tokenByJob.set(input.jobId, token);
100
+ return { host: BROKER_HOST, port: this.address?.port ?? 0, token };
101
+ }
102
+ createMainRequest(jobId, message) {
103
+ this.assertReady();
104
+ const job = this.requireJob(jobId);
105
+ return this.createRequest(job, "main", message);
106
+ }
107
+ replyFromMain(requestId, message) {
108
+ this.assertReady();
109
+ return this.acceptResponse("main", void 0, requestId, message);
110
+ }
111
+ rollbackMainRequest(requestId) {
112
+ const request = this.requests.get(requestId);
113
+ if (request?.origin === "main" && request.response === void 0) {
114
+ this.clearWaiter(request);
115
+ this.requests.delete(requestId);
116
+ }
117
+ }
118
+ revokeJob(jobId, reason = "Subagent job is no longer active.") {
119
+ const token = this.tokenByJob.get(jobId);
120
+ if (token) {
121
+ this.tokenByJob.delete(jobId);
122
+ this.jobsByToken.delete(token);
123
+ }
124
+ for (const request of [...this.requests.values()]) {
125
+ if (request.jobId !== jobId) continue;
126
+ if (request.waiter) this.respondError(request.waiter.socket, reason);
127
+ this.clearWaiter(request);
128
+ this.requests.delete(request.requestId);
129
+ }
130
+ }
131
+ hasPendingMainRequest() {
132
+ return [...this.requests.values()].some(
133
+ (request) => request.origin === "child" && request.response === void 0
134
+ );
135
+ }
136
+ takePendingInboundResponse() {
137
+ const pending = this.pendingInboundResponse;
138
+ this.pendingInboundResponse = false;
139
+ return pending;
140
+ }
141
+ markMainRequestQueued(requestId) {
142
+ const request = this.requests.get(requestId);
143
+ if (request?.origin !== "main") {
144
+ throw new Error("Unknown or expired main-agent subagent request.");
145
+ }
146
+ request.deliveryQueued = true;
147
+ return request.response === void 0;
148
+ }
149
+ interruptChildWaits(jobId) {
150
+ let interrupted = 0;
151
+ for (const request of this.requests.values()) {
152
+ if (request.jobId !== jobId || request.origin !== "child" || !request.waiter) continue;
153
+ const socket = request.waiter.socket;
154
+ this.clearWaiter(request);
155
+ this.respondError(socket, CHILD_WAIT_INTERRUPTED_ERROR);
156
+ interrupted++;
157
+ }
158
+ return interrupted;
159
+ }
160
+ subscribeInboundMessage(listener) {
161
+ this.inboundMessageListeners.add(listener);
162
+ if (this.hasPendingMainRequest()) listener();
163
+ return () => this.inboundMessageListeners.delete(listener);
164
+ }
165
+ async shutdown() {
166
+ ++this.generation;
167
+ const starting = this.starting;
168
+ if (starting) await starting.catch(() => void 0);
169
+ for (const jobId of [...this.tokenByJob.keys()]) {
170
+ this.revokeJob(jobId, "Subagent session shut down.");
171
+ }
172
+ this.requests.clear();
173
+ this.inboundMessageListeners.clear();
174
+ this.pendingInboundResponse = false;
175
+ for (const socket of this.sockets) socket.destroy();
176
+ this.sockets.clear();
177
+ const server = this.server;
178
+ this.server = void 0;
179
+ this.address = void 0;
180
+ this.failure = void 0;
181
+ if (!server?.listening) return;
182
+ await new Promise((resolve) => server.close(() => resolve()));
183
+ }
184
+ requireJob(jobId) {
185
+ const token = this.tokenByJob.get(jobId);
186
+ const job = token ? this.jobsByToken.get(token) : void 0;
187
+ if (!job) throw new Error("Unknown or inactive subagent job.");
188
+ return job;
189
+ }
190
+ hasQueuedRequestForChild(jobId) {
191
+ return [...this.requests.values()].some(
192
+ (request) => request.jobId === jobId && request.origin === "main" && request.deliveryQueued === true && request.response === void 0
193
+ );
194
+ }
195
+ createRequest(job, origin, message) {
196
+ validateMessage(message, "Subagent request");
197
+ const outstanding = [...this.requests.values()].filter(
198
+ (request2) => request2.jobId === job.jobId && request2.consumedAt === void 0
199
+ ).length;
200
+ if (outstanding >= MAX_OUTSTANDING_REQUESTS) {
201
+ throw new Error(
202
+ `Subagent job may have at most ${MAX_OUTSTANDING_REQUESTS} outstanding requests.`
203
+ );
204
+ }
205
+ const request = {
206
+ requestId: `req_${randomUUID()}`,
207
+ jobId: job.jobId,
208
+ generation: job.generation,
209
+ origin,
210
+ expectedResponder: origin === "main" ? "child" : "main",
211
+ message,
212
+ createdAt: this.now()
213
+ };
214
+ this.requests.set(request.requestId, request);
215
+ if (origin === "child") {
216
+ try {
217
+ this.deliverInbound({
218
+ kind: "request",
219
+ requestId: request.requestId,
220
+ jobId: request.jobId,
221
+ message: request.message
222
+ });
223
+ } catch (error) {
224
+ this.requests.delete(request.requestId);
225
+ throw error;
226
+ }
227
+ }
228
+ return { requestId: request.requestId, accepted: true, duplicate: false };
229
+ }
230
+ acceptResponse(responder, job, requestId, message) {
231
+ validateRequestId(requestId);
232
+ validateMessage(message, "Subagent response");
233
+ const request = this.requests.get(requestId);
234
+ if (!request || request.expectedResponder !== responder || job && (request.jobId !== job.jobId || request.generation !== job.generation)) {
235
+ throw new Error("Unknown, expired, or unauthorized subagent request.");
236
+ }
237
+ if (request.response !== void 0) {
238
+ return { requestId, accepted: false, duplicate: true };
239
+ }
240
+ request.response = message;
241
+ if (responder === "child") {
242
+ try {
243
+ this.deliverInbound({
244
+ kind: "response",
245
+ requestId,
246
+ jobId: request.jobId,
247
+ message
248
+ });
249
+ this.markConsumed(request);
250
+ } catch (error) {
251
+ request.response = void 0;
252
+ throw error;
253
+ }
254
+ } else if (request.waiter) {
255
+ const socket = request.waiter.socket;
256
+ this.clearWaiter(request);
257
+ this.respond(socket, { ok: true, response: message }, () => this.markConsumed(request));
258
+ }
259
+ return { requestId, accepted: true, duplicate: false };
260
+ }
261
+ deliverInbound(message) {
262
+ this.options.onMessage(message);
263
+ if (message.kind === "response" && this.inboundMessageListeners.size === 0) {
264
+ this.pendingInboundResponse = true;
265
+ }
266
+ for (const listener of [...this.inboundMessageListeners]) {
267
+ try {
268
+ listener();
269
+ } catch {
270
+ }
271
+ }
272
+ }
273
+ accept(socket) {
274
+ if (!this.server || this.failure || this.sockets.size >= MAX_CONNECTIONS) {
275
+ socket.destroy();
276
+ return;
277
+ }
278
+ this.sockets.add(socket);
279
+ socket.setNoDelay(true);
280
+ let frame = Buffer.alloc(0);
281
+ let handled = false;
282
+ const frameTimer = setTimeout(() => {
283
+ if (handled) return;
284
+ handled = true;
285
+ this.respondError(socket, "Subagent broker request frame timed out.");
286
+ }, this.requestFrameTimeoutMs);
287
+ frameTimer.unref();
288
+ const cleanup = () => {
289
+ clearTimeout(frameTimer);
290
+ this.sockets.delete(socket);
291
+ for (const request of this.requests.values()) {
292
+ if (request.waiter?.socket === socket) this.clearWaiter(request);
293
+ }
294
+ };
295
+ socket.on("data", (chunk) => {
296
+ if (handled) return;
297
+ frame = Buffer.concat([frame, chunk]);
298
+ if (frame.byteLength > MAX_FRAME_BYTES) {
299
+ handled = true;
300
+ clearTimeout(frameTimer);
301
+ this.respondError(socket, "Subagent broker request exceeded its size limit.");
302
+ return;
303
+ }
304
+ const newline = frame.indexOf(10);
305
+ if (newline < 0) return;
306
+ handled = true;
307
+ clearTimeout(frameTimer);
308
+ socket.removeAllListeners("data");
309
+ const trailing = frame.subarray(newline + 1).toString("utf8").trim();
310
+ if (trailing) {
311
+ this.respondError(socket, "Subagent broker accepts one request per connection.");
312
+ return;
313
+ }
314
+ this.handleFrame(socket, frame.subarray(0, newline).toString("utf8"));
315
+ });
316
+ socket.once("close", cleanup);
317
+ socket.once("error", cleanup);
318
+ }
319
+ handleFrame(socket, frame) {
320
+ let request;
321
+ try {
322
+ const parsed = JSON.parse(frame);
323
+ if (!isRecord(parsed)) throw new Error();
324
+ request = parsed;
325
+ } catch {
326
+ this.respondError(socket, "Malformed subagent broker request.");
327
+ return;
328
+ }
329
+ const job = typeof request.token === "string" ? this.jobsByToken.get(request.token) : void 0;
330
+ if (!job) {
331
+ this.respondError(socket, "Unauthenticated subagent broker request.");
332
+ return;
333
+ }
334
+ try {
335
+ if (request.type === "send") {
336
+ this.handleSend(socket, job, request);
337
+ return;
338
+ }
339
+ if (request.type === "wait") {
340
+ this.handleWait(socket, job, request);
341
+ return;
342
+ }
343
+ throw new Error("Unsupported subagent broker request.");
344
+ } catch (error) {
345
+ this.respondError(socket, error instanceof Error ? error.message : String(error));
346
+ }
347
+ }
348
+ handleSend(socket, job, request) {
349
+ if (typeof request.message !== "string") {
350
+ throw new Error("subagent_send requires a message string.");
351
+ }
352
+ const hasRecipient = typeof request.recipient === "string";
353
+ const hasRequestId = typeof request.requestId === "string";
354
+ if (hasRecipient === hasRequestId) {
355
+ throw new Error("subagent_send requires exactly one of recipient or requestId.");
356
+ }
357
+ const acknowledgement = hasRecipient ? request.recipient === "main" ? this.createRequest(job, "child", request.message) : (() => {
358
+ throw new Error('A subagent may send new requests only to recipient "main".');
359
+ })() : this.acceptResponse("child", job, request.requestId ?? "", request.message);
360
+ this.respond(socket, { ok: true, ...acknowledgement });
361
+ }
362
+ handleWait(socket, job, request) {
363
+ if (typeof request.requestId !== "string") {
364
+ throw new Error("Subagent wait requires a request ID.");
365
+ }
366
+ validateRequestId(request.requestId);
367
+ if (request.timeoutMs !== void 0) validateTimeout(request.timeoutMs);
368
+ const record = this.requests.get(request.requestId);
369
+ if (record?.origin !== "child" || record.jobId !== job.jobId || record.generation !== job.generation) {
370
+ throw new Error("Unknown or expired subagent request.");
371
+ }
372
+ if (record.consumedAt !== void 0 && record.response !== void 0) {
373
+ this.respond(socket, { ok: true, response: record.response });
374
+ return;
375
+ }
376
+ if (record.response !== void 0) {
377
+ this.respond(
378
+ socket,
379
+ { ok: true, response: record.response },
380
+ () => this.markConsumed(record)
381
+ );
382
+ return;
383
+ }
384
+ if (this.hasQueuedRequestForChild(job.jobId)) {
385
+ this.respondError(socket, CHILD_WAIT_INTERRUPTED_ERROR);
386
+ return;
387
+ }
388
+ if (record.waiter) {
389
+ throw new Error(`A wait is already active for subagent request ${request.requestId}.`);
390
+ }
391
+ const waiter = { socket };
392
+ record.waiter = waiter;
393
+ if (request.timeoutMs !== void 0) {
394
+ waiter.timer = setTimeout(() => {
395
+ if (record.waiter !== waiter) return;
396
+ this.clearWaiter(record);
397
+ this.respondError(socket, "Subagent response wait timed out.");
398
+ }, request.timeoutMs);
399
+ waiter.timer.unref();
400
+ }
401
+ }
402
+ markConsumed(request) {
403
+ if (this.requests.get(request.requestId) !== request || request.response === void 0) return;
404
+ request.consumedAt ??= this.now();
405
+ const consumed = [...this.requests.values()].filter(
406
+ (candidate) => candidate.jobId === request.jobId && candidate.consumedAt !== void 0
407
+ ).sort((left, right) => (left.consumedAt ?? 0) - (right.consumedAt ?? 0));
408
+ for (const expired of consumed.slice(
409
+ 0,
410
+ Math.max(0, consumed.length - MAX_RETAINED_CONSUMED_REQUESTS)
411
+ )) {
412
+ this.requests.delete(expired.requestId);
413
+ }
414
+ }
415
+ clearWaiter(request) {
416
+ if (request.waiter?.timer) clearTimeout(request.waiter.timer);
417
+ request.waiter = void 0;
418
+ }
419
+ respondError(socket, error) {
420
+ this.respond(socket, { ok: false, error: truncateError(error) });
421
+ }
422
+ respond(socket, value, onFlushed) {
423
+ if (socket.destroyed) return;
424
+ let content = `${JSON.stringify(value)}
425
+ `;
426
+ if (Buffer.byteLength(content, "utf8") > MAX_FRAME_BYTES) {
427
+ content = `${JSON.stringify({ ok: false, error: "Subagent broker response exceeded its size limit." })}
428
+ `;
429
+ }
430
+ socket.end(content, onFlushed);
431
+ }
432
+ fail(error) {
433
+ this.failure = truncateError(error.message);
434
+ for (const jobId of [...this.tokenByJob.keys()]) {
435
+ this.revokeJob(jobId, "Subagent message broker failed.");
436
+ }
437
+ for (const socket of this.sockets) socket.destroy();
438
+ this.sockets.clear();
439
+ this.address = void 0;
440
+ }
441
+ };
442
+ function validateMessage(message, label) {
443
+ if (!message.trim()) throw new Error(`${label} is required.`);
444
+ if (message.includes("\0")) throw new Error(`${label} must not contain NUL bytes.`);
445
+ if (Buffer.byteLength(message, "utf8") > MAX_MESSAGE_BYTES) {
446
+ throw new Error(`${label} must be at most ${MAX_MESSAGE_BYTES} UTF-8 bytes.`);
447
+ }
448
+ if (lineCount(message) > MAX_MESSAGE_LINES) {
449
+ throw new Error(`${label} must contain at most ${MAX_MESSAGE_LINES} lines.`);
450
+ }
451
+ }
452
+ function sanitizeTerminalText(value) {
453
+ return [...value].filter((character) => {
454
+ const codePoint = character.codePointAt(0) ?? 0;
455
+ if (character === "\n" || character === " ") return true;
456
+ if (codePoint <= 31 || codePoint >= 127 && codePoint <= 159) return false;
457
+ return !(codePoint >= 8234 && codePoint <= 8238 || codePoint >= 8294 && codePoint <= 8297);
458
+ }).join("");
459
+ }
460
+ function validateRequestId(requestId) {
461
+ if (requestId.length > MAX_IDENTIFIER_LENGTH || !/^req_[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/u.test(requestId)) {
462
+ throw new Error("Invalid subagent request ID.");
463
+ }
464
+ }
465
+ function validateTimeout(timeoutMs) {
466
+ if (!Number.isFinite(timeoutMs) || timeoutMs <= 0 || timeoutMs > MAX_TIMEOUT_MS) {
467
+ throw new Error("Subagent wait timeout is outside the supported range.");
468
+ }
469
+ }
470
+ function lineCount(value) {
471
+ let count = 1;
472
+ for (const character of value) if (character === "\n") count++;
473
+ return count;
474
+ }
475
+ function truncateError(error) {
476
+ const bytes = Buffer.from(error, "utf8");
477
+ if (bytes.length <= MAX_ERROR_BYTES) return error;
478
+ return `${bytes.subarray(0, Math.max(0, MAX_ERROR_BYTES - 18)).toString("utf8").replace(/�+$/gu, "")}
479
+ \u2026 [truncated]`;
480
+ }
481
+ function isRecord(value) {
482
+ return typeof value === "object" && value !== null && !Array.isArray(value);
483
+ }
484
+ function isLoopbackAddress(address) {
485
+ return Boolean(address && typeof address !== "string" && address.address === BROKER_HOST);
486
+ }
487
+
488
+ // src/broker-credentials.ts
489
+ import * as fs from "node:fs";
490
+ var BROKER_CREDENTIAL_FD = 3;
491
+ var BROKER_CREDENTIAL_FD_ENV = "PI_SUBAGENT_BROKER_FD";
492
+ var MAX_CREDENTIAL_BYTES = 1024;
493
+ function brokerCredentialEnvironment() {
494
+ return { [BROKER_CREDENTIAL_FD_ENV]: String(BROKER_CREDENTIAL_FD) };
495
+ }
496
+ function serializeBrokerCredentials(credentials) {
497
+ return JSON.stringify(credentials);
498
+ }
499
+ function captureBrokerCredentials(readCredentials = readCredentialPipe) {
500
+ const descriptor = process.env[BROKER_CREDENTIAL_FD_ENV];
501
+ delete process.env[BROKER_CREDENTIAL_FD_ENV];
502
+ if (descriptor === void 0) return void 0;
503
+ if (descriptor !== String(BROKER_CREDENTIAL_FD)) {
504
+ throw new Error("Invalid pi-subagents broker credential descriptor.");
505
+ }
506
+ let serialized;
507
+ try {
508
+ serialized = readCredentials();
509
+ } catch {
510
+ throw new Error("Unable to read pi-subagents broker credentials.");
511
+ }
512
+ if (Buffer.byteLength(serialized, "utf8") > MAX_CREDENTIAL_BYTES) {
513
+ throw new Error("Invalid pi-subagents broker credentials.");
514
+ }
515
+ let value;
516
+ try {
517
+ value = JSON.parse(serialized);
518
+ } catch {
519
+ throw new Error("Invalid pi-subagents broker credentials.");
520
+ }
521
+ if (!isBrokerCredentials(value)) {
522
+ throw new Error("Invalid pi-subagents broker credentials.");
523
+ }
524
+ return value;
525
+ }
526
+ function readCredentialPipe() {
527
+ try {
528
+ return fs.readFileSync(BROKER_CREDENTIAL_FD, "utf8");
529
+ } finally {
530
+ try {
531
+ fs.closeSync(BROKER_CREDENTIAL_FD);
532
+ } catch {
533
+ }
534
+ }
535
+ }
536
+ function isBrokerCredentials(value) {
537
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
538
+ const candidate = value;
539
+ return Object.keys(candidate).length === 3 && candidate.host === "127.0.0.1" && Number.isSafeInteger(candidate.port) && candidate.port >= 1 && candidate.port <= 65535 && typeof candidate.token === "string" && /^[a-f0-9]{64}$/u.test(candidate.token);
540
+ }
541
+
542
+ // src/child-communication-tools.ts
543
+ import { Type } from "typebox";
544
+ var CHILD_COMMUNICATION_TOOL_NAMES = ["subagent_send", "subagent_wait"];
545
+ var MAX_TIMEOUT_MS2 = 2147483647;
546
+ var MAX_TIMEOUT_SECONDS = MAX_TIMEOUT_MS2 / 1e3;
547
+ var SendParameters = Type.Object(
548
+ {
549
+ requestId: Type.Optional(
550
+ Type.String({
551
+ description: "Pending main-agent request to answer. Omit when starting a new request.",
552
+ minLength: 1,
553
+ maxLength: MAX_IDENTIFIER_LENGTH
554
+ })
555
+ ),
556
+ message: Type.String({
557
+ description: "Plain-text request or response. Maximum 48 KiB of UTF-8 text and 1,992 lines.",
558
+ minLength: 1,
559
+ maxLength: MAX_MESSAGE_BYTES
560
+ })
561
+ },
562
+ { additionalProperties: false }
563
+ );
564
+ var WaitParameters = Type.Object(
565
+ {
566
+ requestId: Type.String({
567
+ description: "Request ID returned by subagent_send.",
568
+ minLength: 1,
569
+ maxLength: MAX_IDENTIFIER_LENGTH
570
+ }),
571
+ timeout: Type.Optional(
572
+ Type.Number({ description: "Timeout in seconds (optional, no default timeout)" })
573
+ )
574
+ },
575
+ { additionalProperties: false }
576
+ );
577
+ function createChildCommunicationExtension(client) {
578
+ return (pi) => {
579
+ pi.registerTool({
580
+ name: "subagent_send",
581
+ label: "Subagent \xB7 Send to Main",
582
+ description: "Use subagent_send to send one request to the main agent or answer one pending main-agent request. Omit requestId to start a request. Provide requestId to answer that request.",
583
+ promptSnippet: "Use subagent_send to send or answer one main-agent message",
584
+ parameters: SendParameters,
585
+ async execute(_toolCallId, params, signal) {
586
+ validateMessage(params.message, "Subagent message");
587
+ const requestId = optionalIdentifier(params.requestId, "requestId");
588
+ const acknowledgement = await client.send(
589
+ requestId === void 0 ? { recipient: "main", message: params.message } : { requestId, message: params.message },
590
+ signal
591
+ );
592
+ return {
593
+ content: [{ type: "text", text: JSON.stringify(acknowledgement) }],
594
+ details: acknowledgement
595
+ };
596
+ }
597
+ });
598
+ pi.registerTool({
599
+ name: "subagent_wait",
600
+ label: "Subagent \xB7 Wait for Main Agent",
601
+ description: "Use subagent_wait with a request ID from subagent_send to wait for the main agent's plain-text response. A timeout, caller cancellation, or incoming main-agent request stops only this wait and does not cancel the original request. Retry the wait when its response is still needed.",
602
+ promptSnippet: "Use subagent_wait to receive a requested main-agent response",
603
+ parameters: WaitParameters,
604
+ prepareArguments: prepareWaitArguments,
605
+ async execute(_toolCallId, params, signal) {
606
+ const requestId = requiredIdentifier(params.requestId, "requestId");
607
+ const response = await client.wait(requestId, resolveTimeoutMs(params.timeout), signal);
608
+ return {
609
+ content: [{ type: "text", text: sanitizeTerminalText(response) }],
610
+ details: { requestId }
611
+ };
612
+ }
613
+ });
614
+ };
615
+ }
616
+ function resolveTimeoutMs(timeout) {
617
+ if (timeout === void 0) return void 0;
618
+ if (!Number.isFinite(timeout) || timeout <= 0) {
619
+ throw new Error("Invalid timeout: must be a finite number of seconds");
620
+ }
621
+ const timeoutMs = timeout * 1e3;
622
+ if (timeoutMs > MAX_TIMEOUT_MS2) {
623
+ throw new Error(`Invalid timeout: maximum is ${MAX_TIMEOUT_SECONDS} seconds`);
624
+ }
625
+ return timeoutMs;
626
+ }
627
+ function prepareWaitArguments(args) {
628
+ if (!args || typeof args !== "object") return args;
629
+ if (!Object.hasOwn(args, "timeoutMs")) return args;
630
+ const record = args;
631
+ if (typeof record.timeoutMs !== "number") return record;
632
+ const { timeoutMs, ...prepared } = record;
633
+ if (prepared.timeout === void 0) {
634
+ return { ...prepared, timeout: timeoutMs / 1e3 };
635
+ }
636
+ return prepared;
637
+ }
638
+ function optionalIdentifier(value, field) {
639
+ return value === void 0 ? void 0 : requiredIdentifier(value, field);
640
+ }
641
+ function requiredIdentifier(value, field) {
642
+ if (typeof value !== "string" || !value.trim()) throw new Error(`Subagent ${field} is required.`);
643
+ const identifier = value.trim();
644
+ if (identifier.length > MAX_IDENTIFIER_LENGTH || [...identifier].some((character) => {
645
+ const codePoint = character.codePointAt(0) ?? 0;
646
+ return codePoint <= 31 || codePoint >= 127 && codePoint <= 159;
647
+ })) {
648
+ throw new Error(`Subagent ${field} is invalid.`);
649
+ }
650
+ return identifier;
651
+ }
652
+
653
+ export {
654
+ MAX_MESSAGE_BYTES,
655
+ MAX_FRAME_BYTES,
656
+ MAX_IDENTIFIER_LENGTH,
657
+ MessageBroker,
658
+ validateMessage,
659
+ sanitizeTerminalText,
660
+ BROKER_CREDENTIAL_FD,
661
+ brokerCredentialEnvironment,
662
+ serializeBrokerCredentials,
663
+ captureBrokerCredentials,
664
+ CHILD_COMMUNICATION_TOOL_NAMES,
665
+ createChildCommunicationExtension
666
+ };
667
+ //# sourceMappingURL=chunk-UKTWUQRM.js.map