@mono-agent/agent-runtime 0.20.11 → 0.21.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 (148) hide show
  1. package/ARCHITECTURE.md +50 -11
  2. package/MIGRATION.md +288 -26
  3. package/README.md +352 -477
  4. package/package.json +13 -44
  5. package/src/agent/tool-bloat.js +145 -9
  6. package/src/agent/tools/agent-tool.js +108 -9
  7. package/src/agent/tools/bash.js +11 -26
  8. package/src/agent/tools/codex-subscription-search.js +123 -29
  9. package/src/agent/tools/exec.js +10 -2
  10. package/src/agent/tools/index.js +7 -0
  11. package/src/agent/tools/monitor.js +149 -0
  12. package/src/agent/tools/pi-bridge.js +123 -19
  13. package/src/agent/tools/shared/bash-environment.js +31 -0
  14. package/src/agent/tools/shared/monitors.js +293 -0
  15. package/src/agent/tools/shared/path-resolver.js +25 -6
  16. package/src/agent/tools/shared/process-jobs.js +6 -1
  17. package/src/agent/tools/shared/process-runner.js +26 -6
  18. package/src/agent/tools/shared/tool-context.js +8 -0
  19. package/src/agent/tools/web-access-interstitial.js +70 -0
  20. package/src/agent/tools/web-browser-render.js +83 -58
  21. package/src/agent/tools/web-controller.js +112 -21
  22. package/src/agent/tools/web-document-extractor.js +379 -0
  23. package/src/agent/tools/web-fetch.js +271 -243
  24. package/src/agent/tools/web-request.js +65 -0
  25. package/src/agent/tools/web-search-output.js +165 -0
  26. package/src/agent/tools/web-search-state.js +75 -0
  27. package/src/agent/tools/web-search.js +532 -71
  28. package/src/ai/cost.js +13 -68
  29. package/src/ai/failure.js +3 -3
  30. package/src/ai/index.js +5 -17
  31. package/src/ai/observer.js +8 -0
  32. package/src/ai/pi-interop.js +221 -1
  33. package/src/ai/pi-oauth-compat.js +1 -1
  34. package/src/ai/provider-check.js +131 -0
  35. package/src/ai/providers/codex/app-server-client.js +592 -0
  36. package/src/ai/providers/pi-models.js +18 -10
  37. package/src/ai/providers/pi-native/compaction-driver.js +94 -42
  38. package/src/ai/providers/pi-native/compaction-summary.js +140 -0
  39. package/src/ai/providers/pi-native/harness-adapter.js +376 -0
  40. package/src/ai/providers/pi-native/prompt-cache-diagnostics.js +103 -0
  41. package/src/ai/providers/pi-native/provider-attribution.js +102 -0
  42. package/src/ai/providers/pi-native/result-builder.js +38 -14
  43. package/src/ai/providers/pi-native/session-lifecycle.js +253 -55
  44. package/src/ai/providers/pi-native/stream-subscriber.js +52 -6
  45. package/src/ai/providers/pi-native/terminal-recovery.js +40 -0
  46. package/src/ai/providers/pi-native/turn-runner.js +279 -28
  47. package/src/ai/providers/pi-native.js +206 -61
  48. package/src/ai/runtime/capabilities.js +11 -56
  49. package/src/ai/runtime/live-input-events.js +250 -54
  50. package/src/ai/runtime/model-refs.js +118 -153
  51. package/src/ai/runtime/registry.js +22 -56
  52. package/src/ai/runtime/router.js +76 -417
  53. package/src/ai/runtime/session-liveness.js +3 -4
  54. package/src/ai/runtime/sessions.js +4 -5
  55. package/src/ai/runtime/tool-policy.js +0 -2
  56. package/src/ai/tool-lifecycle.js +32 -18
  57. package/src/ai/types.js +37 -112
  58. package/src/index.js +0 -6
  59. package/src/runtime.js +29 -16
  60. package/types/agent/tool-bloat.d.ts +1 -1
  61. package/types/agent/tools/agent-tool.d.ts +4 -2
  62. package/types/agent/tools/bash.d.ts +5 -3
  63. package/types/agent/tools/codex-subscription-search.d.ts +7 -3
  64. package/types/agent/tools/exec.d.ts +5 -3
  65. package/types/agent/tools/index.d.ts +1 -0
  66. package/types/agent/tools/monitor.d.ts +47 -0
  67. package/types/agent/tools/pi-bridge.d.ts +7 -4
  68. package/types/agent/tools/shared/bash-environment.d.ts +4 -0
  69. package/types/agent/tools/shared/monitors.d.ts +98 -0
  70. package/types/agent/tools/shared/process-jobs.d.ts +5 -1
  71. package/types/agent/tools/shared/process-runner.d.ts +14 -4
  72. package/types/agent/tools/shared/tool-context.d.ts +2 -0
  73. package/types/agent/tools/web-access-interstitial.d.ts +23 -0
  74. package/types/agent/tools/web-browser-render.d.ts +4 -1
  75. package/types/agent/tools/web-controller.d.ts +4 -2
  76. package/types/agent/tools/web-document-extractor.d.ts +27 -0
  77. package/types/agent/tools/web-fetch.d.ts +19 -24
  78. package/types/agent/tools/web-request.d.ts +20 -0
  79. package/types/agent/tools/web-search-output.d.ts +31 -0
  80. package/types/agent/tools/web-search-state.d.ts +21 -0
  81. package/types/agent/tools/web-search.d.ts +10 -45
  82. package/types/ai/cost.d.ts +1 -2
  83. package/types/ai/index.d.ts +2 -4
  84. package/types/ai/observer.d.ts +6 -0
  85. package/types/ai/pi-interop.d.ts +81 -0
  86. package/types/ai/provider-check.d.ts +53 -0
  87. package/types/ai/providers/codex/app-server-client.d.ts +37 -0
  88. package/types/ai/providers/pi-native/compaction-driver.d.ts +2 -1
  89. package/types/ai/providers/pi-native/compaction-summary.d.ts +19 -0
  90. package/types/ai/providers/pi-native/harness-adapter.d.ts +58 -0
  91. package/types/ai/providers/pi-native/prompt-cache-diagnostics.d.ts +3 -0
  92. package/types/ai/providers/pi-native/provider-attribution.d.ts +26 -0
  93. package/types/ai/providers/pi-native/result-builder.d.ts +14 -4
  94. package/types/ai/providers/pi-native/session-lifecycle.d.ts +25 -6
  95. package/types/ai/providers/pi-native/stream-subscriber.d.ts +2 -2
  96. package/types/ai/providers/pi-native/terminal-recovery.d.ts +2 -0
  97. package/types/ai/providers/pi-native/turn-runner.d.ts +68 -10
  98. package/types/ai/providers/pi-native.d.ts +21 -4
  99. package/types/ai/runtime/capabilities.d.ts +21 -70
  100. package/types/ai/runtime/live-input-events.d.ts +32 -8
  101. package/types/ai/runtime/model-refs.d.ts +0 -24
  102. package/types/ai/runtime/router.d.ts +3 -10
  103. package/types/ai/runtime/tool-policy.d.ts +0 -2
  104. package/types/ai/tool-lifecycle.d.ts +4 -3
  105. package/types/ai/types.d.ts +162 -256
  106. package/types/index.d.ts +0 -1
  107. package/src/ai/providers/acp-client.js +0 -1149
  108. package/src/ai/providers/acp-privacy.js +0 -124
  109. package/src/ai/providers/acp-public.js +0 -21
  110. package/src/ai/providers/acp-session-tokens.js +0 -282
  111. package/src/ai/providers/acp-transport.js +0 -356
  112. package/src/ai/providers/acp.js +0 -543
  113. package/src/ai/providers/claude-cli.js +0 -883
  114. package/src/ai/providers/claude-sandbox.js +0 -71
  115. package/src/ai/providers/claude-sdk-discovery-worker.js +0 -53
  116. package/src/ai/providers/claude-sdk-discovery.js +0 -352
  117. package/src/ai/providers/claude-sdk.js +0 -1127
  118. package/src/ai/providers/claude-subagent-activity.js +0 -719
  119. package/src/ai/providers/claude-subagents.js +0 -88
  120. package/src/ai/providers/codex-app.js +0 -2946
  121. package/src/ai/providers/opencode-app.js +0 -1109
  122. package/src/ai/providers/opencode-discovery.js +0 -39
  123. package/src/ai/providers/opencode-server.js +0 -508
  124. package/src/ai/runtime/context-windows.js +0 -46
  125. package/src/ai/runtime/fast-mode.js +0 -8
  126. package/src/ai/streaming/codex-events.js +0 -146
  127. package/src/ai/streaming/opencode-events.js +0 -59
  128. package/types/ai/providers/acp-client.d.ts +0 -227
  129. package/types/ai/providers/acp-privacy.d.ts +0 -25
  130. package/types/ai/providers/acp-public.d.ts +0 -7
  131. package/types/ai/providers/acp-session-tokens.d.ts +0 -41
  132. package/types/ai/providers/acp-transport.d.ts +0 -45
  133. package/types/ai/providers/acp.d.ts +0 -93
  134. package/types/ai/providers/claude-cli.d.ts +0 -305
  135. package/types/ai/providers/claude-sandbox.d.ts +0 -79
  136. package/types/ai/providers/claude-sdk-discovery-worker.d.ts +0 -1
  137. package/types/ai/providers/claude-sdk-discovery.d.ts +0 -97
  138. package/types/ai/providers/claude-sdk.d.ts +0 -138
  139. package/types/ai/providers/claude-subagent-activity.d.ts +0 -53
  140. package/types/ai/providers/claude-subagents.d.ts +0 -18
  141. package/types/ai/providers/codex-app.d.ts +0 -151
  142. package/types/ai/providers/opencode-app.d.ts +0 -96
  143. package/types/ai/providers/opencode-discovery.d.ts +0 -4
  144. package/types/ai/providers/opencode-server.d.ts +0 -20
  145. package/types/ai/runtime/context-windows.d.ts +0 -9
  146. package/types/ai/runtime/fast-mode.d.ts +0 -2
  147. package/types/ai/streaming/codex-events.d.ts +0 -40
  148. package/types/ai/streaming/opencode-events.d.ts +0 -42
@@ -1,356 +0,0 @@
1
- // @ts-check
2
-
3
- import { AsyncLocalStorage } from "node:async_hooks";
4
-
5
- // Strict, bounded ACP v1 newline transport for an owned stdio child process.
6
- // The SDK's stock ndJsonStream intentionally tolerates malformed input and its
7
- // line buffer is unbounded, which is a poor fit for a long-lived host boundary.
8
-
9
- const DEFAULT_MAX_LINE_BYTES = 1024 * 1024;
10
- const MAX_MAX_LINE_BYTES = 16 * 1024 * 1024;
11
-
12
- // @agentclientprotocol/sdk 1.3.0 sends the trailing arguments of these
13
- // diagnostics directly to console. Those values include raw JSON-RPC payloads
14
- // (and, for malformed notifications, Zod error details derived from them).
15
- // Preserve the useful classification while dropping payload-bearing details.
16
- const ACP_SDK_PAYLOAD_DIAGNOSTICS = Object.freeze({
17
- error: new Set([
18
- "Invalid message",
19
- "Error handling notification",
20
- "Got response to unknown request",
21
- "Failed to parse JSON message:",
22
- "ACP connection router stopped unexpectedly:",
23
- ]),
24
- warn: new Set([
25
- "Skipping JSON line that is not an object:",
26
- ]),
27
- });
28
- const acpSdkDiagnosticScope = new AsyncLocalStorage();
29
- let activeAcpSdkDiagnosticGuards = 0;
30
- /** @type {null|{
31
- * originalError: typeof console.error,
32
- * originalWarn: typeof console.warn,
33
- * guardedError: typeof console.error,
34
- * guardedWarn: typeof console.warn,
35
- * }} */
36
- let acpSdkConsoleGuard = null;
37
-
38
- function installAcpSdkConsoleGuard() {
39
- activeAcpSdkDiagnosticGuards += 1;
40
- if (acpSdkConsoleGuard) return;
41
-
42
- const originalError = console.error;
43
- const originalWarn = console.warn;
44
- /** @type {typeof console.error} */
45
- const guardedError = (...args) => {
46
- const contentFree = args[0];
47
- if (acpSdkDiagnosticScope.getStore() === true
48
- && typeof contentFree === "string"
49
- && ACP_SDK_PAYLOAD_DIAGNOSTICS.error.has(contentFree)) {
50
- Reflect.apply(originalError, console, [contentFree]);
51
- return;
52
- }
53
- Reflect.apply(originalError, console, args);
54
- };
55
- /** @type {typeof console.warn} */
56
- const guardedWarn = (...args) => {
57
- const contentFree = args[0];
58
- if (acpSdkDiagnosticScope.getStore() === true
59
- && typeof contentFree === "string"
60
- && ACP_SDK_PAYLOAD_DIAGNOSTICS.warn.has(contentFree)) {
61
- Reflect.apply(originalWarn, console, [contentFree]);
62
- return;
63
- }
64
- Reflect.apply(originalWarn, console, args);
65
- };
66
-
67
- acpSdkConsoleGuard = { originalError, originalWarn, guardedError, guardedWarn };
68
- console.error = guardedError;
69
- console.warn = guardedWarn;
70
- }
71
-
72
- function releaseAcpSdkConsoleGuard() {
73
- activeAcpSdkDiagnosticGuards = Math.max(0, activeAcpSdkDiagnosticGuards - 1);
74
- if (activeAcpSdkDiagnosticGuards !== 0 || !acpSdkConsoleGuard) return;
75
- const guard = acpSdkConsoleGuard;
76
- acpSdkConsoleGuard = null;
77
- if (console.error === guard.guardedError) console.error = guard.originalError;
78
- if (console.warn === guard.guardedWarn) console.warn = guard.originalWarn;
79
- }
80
-
81
- /**
82
- * Open one SDK connection inside an async context that strips payload-bearing
83
- * SDK console arguments. The SDK starts its detached receive loop during
84
- * `connect`, so descendants retain this scope without muting concurrent host
85
- * work or other ACP connections.
86
- *
87
- * @template {{closed: Promise<unknown>}} T
88
- * @param {() => T} connect
89
- * @returns {T}
90
- */
91
- export function connectWithSafeAcpSdkDiagnostics(connect) {
92
- installAcpSdkConsoleGuard();
93
- let connection;
94
- try {
95
- connection = acpSdkDiagnosticScope.run(true, connect);
96
- } catch (error) {
97
- releaseAcpSdkConsoleGuard();
98
- throw error;
99
- }
100
- void Promise.resolve(connection.closed).then(
101
- releaseAcpSdkConsoleGuard,
102
- releaseAcpSdkConsoleGuard,
103
- );
104
- return connection;
105
- }
106
-
107
- export class AcpTransportError extends Error {
108
- /**
109
- * @param {string} code
110
- * @param {string} message
111
- */
112
- constructor(code, message) {
113
- super(message);
114
- this.name = "AcpTransportError";
115
- this.code = code;
116
- }
117
- }
118
-
119
- /**
120
- * @param {unknown} value
121
- * @param {number} [fallback]
122
- * @returns {number}
123
- */
124
- export function normalizeAcpMaxLineBytes(value, fallback = DEFAULT_MAX_LINE_BYTES) {
125
- if (value === undefined) return fallback;
126
- if (!Number.isInteger(value) || Number(value) < 1024 || Number(value) > MAX_MAX_LINE_BYTES) {
127
- throw new AcpTransportError(
128
- "invalid_transport_policy",
129
- `ACP maxLineBytes must be an integer between 1024 and ${MAX_MAX_LINE_BYTES}.`,
130
- );
131
- }
132
- return Number(value);
133
- }
134
-
135
- /**
136
- * The transport only accepts individual JSON-RPC 2.0 objects. Batches are not
137
- * part of ACP v1 and are rejected before the SDK sees them.
138
- * @param {unknown} value
139
- * @returns {value is Record<string, unknown>}
140
- */
141
- function isIndividualJsonRpcMessage(value) {
142
- if (!value || typeof value !== "object" || Array.isArray(value)) return false;
143
- const record = /** @type {Record<string, unknown>} */ (value);
144
- if (record.jsonrpc !== "2.0") return false;
145
-
146
- const hasId = Object.hasOwn(record, "id");
147
- const hasMethod = Object.hasOwn(record, "method");
148
- const hasParams = Object.hasOwn(record, "params");
149
- const hasResult = Object.hasOwn(record, "result");
150
- const hasError = Object.hasOwn(record, "error");
151
-
152
- const validId = !hasId
153
- || record.id === null
154
- || typeof record.id === "string"
155
- || (typeof record.id === "number" && Number.isFinite(record.id));
156
- if (!validId) return false;
157
-
158
- if (hasMethod) {
159
- if (typeof record.method !== "string" || record.method.length === 0) return false;
160
- if (hasParams) {
161
- const params = record.params;
162
- if (!params || typeof params !== "object") return false;
163
- }
164
- return !hasResult && !hasError;
165
- }
166
-
167
- if (!hasId || hasParams || hasResult === hasError) return false;
168
- if (!hasError) return true;
169
- if (!record.error || typeof record.error !== "object" || Array.isArray(record.error)) return false;
170
- const error = /** @type {Record<string, unknown>} */ (record.error);
171
- return Number.isInteger(error.code) && typeof error.message === "string";
172
- }
173
-
174
- /**
175
- * @param {Buffer} line
176
- * @returns {Record<string, unknown>}
177
- */
178
- function decodeLine(line) {
179
- if (line.length === 0) {
180
- throw new AcpTransportError("invalid_jsonrpc", "ACP peer emitted an empty NDJSON line.");
181
- }
182
- let text;
183
- try {
184
- text = new TextDecoder("utf-8", { fatal: true }).decode(line);
185
- } catch {
186
- throw new AcpTransportError("invalid_utf8", "ACP peer emitted invalid UTF-8.");
187
- }
188
- let parsed;
189
- try {
190
- parsed = JSON.parse(text);
191
- } catch {
192
- throw new AcpTransportError("invalid_jsonrpc", "ACP peer emitted malformed JSON.");
193
- }
194
- if (!isIndividualJsonRpcMessage(parsed)) {
195
- throw new AcpTransportError("invalid_jsonrpc", "ACP peer emitted a non-ACP JSON-RPC message.");
196
- }
197
- return parsed;
198
- }
199
-
200
- /**
201
- * Build the Stream shape consumed by @agentclientprotocol/sdk from a child
202
- * process's stdin/stdout. Both inbound and outbound payloads are capped.
203
- *
204
- * @param {{stdin: import('node:stream').Writable|null, stdout: import('node:stream').Readable|null}} child
205
- * @param {{maxLineBytes?: number}} [options]
206
- * @returns {{readable: ReadableStream<any>, writable: WritableStream<any>}}
207
- */
208
- export function createBoundedAcpStdioStream(child, options = {}) {
209
- const maxLineBytes = normalizeAcpMaxLineBytes(options.maxLineBytes);
210
- if (!child.stdin || !child.stdout) {
211
- throw new AcpTransportError("stdio_unavailable", "ACP child stdio is unavailable.");
212
- }
213
- const input = child.stdout;
214
- const output = child.stdin;
215
-
216
- let pending = Buffer.alloc(0);
217
- let settled = false;
218
- let inputEnded = false;
219
- /** @type {ReadableStreamDefaultController<any>|null} */
220
- let readableController = null;
221
-
222
- const cleanupReadable = () => {
223
- input.off("data", onData);
224
- input.off("end", onEnd);
225
- input.off("error", onError);
226
- };
227
- const failReadable = (error) => {
228
- if (settled) return;
229
- settled = true;
230
- input.pause();
231
- cleanupReadable();
232
- readableController?.error(error instanceof Error
233
- ? error
234
- : new AcpTransportError("transport_failed", "ACP stdout failed."));
235
- };
236
- const firstPendingLineIsTooLarge = () => {
237
- const newline = pending.indexOf(0x0a);
238
- if (newline !== -1) {
239
- const contentBytes = newline > 0 && pending[newline - 1] === 0x0d ? newline - 1 : newline;
240
- return contentBytes > maxLineBytes;
241
- }
242
- if (pending.length <= maxLineBytes) return false;
243
- return pending.length > maxLineBytes + 1 || pending[pending.length - 1] !== 0x0d;
244
- };
245
- const finishReadableIfEnded = () => {
246
- if (!inputEnded || settled || !readableController) return false;
247
- if (pending.length === 0) {
248
- settled = true;
249
- cleanupReadable();
250
- readableController.close();
251
- return true;
252
- }
253
- if (pending.indexOf(0x0a) === -1) {
254
- failReadable(new AcpTransportError(
255
- "unterminated_line",
256
- "ACP peer closed stdout with an unterminated JSON-RPC line.",
257
- ));
258
- return true;
259
- }
260
- return false;
261
- };
262
- const drainPending = () => {
263
- if (settled || !readableController) return;
264
- while (readableController.desiredSize !== null && readableController.desiredSize > 0) {
265
- const newline = pending.indexOf(0x0a);
266
- if (newline === -1) break;
267
- let line = pending.subarray(0, newline);
268
- pending = pending.subarray(newline + 1);
269
- if (line.length > 0 && line[line.length - 1] === 0x0d) line = line.subarray(0, line.length - 1);
270
- if (line.length > maxLineBytes) {
271
- failReadable(new AcpTransportError("line_too_large", "ACP peer exceeded the inbound line limit."));
272
- return;
273
- }
274
- try {
275
- readableController.enqueue(decodeLine(line));
276
- } catch (error) {
277
- failReadable(error);
278
- return;
279
- }
280
- }
281
- if (firstPendingLineIsTooLarge()) {
282
- failReadable(new AcpTransportError("line_too_large", "ACP peer exceeded the inbound line limit."));
283
- return;
284
- }
285
- if (finishReadableIfEnded()) return;
286
- if (readableController.desiredSize !== null
287
- && readableController.desiredSize > 0
288
- && pending.indexOf(0x0a) === -1) {
289
- input.resume();
290
- }
291
- };
292
- const onData = (chunk) => {
293
- if (settled) return;
294
- input.pause();
295
- const next = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
296
- pending = pending.length === 0 ? next : Buffer.concat([pending, next]);
297
- drainPending();
298
- };
299
- const onEnd = () => {
300
- if (settled) return;
301
- inputEnded = true;
302
- drainPending();
303
- };
304
- const onError = () => failReadable(new AcpTransportError("transport_failed", "ACP stdout failed."));
305
-
306
- const readable = new ReadableStream({
307
- start(controller) {
308
- readableController = controller;
309
- input.pause();
310
- input.on("data", onData);
311
- input.once("end", onEnd);
312
- input.once("error", onError);
313
- drainPending();
314
- },
315
- pull() {
316
- drainPending();
317
- },
318
- cancel() {
319
- if (!settled) {
320
- settled = true;
321
- cleanupReadable();
322
- }
323
- input.destroy();
324
- },
325
- }, { highWaterMark: 1 });
326
-
327
- const writable = new WritableStream({
328
- async write(message) {
329
- let json;
330
- try {
331
- json = JSON.stringify(message);
332
- } catch {
333
- throw new AcpTransportError("invalid_outbound_json", "ACP outbound message is not JSON serializable.");
334
- }
335
- if (typeof json !== "string" || Buffer.byteLength(json, "utf8") > maxLineBytes) {
336
- throw new AcpTransportError("line_too_large", "ACP outbound message exceeded the line limit.");
337
- }
338
- if (output.destroyed || output.writableEnded) {
339
- throw new AcpTransportError("transport_closed", "ACP stdin is closed.");
340
- }
341
- await new Promise((resolve, reject) => {
342
- output.write(`${json}\n`, (error) => error ? reject(error) : resolve(undefined));
343
- });
344
- },
345
- close() {
346
- if (!output.destroyed && !output.writableEnded) output.end();
347
- },
348
- abort() {
349
- output.destroy();
350
- },
351
- });
352
-
353
- return { readable, writable };
354
- }
355
-
356
- export const ACP_DEFAULT_MAX_LINE_BYTES = DEFAULT_MAX_LINE_BYTES;