@mono-agent/agent-runtime 0.4.0 → 0.4.1

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 (119) hide show
  1. package/ARCHITECTURE.md +37 -16
  2. package/MIGRATION.md +185 -7
  3. package/README.md +24 -14
  4. package/package.json +103 -10
  5. package/src/agent/allowlists.js +3 -0
  6. package/src/agent/approval.js +3 -0
  7. package/src/agent/compaction.js +244 -1
  8. package/src/agent/prompt/skill-index.js +6 -0
  9. package/src/agent/sandbox-seam.js +227 -0
  10. package/src/agent/tool-bloat.js +8 -2
  11. package/src/agent/tools/bash.js +16 -8
  12. package/src/agent/tools/edit.js +7 -3
  13. package/src/agent/tools/glob.js +11 -5
  14. package/src/agent/tools/grep.js +11 -5
  15. package/src/agent/tools/pi-bridge.js +227 -45
  16. package/src/agent/tools/read.js +28 -3
  17. package/src/agent/tools/shared/output-truncation.js +8 -3
  18. package/src/agent/tools/shared/path-resolver.js +24 -18
  19. package/src/agent/tools/shared/ripgrep.js +33 -6
  20. package/src/agent/tools/shared/runtime-context.js +60 -50
  21. package/src/agent/tools/shared/tool-context.js +157 -0
  22. package/src/agent/tools/web-fetch.js +21 -10
  23. package/src/agent/tools/web-search.js +11 -4
  24. package/src/agent/tools/write.js +7 -3
  25. package/src/agent/transcript.js +16 -1
  26. package/src/ai/cost.js +128 -3
  27. package/src/ai/failure.js +96 -4
  28. package/src/ai/live-input-prompt.js +11 -1
  29. package/src/ai/providers/claude-cli.js +2 -2
  30. package/src/ai/providers/claude-sdk.js +55 -12
  31. package/src/ai/providers/codex-app.js +36 -23
  32. package/src/ai/providers/opencode-app.js +2 -2
  33. package/src/ai/providers/opencode-discovery.js +2 -2
  34. package/src/ai/providers/pi-events.js +5 -0
  35. package/src/ai/providers/pi-models.js +21 -4
  36. package/src/ai/providers/pi-native/compaction-driver.js +394 -0
  37. package/src/ai/providers/pi-native/result-builder.js +312 -0
  38. package/src/ai/providers/pi-native/session-lifecycle.js +438 -0
  39. package/src/ai/providers/pi-native/stream-subscriber.js +148 -0
  40. package/src/ai/providers/pi-native/structured-output.js +130 -0
  41. package/src/ai/providers/pi-native/turn-runner.js +278 -0
  42. package/src/ai/providers/pi-native.js +415 -1106
  43. package/src/ai/runtime/model-refs.js +30 -0
  44. package/src/ai/runtime/registry.js +29 -0
  45. package/src/ai/runtime/router.js +96 -12
  46. package/src/ai/runtime/session-liveness.js +110 -0
  47. package/src/ai/runtime/sessions.js +16 -0
  48. package/src/ai/types.js +252 -19
  49. package/src/index.js +1 -1
  50. package/src/pi-auth.js +147 -16
  51. package/src/runtime-brand.js +21 -1
  52. package/src/runtime.js +72 -8
  53. package/types/agent/allowlists.d.ts +25 -0
  54. package/types/agent/approval.d.ts +30 -0
  55. package/types/agent/compaction.d.ts +97 -0
  56. package/types/agent/index.d.ts +5 -0
  57. package/types/agent/prompt/skill-index.d.ts +19 -0
  58. package/types/agent/sandbox-seam.d.ts +148 -0
  59. package/types/agent/tool-bloat.d.ts +22 -0
  60. package/types/agent/tools/bash.d.ts +16 -0
  61. package/types/agent/tools/edit.d.ts +14 -0
  62. package/types/agent/tools/glob.d.ts +16 -0
  63. package/types/agent/tools/grep.d.ts +22 -0
  64. package/types/agent/tools/index.d.ts +10 -0
  65. package/types/agent/tools/pi-bridge.d.ts +144 -0
  66. package/types/agent/tools/read.d.ts +19 -0
  67. package/types/agent/tools/shared/constants.d.ts +13 -0
  68. package/types/agent/tools/shared/dedup.d.ts +8 -0
  69. package/types/agent/tools/shared/output-truncation.d.ts +22 -0
  70. package/types/agent/tools/shared/path-resolver.d.ts +6 -0
  71. package/types/agent/tools/shared/ripgrep.d.ts +38 -0
  72. package/types/agent/tools/shared/runtime-context.d.ts +27 -0
  73. package/types/agent/tools/shared/tool-context.d.ts +48 -0
  74. package/types/agent/tools/web-fetch.d.ts +13 -0
  75. package/types/agent/tools/web-search.d.ts +11 -0
  76. package/types/agent/tools/write.d.ts +12 -0
  77. package/types/agent/transcript.d.ts +45 -0
  78. package/types/ai/backend.d.ts +41 -0
  79. package/types/ai/cost.d.ts +96 -0
  80. package/types/ai/failure.d.ts +117 -0
  81. package/types/ai/file-change-stats.d.ts +75 -0
  82. package/types/ai/index.d.ts +7 -0
  83. package/types/ai/live-input-prompt.d.ts +6 -0
  84. package/types/ai/observer.d.ts +68 -0
  85. package/types/ai/providers/claude-cli.d.ts +211 -0
  86. package/types/ai/providers/claude-sdk.d.ts +66 -0
  87. package/types/ai/providers/claude-subagents.d.ts +2 -0
  88. package/types/ai/providers/codex-app.d.ts +151 -0
  89. package/types/ai/providers/opencode-app.d.ts +95 -0
  90. package/types/ai/providers/opencode-discovery.d.ts +4 -0
  91. package/types/ai/providers/pi-errors.d.ts +3 -0
  92. package/types/ai/providers/pi-events.d.ts +24 -0
  93. package/types/ai/providers/pi-messages.d.ts +5 -0
  94. package/types/ai/providers/pi-models.d.ts +57 -0
  95. package/types/ai/providers/pi-native/compaction-driver.d.ts +86 -0
  96. package/types/ai/providers/pi-native/result-builder.d.ts +168 -0
  97. package/types/ai/providers/pi-native/session-lifecycle.d.ts +62 -0
  98. package/types/ai/providers/pi-native/stream-subscriber.d.ts +50 -0
  99. package/types/ai/providers/pi-native/structured-output.d.ts +69 -0
  100. package/types/ai/providers/pi-native/turn-runner.d.ts +60 -0
  101. package/types/ai/providers/pi-native.d.ts +18 -0
  102. package/types/ai/registry.d.ts +1 -0
  103. package/types/ai/runtime/capabilities-used.d.ts +21 -0
  104. package/types/ai/runtime/capabilities.d.ts +33 -0
  105. package/types/ai/runtime/context-windows.d.ts +8 -0
  106. package/types/ai/runtime/fast-mode.d.ts +2 -0
  107. package/types/ai/runtime/model-refs.d.ts +35 -0
  108. package/types/ai/runtime/registry.d.ts +38 -0
  109. package/types/ai/runtime/router.d.ts +56 -0
  110. package/types/ai/runtime/session-liveness.d.ts +55 -0
  111. package/types/ai/runtime/sessions.d.ts +38 -0
  112. package/types/ai/streaming/codex-events.d.ts +30 -0
  113. package/types/ai/streaming/opencode-events.d.ts +41 -0
  114. package/types/ai/types.d.ts +702 -0
  115. package/types/index.d.ts +7 -0
  116. package/types/pi-auth.d.ts +28 -0
  117. package/types/runtime-brand.d.ts +30 -0
  118. package/types/runtime.d.ts +10 -0
  119. package/src/ai/providers/pi-sdk.js +0 -35
@@ -0,0 +1,312 @@
1
+ // @ts-check
2
+ // Result assembly for the pi-native bridge.
3
+ //
4
+ // Pure moves out of pi-native.js: usage aggregation, the usage/cost/capabilities
5
+ // event emission, the failure-kind classifier, and the success / error / aborted
6
+ // result-object factories. No session or run state lives here — every builder
7
+ // takes its inputs explicitly and returns the verbatim runtime-result contract
8
+ // (diagnostics key spellings, error fields, and shape unchanged — I9).
9
+
10
+ import { isContextLimitError } from "../pi-errors.js";
11
+ import { isLikelyContextTermination } from "../../../agent/compaction.js";
12
+ import { isProviderAuthFailureText } from "../../failure.js";
13
+ import { structuredOutputRetryDiagnostics } from "./structured-output.js";
14
+
15
+ /**
16
+ * Sum assistant-message usage across a transcript slice.
17
+ * @param {Array<any>} [messages]
18
+ * @returns {{input: number, output: number, cacheRead: number, cacheWrite: number, cost: number}}
19
+ */
20
+ export function usageFromMessages(messages = []) {
21
+ const usage = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, cost: 0 };
22
+ for (const message of messages) {
23
+ if (message?.role !== "assistant") continue;
24
+ const next = message.usage || {};
25
+ usage.input += Number(next.input) || 0;
26
+ usage.output += Number(next.output) || 0;
27
+ usage.cacheRead += Number(next.cacheRead) || 0;
28
+ usage.cacheWrite += Number(next.cacheWrite) || 0;
29
+ usage.cost += Number(next.cost?.total) || 0;
30
+ }
31
+ return usage;
32
+ }
33
+
34
+ /**
35
+ * Classify a pi error message into a runtime failure kind. Context-limit /
36
+ * max-turns terminations map to usage_limit; credential/config auth failures
37
+ * map to provider_auth; everything else to provider_unavailable. Null message → null.
38
+ * @param {string|null} message
39
+ * @param {Record<string, unknown>} diagnostics
40
+ * @param {{maxTurnsHit?: boolean}} [opts]
41
+ * @returns {string|null}
42
+ */
43
+ export function failureKindForPiError(message, diagnostics, { maxTurnsHit = false } = {}) {
44
+ if (!message) return null;
45
+ if (maxTurnsHit || isContextLimitError(message) || isLikelyContextTermination(message, diagnostics)) {
46
+ return "usage_limit";
47
+ }
48
+ if (isProviderAuthFailureText(message)) return "provider_auth";
49
+ return "provider_unavailable";
50
+ }
51
+
52
+ /**
53
+ * Emit the per-run cache / cost / provider-completed events.
54
+ * @param {{onEvent: (event: any) => void, resolved: any, reference: string, usage: {input: number, output: number, cacheRead: number, cacheWrite: number, cost: number}, estimatedCost: number, start: number, externalAbort: boolean}} params
55
+ */
56
+ export function emitUsageCostEvents({ onEvent, resolved, reference, usage, estimatedCost, start, externalAbort }) {
57
+ if (usage.cacheRead > 0) {
58
+ onEvent({ type: "cache_hit", sdk: resolved.sdk, model: reference, tokens: usage.cacheRead, source: "prompt_cache" });
59
+ }
60
+ if (usage.cacheWrite > 0) {
61
+ onEvent({ type: "cache_miss", sdk: resolved.sdk, model: reference, tokens: usage.cacheWrite, source: "prompt_cache" });
62
+ }
63
+ onEvent({
64
+ type: "cost_accumulated",
65
+ sdk: resolved.sdk,
66
+ model: reference,
67
+ cumulativeUsd: Number(usage.cost) || Number(estimatedCost) || 0,
68
+ tokens: {
69
+ input: Number(usage.input) || 0,
70
+ output: Number(usage.output) || 0,
71
+ cacheReadTokens: Number(usage.cacheRead) || 0,
72
+ cacheCreationTokens: Number(usage.cacheWrite) || 0,
73
+ },
74
+ });
75
+ onEvent({
76
+ type: "provider_request_completed",
77
+ sdk: resolved.sdk,
78
+ model: reference,
79
+ runtime: "pi",
80
+ timestamp: Date.now(),
81
+ durationMs: Date.now() - start,
82
+ cancelled: externalAbort,
83
+ });
84
+ }
85
+
86
+ /**
87
+ * Emit the capabilities_resolved event.
88
+ * @param {(event: any) => void} onEvent
89
+ * @param {{sdk: string, model: string, capabilitiesUsed: any}} payload
90
+ */
91
+ export function emitCapabilitiesResolved(onEvent, { sdk, model, capabilitiesUsed }) {
92
+ onEvent({ type: "capabilities_resolved", sdk, model, capabilitiesUsed });
93
+ }
94
+
95
+ /**
96
+ * The aborted-run result (entry pre-check / pre-request abort). Pure factory.
97
+ * @param {{resolved: any, options: any, events: any[], runtimeWarnings: any[], start: number, providerSessionId: string}} params
98
+ */
99
+ export function abortedResult({ resolved, options, events, runtimeWarnings, start, providerSessionId }) {
100
+ return {
101
+ text: null,
102
+ thinking: "",
103
+ events,
104
+ usage: {},
105
+ durationMs: Date.now() - start,
106
+ numTurns: 0,
107
+ model: resolved?.reference || resolved?.model || null,
108
+ effort: options.effort || null,
109
+ sdk: resolved?.sdk || "pi",
110
+ cancelled: true,
111
+ error: null,
112
+ failureKind: null,
113
+ providerSessionId,
114
+ runtimeWarnings,
115
+ diagnostics: {
116
+ provider_session_id: providerSessionId,
117
+ pi_stop_reason: "aborted",
118
+ pi_engine: "native",
119
+ external_abort: true,
120
+ },
121
+ };
122
+ }
123
+
124
+ /**
125
+ * The verbatim success-path result object (also carries a run-level error when
126
+ * a turn ended in an error/max-turns/abort without throwing). Pure assembly.
127
+ * @param {object} params
128
+ */
129
+ export function buildSuccessResult(params) {
130
+ const {
131
+ finalText,
132
+ finalThinking,
133
+ events,
134
+ usage,
135
+ estimatedCost,
136
+ start,
137
+ turnCount,
138
+ runAssistantCount,
139
+ resolved,
140
+ options,
141
+ externalAbort,
142
+ errorMessage,
143
+ errorDetails,
144
+ diagnostics,
145
+ maxTurnsHit,
146
+ providerSessionId,
147
+ runtimeWarnings,
148
+ capabilitiesUsed,
149
+ structuredResult,
150
+ } = params;
151
+ return {
152
+ text: finalText,
153
+ thinking: finalThinking,
154
+ events,
155
+ usage: {
156
+ input_tokens: usage.input || null,
157
+ output_tokens: usage.output || null,
158
+ cache_read_tokens: usage.cacheRead || null,
159
+ cache_creation_tokens: usage.cacheWrite || null,
160
+ cache_write_tokens: usage.cacheWrite || null,
161
+ cost_usd: usage.cost || estimatedCost,
162
+ },
163
+ durationMs: Date.now() - start,
164
+ numTurns: turnCount || runAssistantCount,
165
+ model: resolved.reference || `pi:${resolved.provider}:${resolved.model}`,
166
+ effort: options.effort || null,
167
+ sdk: resolved.sdk,
168
+ cancelled: externalAbort,
169
+ error: errorMessage,
170
+ errorDetails,
171
+ failureKind: errorMessage
172
+ ? failureKindForPiError(errorMessage, diagnostics, { maxTurnsHit })
173
+ : null,
174
+ providerSessionId,
175
+ runtimeWarnings,
176
+ diagnostics,
177
+ capabilitiesUsed,
178
+ ...(structuredResult !== null && structuredResult !== undefined
179
+ ? { structuredResult, structuredResultSource: "StructuredOutput" }
180
+ : { structuredResult: undefined, structuredResultSource: null }),
181
+ };
182
+ }
183
+
184
+ /**
185
+ * The verbatim outer-catch error result. Pure assembly.
186
+ * @param {object} params
187
+ */
188
+ export function buildErrorResult(params) {
189
+ const {
190
+ assistantTexts,
191
+ events,
192
+ start,
193
+ turnCount,
194
+ resolved,
195
+ options,
196
+ externalAbort,
197
+ errorMessage,
198
+ lastToolName,
199
+ toolResultsSeen,
200
+ maxTurnsHit,
201
+ providerSessionId,
202
+ runtimeWarnings,
203
+ isRetryable,
204
+ } = params;
205
+ return {
206
+ text: assistantTexts.join("") || null,
207
+ events,
208
+ usage: {},
209
+ durationMs: Date.now() - start,
210
+ numTurns: turnCount,
211
+ model: resolved?.reference || resolved?.model || null,
212
+ effort: options.effort || null,
213
+ sdk: resolved?.sdk || "pi",
214
+ cancelled: externalAbort,
215
+ error: externalAbort ? null : errorMessage,
216
+ errorDetails: externalAbort ? null : {
217
+ pi_stop_reason: "error",
218
+ last_tool_name: lastToolName,
219
+ tool_results_seen: toolResultsSeen,
220
+ turn_count: turnCount,
221
+ max_turns_hit: maxTurnsHit,
222
+ provider_session_id: providerSessionId,
223
+ pi_engine: "native",
224
+ pi_error_retryable: isRetryable,
225
+ },
226
+ failureKind: externalAbort ? null : failureKindForPiError(errorMessage, {}, { maxTurnsHit }),
227
+ providerSessionId,
228
+ runtimeWarnings,
229
+ diagnostics: {
230
+ provider_session_id: providerSessionId,
231
+ pi_stop_reason: externalAbort ? "aborted" : "error",
232
+ pi_engine: "native",
233
+ max_turns_hit: maxTurnsHit,
234
+ turn_count: turnCount,
235
+ external_abort: externalAbort,
236
+ },
237
+ };
238
+ }
239
+
240
+ /**
241
+ * Assemble the success-path diagnostics object. Pure.
242
+ * @param {object} params
243
+ * @returns {Record<string, unknown>}
244
+ */
245
+ export function buildDiagnostics(params) {
246
+ const {
247
+ providerSessionId,
248
+ stopReason,
249
+ maxTurnsHit,
250
+ maxTurns,
251
+ turnCount,
252
+ runAssistantCount,
253
+ externalAbort,
254
+ maxRetries,
255
+ lastToolName,
256
+ structuredRetry,
257
+ contextCompactionDiagnostics,
258
+ } = params;
259
+ return {
260
+ provider_session_id: providerSessionId,
261
+ pi_stop_reason: stopReason,
262
+ pi_engine: "native",
263
+ max_turns_hit: maxTurnsHit,
264
+ max_turns: Number.isFinite(Number(maxTurns)) ? Number(maxTurns) : null,
265
+ turn_count: turnCount || runAssistantCount,
266
+ external_abort: externalAbort,
267
+ pi_max_retries: maxRetries,
268
+ ...(lastToolName ? { last_tool_name: lastToolName } : {}),
269
+ ...structuredOutputRetryDiagnostics(
270
+ structuredRetry.attempts,
271
+ structuredRetry.reason,
272
+ structuredRetry.failed,
273
+ ),
274
+ ...contextCompactionDiagnostics,
275
+ };
276
+ }
277
+
278
+ /**
279
+ * Assemble the success-path errorDetails object (or null when no error). Pure.
280
+ * @param {object} params
281
+ * @returns {Record<string, unknown>|null}
282
+ */
283
+ export function buildErrorDetails(params) {
284
+ const {
285
+ errorMessage,
286
+ stopReason,
287
+ lastToolName,
288
+ toolResultsSeen,
289
+ turnCount,
290
+ runAssistantCount,
291
+ maxTurnsHit,
292
+ providerSessionId,
293
+ structuredRetry,
294
+ contextCompactionDiagnostics,
295
+ } = params;
296
+ if (!errorMessage) return null;
297
+ return {
298
+ pi_stop_reason: stopReason || "error",
299
+ last_tool_name: lastToolName,
300
+ tool_results_seen: toolResultsSeen,
301
+ turn_count: turnCount || runAssistantCount,
302
+ max_turns_hit: maxTurnsHit,
303
+ provider_session_id: providerSessionId,
304
+ pi_engine: "native",
305
+ ...structuredOutputRetryDiagnostics(
306
+ structuredRetry.attempts,
307
+ structuredRetry.reason,
308
+ structuredRetry.failed,
309
+ ),
310
+ ...contextCompactionDiagnostics,
311
+ };
312
+ }