@narumitw/pi-subagents 3.0.1 → 3.0.2
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.
- package/README.md +35 -100
- package/dist/child-communication-bridge.ts +3 -8
- package/dist/child-communication-bridge.ts.map +2 -2
- package/dist/chunks/{chunk-UKTWUQRM.js → chunk-7JQOB375.ts} +7 -22
- package/dist/chunks/chunk-7JQOB375.ts.map +7 -0
- package/dist/index.ts +13 -46
- package/dist/index.ts.map +2 -2
- package/package.json +53 -54
- package/src/broker-credentials.ts +48 -48
- package/src/child-communication-bridge.ts +115 -123
- package/src/child-communication-tools.ts +105 -111
- package/src/completion-renderer.ts +46 -48
- package/src/message-broker.ts +531 -561
- package/src/model-output.ts +25 -28
- package/src/process.ts +595 -616
- package/src/runtime.ts +454 -478
- package/src/subagents.ts +20 -23
- package/src/tools.ts +305 -319
- package/src/types.ts +41 -58
- package/src/widget.ts +85 -91
- package/dist/chunks/chunk-UKTWUQRM.js.map +0 -7
package/README.md
CHANGED
|
@@ -20,7 +20,6 @@ Pi Subagents runs Pi jobs in separate child processes and supports authenticated
|
|
|
20
20
|
## 📦 Install
|
|
21
21
|
|
|
22
22
|
The version 3 runtime documented here is not yet published to npm.
|
|
23
|
-
|
|
24
23
|
The npm package still contains the legacy 2.x runtime and does not provide the tools below.
|
|
25
24
|
|
|
26
25
|
Install the repository source as one Pi package:
|
|
@@ -49,39 +48,27 @@ pi --no-extensions -e ./packages/pi-subagents
|
|
|
49
48
|
```
|
|
50
49
|
|
|
51
50
|
The package entry is generated at `dist/index.ts` and loaded through Pi's Jiti runtime.
|
|
52
|
-
|
|
53
51
|
An unbuilt local package directory cannot load its declared extension entry.
|
|
54
52
|
|
|
55
53
|
Pi extensions and children with `bash`, `powershell`, `edit`, or `write` execute with your user permissions.
|
|
56
|
-
|
|
57
54
|
Review the source before installing or invoking the extension.
|
|
58
55
|
|
|
59
56
|
## 🚀 Quick start
|
|
60
57
|
|
|
61
58
|
Call `subagent_spawn` with a self-contained task and only the work tools that task needs.
|
|
62
59
|
|
|
63
|
-
The package intentionally does not register or publish a skill.
|
|
64
|
-
|
|
65
|
-
Create a project skill under `.pi/skills/<your-skill>/SKILL.md` or a global skill under `~/.pi/agent/skills/<your-skill>/SKILL.md` when you want reusable delegation policy.
|
|
66
|
-
|
|
67
|
-
Choose a name, trigger description, tool policy, task format, and verification workflow for your own use case.
|
|
68
|
-
|
|
69
|
-
The repository-only [`using-pi-subagents` example](https://github.com/narumiruna/pi-extensions/tree/main/packages/pi-subagents/skills/using-pi-subagents) demonstrates one possible design without imposing it on installed users.
|
|
70
|
-
|
|
71
60
|
The call returns a `jobId` immediately, and the job continues in the background.
|
|
72
|
-
|
|
73
61
|
Continue useful main-agent work until the result is required or a completion arrives.
|
|
74
62
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
If `subagent_wait` returns `reason: "subagent_message"`, handle the visible request or response and wait for the job again only when needed.
|
|
63
|
+
Use messaging only when needed:
|
|
78
64
|
|
|
79
|
-
|
|
65
|
+
- Call `subagent_send` with `recipient: jobId` to ask an active child a question.
|
|
66
|
+
- If `subagent_wait` returns `reason: "subagent_message"`, handle the visible request or response and wait for the job again only when needed.
|
|
67
|
+
- Answer a child-originated request by calling `subagent_send` with its `requestId`.
|
|
80
68
|
|
|
81
69
|
Completion messages follow Pi's global tool-output expansion state and the `app.tools.expand` binding (`Ctrl+O` by default).
|
|
82
70
|
|
|
83
71
|
In TUI mode, the above-editor widget shows each queued or running job's ID, state, elapsed time, timeout, and selected work tools.
|
|
84
|
-
|
|
85
72
|
The widget omits the fixed communication tools, disappears when no jobs remain active, and clears when the session ends.
|
|
86
73
|
|
|
87
74
|
## 🛠️ Tools
|
|
@@ -103,34 +90,23 @@ Every child exposes these communication tools in addition to its selected work t
|
|
|
103
90
|
| `subagent_send` | optional `requestId`, plus `message` | Omit `requestId` to send a new request to main, or provide it to answer one pending main-agent request. |
|
|
104
91
|
| `subagent_wait` | `requestId`, optional `timeout` | Wait for the main agent's plain-text response to a child-originated request. |
|
|
105
92
|
|
|
106
|
-
Main and child processes receive separate provider-visible `subagent_send` definitions for their own context
|
|
107
|
-
|
|
108
|
-
The main agent starts a request with an active job ID as `recipient` and omits `requestId`.
|
|
109
|
-
|
|
110
|
-
The main agent answers a child request with `requestId` and omits `recipient`.
|
|
111
|
-
|
|
112
|
-
A child starts a request to main by omitting `requestId`.
|
|
93
|
+
Main and child processes receive separate provider-visible `subagent_send` definitions for their own context:
|
|
113
94
|
|
|
114
|
-
|
|
95
|
+
- The main agent starts a request with an active job ID as `recipient` and omits `requestId`.
|
|
96
|
+
- The main agent answers a child request with `requestId` and omits `recipient`.
|
|
97
|
+
- A child starts a request to main by omitting `requestId`.
|
|
98
|
+
- A child answers a main-agent request by providing `requestId`.
|
|
115
99
|
|
|
116
100
|
Execution and wait timeouts use seconds, accept finite numbers greater than zero through 2,147,483.647, and have no default.
|
|
117
|
-
|
|
118
101
|
Omitting a job execution timeout lets the child run until it exits, is cancelled, the session shuts down, or the Pi process exits.
|
|
119
|
-
|
|
120
102
|
A wait timeout or caller cancellation stops only that wait and does not cancel its job or message request.
|
|
121
|
-
|
|
122
103
|
An incoming main-agent request interrupts an active child `subagent_wait` after RPC steering is queued so the child can receive the new request.
|
|
123
|
-
|
|
124
104
|
The interrupted child-originated request remains active and may be waited on again.
|
|
125
105
|
|
|
126
106
|
Tasks are limited to 50 KiB of UTF-8 text.
|
|
127
|
-
|
|
128
107
|
Requests and responses are limited to 48 KiB and 1,992 lines so their protocol envelopes fit Pi's 50 KiB and 2,000-line model-text bounds without truncating accepted content.
|
|
129
|
-
|
|
130
108
|
Each job may have up to four unresolved or answered-but-not-consumed requests across both directions.
|
|
131
|
-
|
|
132
109
|
The terminal states are `completed`, `partial`, `failed`, `timed_out`, and `cancelled`.
|
|
133
|
-
|
|
134
110
|
`subagent_inspect` never returns complete task text, child output, prompts, selected tools, context, credentials, environment variables, requests, responses, or secrets.
|
|
135
111
|
|
|
136
112
|
See [`docs/tools.md`](./docs/tools.md) for the concise schema reference.
|
|
@@ -138,85 +114,60 @@ See [`docs/tools.md`](./docs/tools.md) for the concise schema reference.
|
|
|
138
114
|
## ⚙️ Job configuration
|
|
139
115
|
|
|
140
116
|
The task should state the child's role, objective, scope, constraints, and expected result.
|
|
117
|
+
For reusable delegation policy, you can create your own project skill under `.pi/skills/<your-skill>/SKILL.md` or global skill under `~/.pi/agent/skills/<your-skill>/SKILL.md`.
|
|
118
|
+
Choose its name, trigger, tool policy, task format, and verification workflow for your use case.
|
|
119
|
+
The package intentionally registers and publishes no skill; the repository-only [`using-pi-subagents` example](https://github.com/narumiruna/pi-extensions/tree/main/packages/pi-subagents/skills/using-pi-subagents) is an optional starting point.
|
|
141
120
|
|
|
142
|
-
The optional `tools` list limits what the child can do
|
|
143
|
-
|
|
144
|
-
Accepted names are `read`, `bash`, `powershell`, `edit`, `write`, `grep`, `find`, and `ls`.
|
|
121
|
+
The optional `tools` list limits what the child can do:
|
|
145
122
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
Omitting `tools` selects `read`, `grep`, `find`, and `ls`.
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
The runtime always adds `subagent_send` and child `subagent_wait` and removes duplicate names.
|
|
123
|
+
- Accepted names are `read`, `bash`, `powershell`, `edit`, `write`, `grep`, `find`, and `ls`.
|
|
124
|
+
- Unavailable or extension-only tool names are rejected before a job is queued.
|
|
125
|
+
- Omitting `tools` selects `read`, `grep`, `find`, and `ls`.
|
|
126
|
+
- Passing an empty list gives the child no work tools.
|
|
127
|
+
- The runtime always adds `subagent_send` and child `subagent_wait` and removes duplicate names.
|
|
153
128
|
|
|
154
129
|
Adding `edit` or `write` lets the child modify files.
|
|
155
|
-
|
|
156
130
|
Adding `bash` or `powershell` grants unrestricted command execution and can also modify the workspace.
|
|
157
131
|
|
|
158
132
|
The optional `thinkingLevel` accepts `off`, `minimal`, `low`, `medium`, `high`, `xhigh`, or `max`.
|
|
159
|
-
|
|
160
133
|
Omitting `thinkingLevel` captures the main agent's effective level when `subagent_spawn` executes.
|
|
161
|
-
|
|
162
134
|
The child inherits the main agent's effective provider and model when `subagent_spawn` executes.
|
|
163
135
|
|
|
164
136
|
Spawn rejects providers registered by a parent extension because child processes disable unrelated extensions.
|
|
165
|
-
|
|
166
137
|
Spawn also rejects process-local runtime API keys, including a parent-only `--api-key` value.
|
|
167
|
-
|
|
168
138
|
Use stored or environment credentials that child processes can read.
|
|
169
|
-
|
|
170
139
|
The extension does not expose a per-job model override.
|
|
171
140
|
|
|
172
141
|
## 🔄 Messaging, lifecycle, and retention
|
|
173
142
|
|
|
174
143
|
The session starts one TCP broker on `127.0.0.1` with an operating-system-assigned ephemeral port.
|
|
175
|
-
|
|
176
144
|
Each job receives one cryptographically random token bound to its job identity and session generation.
|
|
177
|
-
|
|
178
145
|
The parent passes the broker credentials once through a private inherited pipe instead of placing them in the child's initial environment or command line.
|
|
179
|
-
|
|
180
146
|
The child bridge reads and closes that descriptor before model tool execution.
|
|
181
147
|
|
|
182
148
|
Each child runs in Pi RPC mode so the parent can inject a main-originated request through `steer` after the initial prompt is accepted.
|
|
183
|
-
|
|
184
149
|
Each child broker call uses one request-scoped connection, while a response wait uses an abortable long poll.
|
|
185
|
-
|
|
186
150
|
A main-originated request to a queued job waits for RPC readiness before delivery is accepted.
|
|
187
|
-
|
|
188
151
|
After RPC accepts the steering message, the runtime interrupts active child response waits so the queued request can reach the child model.
|
|
189
|
-
|
|
190
152
|
Caller cancellation before RPC delivery starts rolls the request back.
|
|
191
|
-
|
|
192
153
|
Once RPC delivery starts, cancellation stops only the caller's wait; the request may still arrive and remains answerable until delivery fails or the job terminates.
|
|
193
|
-
|
|
194
154
|
The interrupted child-originated requests remain active and retryable.
|
|
195
155
|
|
|
196
156
|
The first accepted `subagent_send` response wins.
|
|
197
|
-
|
|
198
157
|
Repeated responses acknowledge the existing answer without replacing it.
|
|
199
|
-
|
|
200
158
|
A child may retry `subagent_wait` after a wait timeout because the underlying request remains active.
|
|
201
159
|
|
|
202
160
|
A new job starts as `queued`, transitions to `running`, and reaches exactly one terminal state.
|
|
203
|
-
|
|
204
161
|
The runtime retains up to 32 recent terminal records for up to 24 hours within the current extension session.
|
|
205
|
-
|
|
206
162
|
Inspection reports older records removed by retention bounds through `omitted.jobs`.
|
|
207
|
-
|
|
208
163
|
Cancelling or terminalizing a job revokes its token and rejects pending child waits before stale output can replace the terminal state.
|
|
209
|
-
|
|
210
164
|
Session replacement and shutdown cancel active work, suppress stale completion delivery, revoke credentials, close sockets, and stop the broker.
|
|
211
165
|
|
|
212
166
|
## 🔀 Migrating from 2.x
|
|
213
167
|
|
|
214
168
|
Version 3.0 replaces the previous orchestration runtime.
|
|
215
|
-
|
|
216
169
|
It does not migrate legacy settings, persisted jobs, retained conversations, or recovery state.
|
|
217
|
-
|
|
218
170
|
Finish or record any required work before upgrading, then start a fresh Pi session so stored calls do not request removed tool names.
|
|
219
|
-
|
|
220
171
|
Use these replacements where the new job model supports the previous intent:
|
|
221
172
|
|
|
222
173
|
| Previous interface | Version 3 interface |
|
|
@@ -229,73 +180,57 @@ Use these replacements where the new job model supports the previous intent:
|
|
|
229
180
|
| Running main-to-child questions | Main and child `subagent_send` |
|
|
230
181
|
|
|
231
182
|
The version 3 `subagent_send` contracts are not compatible with the legacy retained-agent follow-up tool of the same name.
|
|
232
|
-
|
|
233
183
|
The `/subagents` command, extension settings, legacy retained follow-ups, `subagent_mailbox`, `subagent_consult`, custom agent catalogs, advanced orchestration, alternate transports, trust-aware cwd policy, and extension-owned worktrees have no direct replacement.
|
|
234
|
-
|
|
235
184
|
Describe the child's specialization in `task` and grant only the required work tools through `tools`.
|
|
236
185
|
|
|
237
186
|
## 🔒 Security and privacy
|
|
238
187
|
|
|
239
188
|
The selected work tools run in the current working directory.
|
|
240
|
-
|
|
241
189
|
The default list contains no shell or file-mutation tool.
|
|
242
|
-
|
|
243
190
|
It is not a filesystem sandbox because its read tools can inspect files available to the user account.
|
|
244
|
-
|
|
245
191
|
Selecting `bash`, `powershell`, `edit`, or `write` permits workspace mutation with the Pi process environment and user permissions.
|
|
246
192
|
|
|
247
193
|
Every child disables session persistence, unrelated extensions, skills, and prompt templates.
|
|
248
|
-
|
|
249
194
|
Provider selection therefore supports Pi's child-visible built-in and configured providers, not providers registered only by a parent extension.
|
|
250
|
-
|
|
251
195
|
Credentials must be available independently to the child through Pi's stored credentials or its inherited environment.
|
|
252
196
|
|
|
253
197
|
The broker accepts only loopback TCP connections with an active per-job token.
|
|
254
|
-
|
|
255
198
|
The token is bootstrapped through a private inherited pipe and is absent from the child's initial environment and command line.
|
|
256
199
|
|
|
257
200
|
A child request or response is visible main-agent model context, but its envelope explicitly identifies it as untrusted subagent content rather than user authorization.
|
|
258
|
-
|
|
259
201
|
A child message cannot grant permission for writes, shell commands, credential access, or other privileged actions.
|
|
260
|
-
|
|
261
202
|
A main-agent request is visible child model context, but it cannot expand the child's selected tools or grant capabilities the child did not receive at spawn time.
|
|
262
203
|
|
|
263
204
|
Terminal controls and bidirectional controls are stripped before untrusted child text is displayed.
|
|
264
|
-
|
|
265
205
|
Tasks, repository context, requests, responses, and inspected file content may be sent to the selected model provider.
|
|
266
|
-
|
|
267
206
|
Parallel writers require disjoint ownership or workspace isolation outside this extension.
|
|
268
207
|
|
|
269
208
|
## 🚧 Limitations
|
|
270
209
|
|
|
271
|
-
The extension does not load arbitrary extension tools or parent-registered model providers in child processes.
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
The main agent must verify child claims against the actual diff and deterministic checks.
|
|
280
|
-
|
|
281
|
-
Child requests and responses trigger a main-agent turn, but asynchronous job completions do not wake an otherwise idle model turn automatically.
|
|
282
|
-
|
|
283
|
-
Jobs, broker requests, and retained results do not survive extension reload, session replacement, or process exit.
|
|
210
|
+
- The extension does not load arbitrary extension tools or parent-registered model providers in child processes.
|
|
211
|
+
- Process-local runtime API keys are not forwarded to children.
|
|
212
|
+
- The extension does not provide custom agents, per-job models, custom system prompts, peer-to-peer child messaging, retained conversations, user-directed follow-up work, mailboxes, Agent Teams, chains, fan-in aggregators, panels, workflow DAGs, dynamic scheduling, verification orchestration, nested subagents, or extension-owned semantic memory.
|
|
213
|
+
- Bidirectional messages use request-response coordination, not a retained conversational session.
|
|
214
|
+
- The main agent must verify child claims against the actual diff and deterministic checks.
|
|
215
|
+
- Child requests and responses trigger a main-agent turn, but asynchronous job completions do not wake an otherwise idle model turn automatically.
|
|
216
|
+
- Jobs, broker requests, and retained results do not survive extension reload, session replacement, or process exit.
|
|
284
217
|
|
|
285
218
|
## 🗂️ Package layout
|
|
286
219
|
|
|
287
220
|
```text
|
|
288
221
|
packages/pi-subagents/
|
|
289
|
-
├──
|
|
290
|
-
├──
|
|
291
|
-
|
|
292
|
-
├──
|
|
293
|
-
├──
|
|
294
|
-
├──
|
|
295
|
-
├──
|
|
296
|
-
└──
|
|
222
|
+
├── src/ # Authoritative implementation and helpers
|
|
223
|
+
│ ├── index.ts # Thin Pi entrypoint
|
|
224
|
+
│ └── subagents.ts # Job, broker, and child lifecycle
|
|
225
|
+
├── dist/ # Generated Jiti runtime and child bridge
|
|
226
|
+
├── scripts/build-runtime.mjs # Runtime builder
|
|
227
|
+
├── docs/ # Published reference documentation
|
|
228
|
+
├── skills/using-pi-subagents/ # Repository-only example; not published
|
|
229
|
+
└── test/ # Behavior and lifecycle coverage
|
|
297
230
|
```
|
|
298
231
|
|
|
232
|
+
The generated runtime is built from `src/index.ts` and does not import back into `src`.
|
|
233
|
+
|
|
299
234
|
## 🔎 Keywords
|
|
300
235
|
|
|
301
236
|
Pi, subagents, delegation, subagent jobs, least privilege, main-agent messaging, cancellation, job lifecycle.
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
MAX_IDENTIFIER_LENGTH,
|
|
6
6
|
captureBrokerCredentials,
|
|
7
7
|
createChildCommunicationExtension
|
|
8
|
-
} from "./chunks/chunk-
|
|
8
|
+
} from "./chunks/chunk-7JQOB375.ts";
|
|
9
9
|
|
|
10
10
|
// src/child-communication-bridge.ts
|
|
11
11
|
import net from "node:net";
|
|
@@ -79,10 +79,7 @@ function requestBroker(credentials, request, signal, responseTimeoutMs) {
|
|
|
79
79
|
socket.once("connect", () => {
|
|
80
80
|
clearTimeout(connectTimer);
|
|
81
81
|
if (responseTimeoutMs !== void 0) {
|
|
82
|
-
responseTimer = setTimeout(
|
|
83
|
-
() => finish(new Error("Subagent broker response timed out.")),
|
|
84
|
-
responseTimeoutMs
|
|
85
|
-
);
|
|
82
|
+
responseTimer = setTimeout(() => finish(new Error("Subagent broker response timed out.")), responseTimeoutMs);
|
|
86
83
|
responseTimer.unref();
|
|
87
84
|
}
|
|
88
85
|
socket.write(`${JSON.stringify(request)}
|
|
@@ -117,9 +114,7 @@ function requestBroker(credentials, request, signal, responseTimeoutMs) {
|
|
|
117
114
|
});
|
|
118
115
|
}
|
|
119
116
|
function brokerError(response) {
|
|
120
|
-
return new Error(
|
|
121
|
-
typeof response.error === "string" ? response.error : "Subagent broker rejected the request."
|
|
122
|
-
);
|
|
117
|
+
return new Error(typeof response.error === "string" ? response.error : "Subagent broker rejected the request.");
|
|
123
118
|
}
|
|
124
119
|
function abortError(message) {
|
|
125
120
|
const error = new Error(message);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/child-communication-bridge.ts"],
|
|
4
|
-
"sourcesContent": ["import net from \"node:net\";\nimport type { ExtensionFactory } from \"@earendil-works/pi-coding-agent\";\nimport { captureBrokerCredentials } from \"./broker-credentials.js\";\nimport {
|
|
5
|
-
"mappings": ";;;;;;;;;;AAAA,OAAO,SAAS;
|
|
4
|
+
"sourcesContent": ["import net from \"node:net\";\nimport type { ExtensionFactory } from \"@earendil-works/pi-coding-agent\";\nimport { captureBrokerCredentials } from \"./broker-credentials.js\";\nimport { type ChildCommunicationClient, createChildCommunicationExtension } from \"./child-communication-tools.js\";\nimport { MAX_FRAME_BYTES, MAX_IDENTIFIER_LENGTH } from \"./message-broker.js\";\nimport type { BrokerCredentials } from \"./types.js\";\n\nconst CONNECT_TIMEOUT_MS = 2_000;\nconst SEND_RESPONSE_TIMEOUT_MS = 5_000;\n\nconst captured = captureBrokerCredentials();\n\nconst childCommunicationBridge: ExtensionFactory = captured\n ? createChildCommunicationExtension(createBrokerClient(captured))\n : () => undefined;\n\nexport default childCommunicationBridge;\n\nexport function createBrokerClient(credentials: BrokerCredentials): ChildCommunicationClient {\n return {\n async send(params, signal) {\n const response = await requestBroker(\n credentials,\n { type: \"send\", token: credentials.token, ...params },\n signal,\n SEND_RESPONSE_TIMEOUT_MS,\n );\n if (response.ok !== true) throw brokerError(response);\n if (\n typeof response.requestId !== \"string\" ||\n !response.requestId ||\n response.requestId.length > MAX_IDENTIFIER_LENGTH ||\n typeof response.accepted !== \"boolean\" ||\n typeof response.duplicate !== \"boolean\"\n ) {\n throw new Error(\"Subagent broker returned an invalid send acknowledgement.\");\n }\n return {\n requestId: response.requestId,\n accepted: response.accepted,\n duplicate: response.duplicate,\n };\n },\n async wait(requestId, timeoutMs, signal) {\n const response = await requestBroker(\n credentials,\n {\n type: \"wait\",\n token: credentials.token,\n requestId,\n ...(timeoutMs !== undefined ? { timeoutMs } : {}),\n },\n signal,\n );\n if (response.ok !== true) throw brokerError(response);\n if (typeof response.response !== \"string\") {\n throw new Error(\"Subagent broker returned an invalid plain-text response.\");\n }\n return response.response;\n },\n };\n}\n\nfunction requestBroker(\n credentials: BrokerCredentials,\n request: Record<string, unknown>,\n signal?: AbortSignal,\n responseTimeoutMs?: number,\n): Promise<Record<string, unknown>> {\n if (signal?.aborted) return Promise.reject(abortError(\"Subagent broker request was cancelled.\"));\n return new Promise((resolve, reject) => {\n const socket = net.createConnection({ host: credentials.host, port: credentials.port });\n let response = Buffer.alloc(0);\n let settled = false;\n let responseTimer: NodeJS.Timeout | undefined;\n const connectTimer = setTimeout(\n () => finish(new Error(\"Subagent broker connection timed out.\")),\n CONNECT_TIMEOUT_MS,\n );\n connectTimer.unref();\n const onAbort = () => finish(abortError(\"Subagent broker request was cancelled.\"));\n const finish = (error?: Error, value?: Record<string, unknown>) => {\n if (settled) return;\n settled = true;\n clearTimeout(connectTimer);\n if (responseTimer) clearTimeout(responseTimer);\n signal?.removeEventListener(\"abort\", onAbort);\n socket.destroy();\n if (error) reject(error);\n else resolve(value ?? {});\n };\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n socket.once(\"connect\", () => {\n clearTimeout(connectTimer);\n if (responseTimeoutMs !== undefined) {\n responseTimer = setTimeout(() => finish(new Error(\"Subagent broker response timed out.\")), responseTimeoutMs);\n responseTimer.unref();\n }\n socket.write(`${JSON.stringify(request)}\\n`);\n });\n socket.on(\"data\", (chunk: Buffer) => {\n if (settled) return;\n response = Buffer.concat([response, chunk]);\n if (response.byteLength > MAX_FRAME_BYTES) {\n finish(new Error(\"Subagent broker response exceeded its size limit.\"));\n return;\n }\n const newline = response.indexOf(0x0a);\n if (newline < 0) return;\n const trailing = response\n .subarray(newline + 1)\n .toString(\"utf8\")\n .trim();\n if (trailing) {\n finish(new Error(\"Subagent broker returned more than one response frame.\"));\n return;\n }\n try {\n const parsed = JSON.parse(response.subarray(0, newline).toString(\"utf8\")) as unknown;\n if (!isRecord(parsed)) throw new Error();\n finish(undefined, parsed);\n } catch {\n finish(new Error(\"Subagent broker returned malformed JSON.\"));\n }\n });\n socket.once(\"error\", (error) => finish(error));\n socket.once(\"close\", () => {\n if (!settled) finish(new Error(\"Subagent broker closed without a response.\"));\n });\n });\n}\n\nfunction brokerError(response: Record<string, unknown>): Error {\n return new Error(typeof response.error === \"string\" ? response.error : \"Subagent broker rejected the request.\");\n}\n\nfunction abortError(message: string): Error {\n const error = new Error(message);\n error.name = \"AbortError\";\n return error;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -129,9 +129,7 @@ var MessageBroker = class {
|
|
|
129
129
|
}
|
|
130
130
|
}
|
|
131
131
|
hasPendingMainRequest() {
|
|
132
|
-
return [...this.requests.values()].some(
|
|
133
|
-
(request) => request.origin === "child" && request.response === void 0
|
|
134
|
-
);
|
|
132
|
+
return [...this.requests.values()].some((request) => request.origin === "child" && request.response === void 0);
|
|
135
133
|
}
|
|
136
134
|
takePendingInboundResponse() {
|
|
137
135
|
const pending = this.pendingInboundResponse;
|
|
@@ -198,9 +196,7 @@ var MessageBroker = class {
|
|
|
198
196
|
(request2) => request2.jobId === job.jobId && request2.consumedAt === void 0
|
|
199
197
|
).length;
|
|
200
198
|
if (outstanding >= MAX_OUTSTANDING_REQUESTS) {
|
|
201
|
-
throw new Error(
|
|
202
|
-
`Subagent job may have at most ${MAX_OUTSTANDING_REQUESTS} outstanding requests.`
|
|
203
|
-
);
|
|
199
|
+
throw new Error(`Subagent job may have at most ${MAX_OUTSTANDING_REQUESTS} outstanding requests.`);
|
|
204
200
|
}
|
|
205
201
|
const request = {
|
|
206
202
|
requestId: `req_${randomUUID()}`,
|
|
@@ -374,11 +370,7 @@ var MessageBroker = class {
|
|
|
374
370
|
return;
|
|
375
371
|
}
|
|
376
372
|
if (record.response !== void 0) {
|
|
377
|
-
this.respond(
|
|
378
|
-
socket,
|
|
379
|
-
{ ok: true, response: record.response },
|
|
380
|
-
() => this.markConsumed(record)
|
|
381
|
-
);
|
|
373
|
+
this.respond(socket, { ok: true, response: record.response }, () => this.markConsumed(record));
|
|
382
374
|
return;
|
|
383
375
|
}
|
|
384
376
|
if (this.hasQueuedRequestForChild(job.jobId)) {
|
|
@@ -402,13 +394,8 @@ var MessageBroker = class {
|
|
|
402
394
|
markConsumed(request) {
|
|
403
395
|
if (this.requests.get(request.requestId) !== request || request.response === void 0) return;
|
|
404
396
|
request.consumedAt ??= this.now();
|
|
405
|
-
const consumed = [...this.requests.values()].filter(
|
|
406
|
-
|
|
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
|
-
)) {
|
|
397
|
+
const consumed = [...this.requests.values()].filter((candidate) => candidate.jobId === request.jobId && candidate.consumedAt !== void 0).sort((left, right) => (left.consumedAt ?? 0) - (right.consumedAt ?? 0));
|
|
398
|
+
for (const expired of consumed.slice(0, Math.max(0, consumed.length - MAX_RETAINED_CONSUMED_REQUESTS))) {
|
|
412
399
|
this.requests.delete(expired.requestId);
|
|
413
400
|
}
|
|
414
401
|
}
|
|
@@ -568,9 +555,7 @@ var WaitParameters = Type.Object(
|
|
|
568
555
|
minLength: 1,
|
|
569
556
|
maxLength: MAX_IDENTIFIER_LENGTH
|
|
570
557
|
}),
|
|
571
|
-
timeout: Type.Optional(
|
|
572
|
-
Type.Number({ description: "Timeout in seconds (optional, no default timeout)" })
|
|
573
|
-
)
|
|
558
|
+
timeout: Type.Optional(Type.Number({ description: "Timeout in seconds (optional, no default timeout)" }))
|
|
574
559
|
},
|
|
575
560
|
{ additionalProperties: false }
|
|
576
561
|
);
|
|
@@ -664,4 +649,4 @@ export {
|
|
|
664
649
|
CHILD_COMMUNICATION_TOOL_NAMES,
|
|
665
650
|
createChildCommunicationExtension
|
|
666
651
|
};
|
|
667
|
-
//# sourceMappingURL=chunk-
|
|
652
|
+
//# sourceMappingURL=chunk-7JQOB375.ts.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/message-broker.ts", "../../src/broker-credentials.ts", "../../src/child-communication-tools.ts"],
|
|
4
|
+
"sourcesContent": ["import { randomBytes, randomUUID } from \"node:crypto\";\nimport net, { type AddressInfo, type Server, type Socket } from \"node:net\";\nimport type { BrokerCredentials } from \"./types.js\";\n\nexport const BROKER_HOST = \"127.0.0.1\" as const;\nexport const MAX_MESSAGE_BYTES = 48 * 1024;\nexport const MAX_MESSAGE_LINES = 1_992;\nexport const MAX_FRAME_BYTES = 384 * 1024;\nexport const MAX_ERROR_BYTES = 8 * 1024;\nexport const MAX_OUTSTANDING_REQUESTS = 4;\nexport const MAX_IDENTIFIER_LENGTH = 128;\n\nconst MAX_CONNECTIONS = 32;\nconst REQUEST_FRAME_TIMEOUT_MS = 2_000;\nconst MAX_TIMEOUT_MS = 2_147_483_647;\nconst MAX_RETAINED_CONSUMED_REQUESTS = 4;\nconst CHILD_WAIT_INTERRUPTED_ERROR =\n \"Subagent wait was interrupted by an incoming main-agent request. The original request remains active.\";\n\nexport type BrokerRequestOrigin = \"main\" | \"child\";\n\nexport interface BrokerInboundMessage {\n kind: \"request\" | \"response\";\n requestId: string;\n jobId: string;\n message: string;\n}\n\nexport interface BrokerSendAcknowledgement {\n requestId: string;\n accepted: boolean;\n duplicate: boolean;\n}\n\nexport interface MessageBrokerOptions {\n onMessage(message: BrokerInboundMessage): void;\n createServer?: (listener: (socket: Socket) => void) => Server;\n now?: () => number;\n requestFrameTimeoutMs?: number;\n}\n\ninterface JobRecord {\n jobId: string;\n generation: number;\n token: string;\n}\n\ninterface RequestWaiter {\n socket: Socket;\n timer?: NodeJS.Timeout;\n}\n\ninterface RequestRecord {\n requestId: string;\n jobId: string;\n generation: number;\n origin: BrokerRequestOrigin;\n expectedResponder: BrokerRequestOrigin;\n message: string;\n createdAt: number;\n response?: string;\n consumedAt?: number;\n deliveryQueued?: boolean;\n waiter?: RequestWaiter;\n}\n\ntype BrokerRequest =\n | {\n type: \"send\";\n token: string;\n recipient?: string;\n requestId?: string;\n message: string;\n }\n | { type: \"wait\"; token: string; requestId: string; timeoutMs?: number };\n\n/** Session-scoped authenticated loopback transport for bidirectional requests and responses. */\nexport class MessageBroker {\n private server?: Server;\n private starting?: Promise<void>;\n private address?: { host: typeof BROKER_HOST; port: number };\n private failure?: string;\n private generation = 0;\n private readonly sockets = new Set<Socket>();\n private readonly jobsByToken = new Map<string, JobRecord>();\n private readonly tokenByJob = new Map<string, string>();\n private readonly requests = new Map<string, RequestRecord>();\n private readonly inboundMessageListeners = new Set<() => void>();\n private pendingInboundResponse = false;\n private readonly createServer: (listener: (socket: Socket) => void) => Server;\n private readonly now: () => number;\n private readonly requestFrameTimeoutMs: number;\n\n constructor(private readonly options: MessageBrokerOptions) {\n this.createServer = options.createServer ?? ((listener) => net.createServer(listener));\n this.now = options.now ?? Date.now;\n this.requestFrameTimeoutMs = options.requestFrameTimeoutMs ?? REQUEST_FRAME_TIMEOUT_MS;\n if (!Number.isFinite(this.requestFrameTimeoutMs) || this.requestFrameTimeoutMs <= 0) {\n throw new Error(\"Subagent broker frame timeout must be positive.\");\n }\n }\n\n async start(): Promise<void> {\n if (this.server && this.address && !this.failure) return;\n if (this.starting) return this.starting;\n const ownerGeneration = ++this.generation;\n this.failure = undefined;\n this.starting = new Promise<void>((resolve, reject) => {\n const server = this.createServer((socket) => this.accept(socket));\n server.maxConnections = MAX_CONNECTIONS;\n const onStartError = (error: Error) => {\n server.close(() => undefined);\n reject(error);\n };\n server.once(\"error\", onStartError);\n server.listen({ host: BROKER_HOST, port: 0 }, () => {\n server.off(\"error\", onStartError);\n if (ownerGeneration !== this.generation) {\n server.close(() => undefined);\n reject(new Error(\"Subagent message broker start was superseded.\"));\n return;\n }\n const address = server.address();\n if (!isLoopbackAddress(address)) {\n server.close(() => undefined);\n reject(new Error(\"Subagent message broker did not bind to loopback.\"));\n return;\n }\n this.server = server;\n this.address = { host: BROKER_HOST, port: address.port };\n server.on(\"error\", (error) => this.fail(error));\n server.unref();\n resolve();\n });\n })\n .catch((error) => {\n const message = truncateError(error instanceof Error ? error.message : String(error));\n this.failure = message;\n throw new Error(`Subagent message broker failed to start: ${message}`);\n })\n .finally(() => {\n this.starting = undefined;\n });\n return this.starting;\n }\n\n assertReady(): void {\n if (this.server && this.address && !this.failure) return;\n throw new Error(\n this.failure\n ? `Subagent messaging is unavailable: ${this.failure}`\n : \"Subagent messaging is unavailable because the session broker is not ready.\",\n );\n }\n\n issueCredentials(input: { jobId: string; generation: number }): BrokerCredentials {\n this.assertReady();\n if (this.tokenByJob.has(input.jobId)) {\n throw new Error(`Subagent messaging credentials already exist for ${input.jobId}.`);\n }\n const token = randomBytes(32).toString(\"hex\");\n const record: JobRecord = { ...input, token };\n this.jobsByToken.set(token, record);\n this.tokenByJob.set(input.jobId, token);\n return { host: BROKER_HOST, port: this.address?.port ?? 0, token };\n }\n\n createMainRequest(jobId: string, message: string): BrokerSendAcknowledgement {\n this.assertReady();\n const job = this.requireJob(jobId);\n return this.createRequest(job, \"main\", message);\n }\n\n replyFromMain(requestId: string, message: string): BrokerSendAcknowledgement {\n this.assertReady();\n return this.acceptResponse(\"main\", undefined, requestId, message);\n }\n\n rollbackMainRequest(requestId: string): void {\n const request = this.requests.get(requestId);\n if (request?.origin === \"main\" && request.response === undefined) {\n this.clearWaiter(request);\n this.requests.delete(requestId);\n }\n }\n\n revokeJob(jobId: string, reason = \"Subagent job is no longer active.\"): void {\n const token = this.tokenByJob.get(jobId);\n if (token) {\n this.tokenByJob.delete(jobId);\n this.jobsByToken.delete(token);\n }\n for (const request of [...this.requests.values()]) {\n if (request.jobId !== jobId) continue;\n if (request.waiter) this.respondError(request.waiter.socket, reason);\n this.clearWaiter(request);\n this.requests.delete(request.requestId);\n }\n }\n\n hasPendingMainRequest(): boolean {\n return [...this.requests.values()].some((request) => request.origin === \"child\" && request.response === undefined);\n }\n\n takePendingInboundResponse(): boolean {\n const pending = this.pendingInboundResponse;\n this.pendingInboundResponse = false;\n return pending;\n }\n\n markMainRequestQueued(requestId: string): boolean {\n const request = this.requests.get(requestId);\n if (request?.origin !== \"main\") {\n throw new Error(\"Unknown or expired main-agent subagent request.\");\n }\n request.deliveryQueued = true;\n return request.response === undefined;\n }\n\n interruptChildWaits(jobId: string): number {\n let interrupted = 0;\n for (const request of this.requests.values()) {\n if (request.jobId !== jobId || request.origin !== \"child\" || !request.waiter) continue;\n const socket = request.waiter.socket;\n this.clearWaiter(request);\n this.respondError(socket, CHILD_WAIT_INTERRUPTED_ERROR);\n interrupted++;\n }\n return interrupted;\n }\n\n subscribeInboundMessage(listener: () => void): () => void {\n this.inboundMessageListeners.add(listener);\n if (this.hasPendingMainRequest()) listener();\n return () => this.inboundMessageListeners.delete(listener);\n }\n\n async shutdown(): Promise<void> {\n ++this.generation;\n const starting = this.starting;\n if (starting) await starting.catch(() => undefined);\n for (const jobId of [...this.tokenByJob.keys()]) {\n this.revokeJob(jobId, \"Subagent session shut down.\");\n }\n this.requests.clear();\n this.inboundMessageListeners.clear();\n this.pendingInboundResponse = false;\n for (const socket of this.sockets) socket.destroy();\n this.sockets.clear();\n const server = this.server;\n this.server = undefined;\n this.address = undefined;\n this.failure = undefined;\n if (!server?.listening) return;\n await new Promise<void>((resolve) => server.close(() => resolve()));\n }\n\n private requireJob(jobId: string): JobRecord {\n const token = this.tokenByJob.get(jobId);\n const job = token ? this.jobsByToken.get(token) : undefined;\n if (!job) throw new Error(\"Unknown or inactive subagent job.\");\n return job;\n }\n\n private hasQueuedRequestForChild(jobId: string): boolean {\n return [...this.requests.values()].some(\n (request) =>\n request.jobId === jobId &&\n request.origin === \"main\" &&\n request.deliveryQueued === true &&\n request.response === undefined,\n );\n }\n\n private createRequest(job: JobRecord, origin: BrokerRequestOrigin, message: string): BrokerSendAcknowledgement {\n validateMessage(message, \"Subagent request\");\n const outstanding = [...this.requests.values()].filter(\n (request) => request.jobId === job.jobId && request.consumedAt === undefined,\n ).length;\n if (outstanding >= MAX_OUTSTANDING_REQUESTS) {\n throw new Error(`Subagent job may have at most ${MAX_OUTSTANDING_REQUESTS} outstanding requests.`);\n }\n const request: RequestRecord = {\n requestId: `req_${randomUUID()}`,\n jobId: job.jobId,\n generation: job.generation,\n origin,\n expectedResponder: origin === \"main\" ? \"child\" : \"main\",\n message,\n createdAt: this.now(),\n };\n this.requests.set(request.requestId, request);\n if (origin === \"child\") {\n try {\n this.deliverInbound({\n kind: \"request\",\n requestId: request.requestId,\n jobId: request.jobId,\n message: request.message,\n });\n } catch (error) {\n this.requests.delete(request.requestId);\n throw error;\n }\n }\n return { requestId: request.requestId, accepted: true, duplicate: false };\n }\n\n private acceptResponse(\n responder: BrokerRequestOrigin,\n job: JobRecord | undefined,\n requestId: string,\n message: string,\n ): BrokerSendAcknowledgement {\n validateRequestId(requestId);\n validateMessage(message, \"Subagent response\");\n const request = this.requests.get(requestId);\n if (\n !request ||\n request.expectedResponder !== responder ||\n (job && (request.jobId !== job.jobId || request.generation !== job.generation))\n ) {\n throw new Error(\"Unknown, expired, or unauthorized subagent request.\");\n }\n if (request.response !== undefined) {\n return { requestId, accepted: false, duplicate: true };\n }\n request.response = message;\n if (responder === \"child\") {\n try {\n this.deliverInbound({\n kind: \"response\",\n requestId,\n jobId: request.jobId,\n message,\n });\n this.markConsumed(request);\n } catch (error) {\n request.response = undefined;\n throw error;\n }\n } else if (request.waiter) {\n const socket = request.waiter.socket;\n this.clearWaiter(request);\n this.respond(socket, { ok: true, response: message }, () => this.markConsumed(request));\n }\n return { requestId, accepted: true, duplicate: false };\n }\n\n private deliverInbound(message: BrokerInboundMessage): void {\n this.options.onMessage(message);\n if (message.kind === \"response\" && this.inboundMessageListeners.size === 0) {\n this.pendingInboundResponse = true;\n }\n for (const listener of [...this.inboundMessageListeners]) {\n try {\n listener();\n } catch {\n // Runtime wait observers cannot interrupt broker delivery.\n }\n }\n }\n\n private accept(socket: Socket): void {\n if (!this.server || this.failure || this.sockets.size >= MAX_CONNECTIONS) {\n socket.destroy();\n return;\n }\n this.sockets.add(socket);\n socket.setNoDelay(true);\n let frame = Buffer.alloc(0);\n let handled = false;\n const frameTimer = setTimeout(() => {\n if (handled) return;\n handled = true;\n this.respondError(socket, \"Subagent broker request frame timed out.\");\n }, this.requestFrameTimeoutMs);\n frameTimer.unref();\n const cleanup = () => {\n clearTimeout(frameTimer);\n this.sockets.delete(socket);\n for (const request of this.requests.values()) {\n if (request.waiter?.socket === socket) this.clearWaiter(request);\n }\n };\n socket.on(\"data\", (chunk: Buffer) => {\n if (handled) return;\n frame = Buffer.concat([frame, chunk]);\n if (frame.byteLength > MAX_FRAME_BYTES) {\n handled = true;\n clearTimeout(frameTimer);\n this.respondError(socket, \"Subagent broker request exceeded its size limit.\");\n return;\n }\n const newline = frame.indexOf(0x0a);\n if (newline < 0) return;\n handled = true;\n clearTimeout(frameTimer);\n socket.removeAllListeners(\"data\");\n const trailing = frame\n .subarray(newline + 1)\n .toString(\"utf8\")\n .trim();\n if (trailing) {\n this.respondError(socket, \"Subagent broker accepts one request per connection.\");\n return;\n }\n this.handleFrame(socket, frame.subarray(0, newline).toString(\"utf8\"));\n });\n socket.once(\"close\", cleanup);\n socket.once(\"error\", cleanup);\n }\n\n private handleFrame(socket: Socket, frame: string): void {\n let request: BrokerRequest;\n try {\n const parsed = JSON.parse(frame) as unknown;\n if (!isRecord(parsed)) throw new Error();\n request = parsed as BrokerRequest;\n } catch {\n this.respondError(socket, \"Malformed subagent broker request.\");\n return;\n }\n const job = typeof request.token === \"string\" ? this.jobsByToken.get(request.token) : undefined;\n if (!job) {\n this.respondError(socket, \"Unauthenticated subagent broker request.\");\n return;\n }\n try {\n if (request.type === \"send\") {\n this.handleSend(socket, job, request);\n return;\n }\n if (request.type === \"wait\") {\n this.handleWait(socket, job, request);\n return;\n }\n throw new Error(\"Unsupported subagent broker request.\");\n } catch (error) {\n this.respondError(socket, error instanceof Error ? error.message : String(error));\n }\n }\n\n private handleSend(socket: Socket, job: JobRecord, request: Extract<BrokerRequest, { type: \"send\" }>): void {\n if (typeof request.message !== \"string\") {\n throw new Error(\"subagent_send requires a message string.\");\n }\n const hasRecipient = typeof request.recipient === \"string\";\n const hasRequestId = typeof request.requestId === \"string\";\n if (hasRecipient === hasRequestId) {\n throw new Error(\"subagent_send requires exactly one of recipient or requestId.\");\n }\n const acknowledgement = hasRecipient\n ? request.recipient === \"main\"\n ? this.createRequest(job, \"child\", request.message)\n : (() => {\n throw new Error('A subagent may send new requests only to recipient \"main\".');\n })()\n : this.acceptResponse(\"child\", job, request.requestId ?? \"\", request.message);\n this.respond(socket, { ok: true, ...acknowledgement });\n }\n\n private handleWait(socket: Socket, job: JobRecord, request: Extract<BrokerRequest, { type: \"wait\" }>): void {\n if (typeof request.requestId !== \"string\") {\n throw new Error(\"Subagent wait requires a request ID.\");\n }\n validateRequestId(request.requestId);\n if (request.timeoutMs !== undefined) validateTimeout(request.timeoutMs);\n const record = this.requests.get(request.requestId);\n if (record?.origin !== \"child\" || record.jobId !== job.jobId || record.generation !== job.generation) {\n throw new Error(\"Unknown or expired subagent request.\");\n }\n if (record.consumedAt !== undefined && record.response !== undefined) {\n this.respond(socket, { ok: true, response: record.response });\n return;\n }\n if (record.response !== undefined) {\n this.respond(socket, { ok: true, response: record.response }, () => this.markConsumed(record));\n return;\n }\n if (this.hasQueuedRequestForChild(job.jobId)) {\n this.respondError(socket, CHILD_WAIT_INTERRUPTED_ERROR);\n return;\n }\n if (record.waiter) {\n throw new Error(`A wait is already active for subagent request ${request.requestId}.`);\n }\n const waiter: RequestWaiter = { socket };\n record.waiter = waiter;\n if (request.timeoutMs !== undefined) {\n waiter.timer = setTimeout(() => {\n if (record.waiter !== waiter) return;\n this.clearWaiter(record);\n this.respondError(socket, \"Subagent response wait timed out.\");\n }, request.timeoutMs);\n waiter.timer.unref();\n }\n }\n\n private markConsumed(request: RequestRecord): void {\n if (this.requests.get(request.requestId) !== request || request.response === undefined) return;\n request.consumedAt ??= this.now();\n const consumed = [...this.requests.values()]\n .filter((candidate) => candidate.jobId === request.jobId && candidate.consumedAt !== undefined)\n .sort((left, right) => (left.consumedAt ?? 0) - (right.consumedAt ?? 0));\n for (const expired of consumed.slice(0, Math.max(0, consumed.length - MAX_RETAINED_CONSUMED_REQUESTS))) {\n this.requests.delete(expired.requestId);\n }\n }\n\n private clearWaiter(request: RequestRecord): void {\n if (request.waiter?.timer) clearTimeout(request.waiter.timer);\n request.waiter = undefined;\n }\n\n private respondError(socket: Socket, error: string): void {\n this.respond(socket, { ok: false, error: truncateError(error) });\n }\n\n private respond(socket: Socket, value: Record<string, unknown>, onFlushed?: () => void): void {\n if (socket.destroyed) return;\n let content = `${JSON.stringify(value)}\\n`;\n if (Buffer.byteLength(content, \"utf8\") > MAX_FRAME_BYTES) {\n content = `${JSON.stringify({ ok: false, error: \"Subagent broker response exceeded its size limit.\" })}\\n`;\n }\n socket.end(content, onFlushed);\n }\n\n private fail(error: Error): void {\n this.failure = truncateError(error.message);\n for (const jobId of [...this.tokenByJob.keys()]) {\n this.revokeJob(jobId, \"Subagent message broker failed.\");\n }\n for (const socket of this.sockets) socket.destroy();\n this.sockets.clear();\n this.address = undefined;\n }\n}\n\nexport function validateMessage(message: string, label: string): void {\n if (!message.trim()) throw new Error(`${label} is required.`);\n if (message.includes(\"\\0\")) throw new Error(`${label} must not contain NUL bytes.`);\n if (Buffer.byteLength(message, \"utf8\") > MAX_MESSAGE_BYTES) {\n throw new Error(`${label} must be at most ${MAX_MESSAGE_BYTES} UTF-8 bytes.`);\n }\n if (lineCount(message) > MAX_MESSAGE_LINES) {\n throw new Error(`${label} must contain at most ${MAX_MESSAGE_LINES} lines.`);\n }\n}\n\nexport function sanitizeTerminalText(value: string): string {\n return [...value]\n .filter((character) => {\n const codePoint = character.codePointAt(0) ?? 0;\n if (character === \"\\n\" || character === \"\\t\") return true;\n if (codePoint <= 0x1f || (codePoint >= 0x7f && codePoint <= 0x9f)) return false;\n return !((codePoint >= 0x202a && codePoint <= 0x202e) || (codePoint >= 0x2066 && codePoint <= 0x2069));\n })\n .join(\"\");\n}\n\nfunction validateRequestId(requestId: string): void {\n if (\n requestId.length > MAX_IDENTIFIER_LENGTH ||\n !/^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)\n ) {\n throw new Error(\"Invalid subagent request ID.\");\n }\n}\n\nfunction validateTimeout(timeoutMs: number): void {\n if (!Number.isFinite(timeoutMs) || timeoutMs <= 0 || timeoutMs > MAX_TIMEOUT_MS) {\n throw new Error(\"Subagent wait timeout is outside the supported range.\");\n }\n}\n\nfunction lineCount(value: string): number {\n let count = 1;\n for (const character of value) if (character === \"\\n\") count++;\n return count;\n}\n\nfunction truncateError(error: string): string {\n const bytes = Buffer.from(error, \"utf8\");\n if (bytes.length <= MAX_ERROR_BYTES) return error;\n return `${bytes\n .subarray(0, Math.max(0, MAX_ERROR_BYTES - 18))\n .toString(\"utf8\")\n .replace(/\uFFFD+$/gu, \"\")}\\n\u2026 [truncated]`;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isLoopbackAddress(address: AddressInfo | string | null): address is AddressInfo {\n return Boolean(address && typeof address !== \"string\" && address.address === BROKER_HOST);\n}\n", "import * as fs from \"node:fs\";\nimport type { BrokerCredentials } from \"./types.js\";\n\nexport const BROKER_CREDENTIAL_FD = 3;\nexport const BROKER_CREDENTIAL_FD_ENV = \"PI_SUBAGENT_BROKER_FD\";\n\nconst MAX_CREDENTIAL_BYTES = 1_024;\n\nexport function brokerCredentialEnvironment(): NodeJS.ProcessEnv {\n return { [BROKER_CREDENTIAL_FD_ENV]: String(BROKER_CREDENTIAL_FD) };\n}\n\nexport function serializeBrokerCredentials(credentials: BrokerCredentials): string {\n return JSON.stringify(credentials);\n}\n\nexport function captureBrokerCredentials(\n readCredentials: () => string = readCredentialPipe,\n): BrokerCredentials | undefined {\n const descriptor = process.env[BROKER_CREDENTIAL_FD_ENV];\n delete process.env[BROKER_CREDENTIAL_FD_ENV];\n if (descriptor === undefined) return undefined;\n if (descriptor !== String(BROKER_CREDENTIAL_FD)) {\n throw new Error(\"Invalid pi-subagents broker credential descriptor.\");\n }\n let serialized: string;\n try {\n serialized = readCredentials();\n } catch {\n throw new Error(\"Unable to read pi-subagents broker credentials.\");\n }\n if (Buffer.byteLength(serialized, \"utf8\") > MAX_CREDENTIAL_BYTES) {\n throw new Error(\"Invalid pi-subagents broker credentials.\");\n }\n let value: unknown;\n try {\n value = JSON.parse(serialized);\n } catch {\n throw new Error(\"Invalid pi-subagents broker credentials.\");\n }\n if (!isBrokerCredentials(value)) {\n throw new Error(\"Invalid pi-subagents broker credentials.\");\n }\n return value;\n}\n\nfunction readCredentialPipe(): string {\n try {\n return fs.readFileSync(BROKER_CREDENTIAL_FD, \"utf8\");\n } finally {\n try {\n fs.closeSync(BROKER_CREDENTIAL_FD);\n } catch {\n // The descriptor may already be closed after a failed read.\n }\n }\n}\n\nfunction isBrokerCredentials(value: unknown): value is BrokerCredentials {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return false;\n const candidate = value as Record<string, unknown>;\n return (\n Object.keys(candidate).length === 3 &&\n candidate.host === \"127.0.0.1\" &&\n Number.isSafeInteger(candidate.port) &&\n (candidate.port as number) >= 1 &&\n (candidate.port as number) <= 65_535 &&\n typeof candidate.token === \"string\" &&\n /^[a-f0-9]{64}$/u.test(candidate.token)\n );\n}\n", "import type { ExtensionFactory } from \"@earendil-works/pi-coding-agent\";\nimport { type Static, Type } from \"typebox\";\nimport {\n type BrokerSendAcknowledgement,\n MAX_IDENTIFIER_LENGTH,\n MAX_MESSAGE_BYTES,\n sanitizeTerminalText,\n validateMessage,\n} from \"./message-broker.js\";\n\nexport const CHILD_COMMUNICATION_TOOL_NAMES = [\"subagent_send\", \"subagent_wait\"] as const;\n\nconst MAX_TIMEOUT_MS = 2_147_483_647;\nconst MAX_TIMEOUT_SECONDS = MAX_TIMEOUT_MS / 1000;\n\nconst SendParameters = Type.Object(\n {\n requestId: Type.Optional(\n Type.String({\n description: \"Pending main-agent request to answer. Omit when starting a new request.\",\n minLength: 1,\n maxLength: MAX_IDENTIFIER_LENGTH,\n }),\n ),\n message: Type.String({\n description: \"Plain-text request or response. Maximum 48 KiB of UTF-8 text and 1,992 lines.\",\n minLength: 1,\n maxLength: MAX_MESSAGE_BYTES,\n }),\n },\n { additionalProperties: false },\n);\n\nconst WaitParameters = Type.Object(\n {\n requestId: Type.String({\n description: \"Request ID returned by subagent_send.\",\n minLength: 1,\n maxLength: MAX_IDENTIFIER_LENGTH,\n }),\n timeout: Type.Optional(Type.Number({ description: \"Timeout in seconds (optional, no default timeout)\" })),\n },\n { additionalProperties: false },\n);\n\ntype ChildBrokerSendArguments = { recipient: \"main\"; message: string } | { requestId: string; message: string };\n\ntype WaitArguments = Static<typeof WaitParameters>;\n\nexport interface ChildCommunicationClient {\n send(params: ChildBrokerSendArguments, signal?: AbortSignal): Promise<BrokerSendAcknowledgement>;\n wait(requestId: string, timeoutMs: number | undefined, signal?: AbortSignal): Promise<string>;\n}\n\nexport function createChildCommunicationExtension(client: ChildCommunicationClient): ExtensionFactory {\n return (pi) => {\n pi.registerTool({\n name: \"subagent_send\",\n label: \"Subagent \u00B7 Send to Main\",\n description:\n \"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.\",\n promptSnippet: \"Use subagent_send to send or answer one main-agent message\",\n parameters: SendParameters,\n async execute(_toolCallId, params, signal) {\n validateMessage(params.message, \"Subagent message\");\n const requestId = optionalIdentifier(params.requestId, \"requestId\");\n const acknowledgement = await client.send(\n requestId === undefined\n ? { recipient: \"main\", message: params.message }\n : { requestId, message: params.message },\n signal,\n );\n return {\n content: [{ type: \"text\" as const, text: JSON.stringify(acknowledgement) }],\n details: acknowledgement,\n };\n },\n });\n\n pi.registerTool({\n name: \"subagent_wait\",\n label: \"Subagent \u00B7 Wait for Main Agent\",\n description:\n \"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.\",\n promptSnippet: \"Use subagent_wait to receive a requested main-agent response\",\n parameters: WaitParameters,\n prepareArguments: prepareWaitArguments,\n async execute(_toolCallId, params, signal) {\n const requestId = requiredIdentifier(params.requestId, \"requestId\");\n const response = await client.wait(requestId, resolveTimeoutMs(params.timeout), signal);\n return {\n content: [{ type: \"text\" as const, text: sanitizeTerminalText(response) }],\n details: { requestId },\n };\n },\n });\n };\n}\n\nfunction resolveTimeoutMs(timeout: number | undefined): number | undefined {\n if (timeout === undefined) return undefined;\n if (!Number.isFinite(timeout) || timeout <= 0) {\n throw new Error(\"Invalid timeout: must be a finite number of seconds\");\n }\n const timeoutMs = timeout * 1000;\n if (timeoutMs > MAX_TIMEOUT_MS) {\n throw new Error(`Invalid timeout: maximum is ${MAX_TIMEOUT_SECONDS} seconds`);\n }\n return timeoutMs;\n}\n\nfunction prepareWaitArguments(args: unknown): WaitArguments {\n if (!args || typeof args !== \"object\") return args as WaitArguments;\n if (!Object.hasOwn(args, \"timeoutMs\")) return args as WaitArguments;\n const record = args as Record<string, unknown>;\n if (typeof record.timeoutMs !== \"number\") return record as WaitArguments;\n const { timeoutMs, ...prepared } = record;\n if (prepared.timeout === undefined) {\n return { ...prepared, timeout: timeoutMs / 1000 } as WaitArguments;\n }\n return prepared as WaitArguments;\n}\n\nfunction optionalIdentifier(value: unknown, field: string): string | undefined {\n return value === undefined ? undefined : requiredIdentifier(value, field);\n}\n\nfunction requiredIdentifier(value: unknown, field: string): string {\n if (typeof value !== \"string\" || !value.trim()) throw new Error(`Subagent ${field} is required.`);\n const identifier = value.trim();\n if (\n identifier.length > MAX_IDENTIFIER_LENGTH ||\n [...identifier].some((character) => {\n const codePoint = character.codePointAt(0) ?? 0;\n return codePoint <= 0x1f || (codePoint >= 0x7f && codePoint <= 0x9f);\n })\n ) {\n throw new Error(`Subagent ${field} is invalid.`);\n }\n return identifier;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["request", "MAX_TIMEOUT_MS"]
|
|
7
|
+
}
|