@mono-agent/agent-runtime 0.4.0 → 0.5.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 (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
package/ARCHITECTURE.md CHANGED
@@ -9,13 +9,18 @@ agent turn:
9
9
 
10
10
  - pick the right backend from a model reference and execution mode
11
11
  - expose built-in tools, MCP tools, approvals, structured output, and live input
12
- - enforce optional sandbox policy for built-in tool execution and stdio MCP startup
12
+ - enforce an optional sandbox policy for built-in tool execution and stdio MCP
13
+ startup, through an injectable seam (see `agent/sandbox-seam.js`) rather than
14
+ a bundled sandboxing implementation
13
15
  - normalize provider events into one runtime event stream
14
16
  - classify runtime failures and retryable provider errors
15
17
  - collect usage, cost, cache, capability, and warning telemetry
16
18
  - return raw text plus raw structured output to the host
17
19
 
18
- Hosts consume the package through `src/runtime.js`.
20
+ Hosts consume the package through `src/runtime.js`. The package has **zero
21
+ workspace-package dependencies**: everything a host-side integration would
22
+ otherwise need to inject (sandboxing, in this package's case) is expressed as
23
+ a plain-data/plain-function seam the host wires up, not an import.
19
24
 
20
25
  ## Package Boundary
21
26
 
@@ -135,11 +140,12 @@ flowchart TB
135
140
 
136
141
  Providers --> Claude["claude-sdk.js"]
137
142
  Providers --> ClaudeCode["claude-cli.js"]
138
- Providers --> Pi["pi-sdk.js<br/>pi-models/messages/events"]
143
+ Providers --> Pi["pi-native.js<br/>pi-models/messages/events"]
139
144
  Providers --> Codex["codex-app.js"]
140
145
 
141
146
  AgentExports --> Tools["agent/tools/*"]
142
- Tools --> ToolRuntime["shared/runtime-context.js<br/>workspace, repoRoot, rg, brand"]
147
+ Tools --> ToolContext["shared/tool-context.js<br/>per-instance ToolContext<br/>workspace, repoRoot, rg, sandbox, brand"]
148
+ ToolContext --> ToolRuntime["shared/runtime-context.js<br/>back-compat DEFAULT context<br/>(module-level singleton wrapping tool-context.js)"]
143
149
  Tools --> PiBridge["tools/pi-bridge.js<br/>built-ins + MCP adaptation"]
144
150
 
145
151
  AgentExports --> Compaction["agent/compaction.js"]
@@ -155,8 +161,9 @@ flowchart TB
155
161
 
156
162
  Key responsibilities by subsystem:
157
163
 
158
- - `runtime.js`: binds host callbacks once, configures tool runtime context, and
159
- routes each call to the resolved bridge.
164
+ - `runtime.js`: binds host callbacks once, builds a per-instance `ToolContext`
165
+ (`agent/tools/shared/tool-context.js`) threaded to every bridge call via
166
+ `options.toolContext`, and routes each call to the resolved bridge.
160
167
  - `ai/runtime/registry.js`: maps model reference plus execution mode to one of
161
168
  the built-in provider bridges.
162
169
  - `ai/runtime/router.js`: retries across an ordered fallback chain on retryable
@@ -166,12 +173,22 @@ Key responsibilities by subsystem:
166
173
  - `agent/tools/*`: implements built-in tools, path/workdir guards, sandbox
167
174
  policy checks, MCP tool adaptation, Playwright artifact routing, and output
168
175
  limits.
169
- - `agent/compaction.js`: two pure helpers consumed by the pi bridge —
176
+ - `agent/sandbox-seam.js`: the injectable `RuntimeSandbox` interface (policy
177
+ merge, command preparation, network-allow checks) and its zero-dependency
178
+ `passthroughSandbox` default (no policy configured → unsandboxed, exactly as
179
+ before; a policy configured with no implementation injected → fails closed).
180
+ Real hosts inject `@mono-agent/runtime-adapter`'s sandbox implementation.
181
+ - `agent/compaction.js`: pure helpers consumed by the pi bridge —
170
182
  `resolveAgentCompactionPolicy` (derives the context-window compaction trigger +
171
183
  tool-output payload limits from `agent_compaction_*` settings and the running
172
- model) and `isLikelyContextTermination` (classifies a context-pressure error).
173
- The bridge drives compaction itself via `AgentHarness.compact()` (proactive +
174
- reactive recovery); the legacy in-loop `transformContext` manager was removed.
184
+ model), `estimateFixedOverheadTokens` (the proactive fixed-overhead correction:
185
+ system prompt + tool schemas + per-turn message), `isLikelyContextTermination`
186
+ (classifies a context-pressure error), and the typed-policy/`settings`-bag shim
187
+ helpers (`resolveRuntimePolicyInputs`, `deprecatedSettingsWarning`) that let a
188
+ present `toolLimits`/`compaction` object win wholesale per-group over the
189
+ deprecated flat `settings` bag (MIGRATION.md §8). The bridge drives compaction
190
+ itself via `AgentHarness.compact()` (proactive + reactive recovery); the legacy
191
+ in-loop `transformContext` manager was removed.
175
192
  - `agent/transcript.js`: builds bounded resume snapshots from prior provider
176
193
  events so a fallback or continuation can keep context.
177
194
  - `agent/approval.js`: provides host-driven human-in-the-loop tool approval
@@ -208,8 +225,9 @@ The host is responsible for:
208
225
  - resolving credentials and custom provider/model rows before provider calls
209
226
  - choosing model references, execution mode, effort, fallback chains, and
210
227
  runtime settings
211
- - persisting artifacts, raw logs, run rows, and UI-facing state (the legacy
212
- compaction-row hook is inert on the current pi bridge)
228
+ - persisting artifacts, raw logs, run rows, and UI-facing state (via the
229
+ `onCompactionRecorded` hook, which fires on every automatic compaction
230
+ proactive or reactive — the pi bridge drives)
213
231
  - validating structured output against the host's domain contract
214
232
  - converting runtime failures into product workflow behavior
215
233
  - deciding when to retry, recover, continue, cancel, or ask for user input
@@ -236,10 +254,13 @@ provider exposes queue-after-turn), not durability/cost:
236
254
 
237
255
  The pi runtime is built on pi-agent-core's native `AgentHarness` (the hand-rolled
238
256
  bridge was removed once native reached parity); it owns the session and
239
- pi-ai-managed retry, and context/window handling is delegated to the harness.
240
- There is **no** automatic in-loop summarization pass driven by this package, so
241
- runs report `context_compaction_applied: null` (unknown/unsupported) rather than
242
- asserting compaction ran.
257
+ pi-ai-managed retry. `AgentHarness` itself has **no** automatic compaction, so
258
+ the pi bridge drives it directly: before each turn it estimates the running
259
+ model's context usage and calls `AgentHarness.compact()` when near the window
260
+ (proactive), and if a turn still overflows it compacts once and re-prompts
261
+ (reactive recovery). Runs report `context_compaction_applied` as `true` (a
262
+ compaction fired), `false` (enabled but not needed), or `null` (disabled via
263
+ `agent_compaction_enabled: false`).
243
264
 
244
265
  | Provider | Warm session | Resume across turns | Survives process restart |
245
266
  |---|---|---|---|
package/MIGRATION.md CHANGED
@@ -22,13 +22,14 @@ registry resolves `pi` → the native bridge unconditionally; there is no
22
22
 
23
23
  - **Public runtime API** (`createRuntime`, model reference `"pi:<provider>:<model>"`)
24
24
  is unchanged — `pi:openai:gpt-5.5` etc. still work.
25
- - **Deep imports** of `@mono-agent/agent-runtime/ai/providers/pi-sdk.js` still
26
- resolve via a **deprecated compatibility shim** that re-exports the native
27
- equivalents (`generatePiResponse` `generatePiNativeResponse`,
28
- `piRuntimeBridge` `piNativeRuntimeBridge`, `isContextLimitError`,
29
- `normalizePiErrorMessage`, and the `pi*Backend` symbols). **Action:** migrate
30
- deep imports to `./ai/providers/pi-native.js`; the shim may be removed in a
31
- future major.
25
+ - **Deep imports** of `@mono-agent/agent-runtime/ai/providers/pi-sdk.js` **no
26
+ longer resolve**: the deprecated compatibility shim was removed and, with the
27
+ Phase-6 explicit `exports` map (no `./ai/*` / `./agent/*` wildcards), that
28
+ subpath is not exported. **Action:** import `generatePiNativeResponse` /
29
+ `piNativeRuntimeBridge` from `./ai`, and
30
+ `isContextLimitError` / `normalizePiErrorMessage` from `./ai/providers/pi-errors.js`
31
+ (or reach for the public runtime registry). The `pi*Backend` aliases are gone —
32
+ all Pi routes through the one native bridge.
32
33
 
33
34
  ## 2. Removed run options: `piReasoningSummary`, `piCodexTransport`
34
35
 
@@ -105,6 +106,126 @@ run reports exhausted instead of degrading silently.
105
106
  resumed sessions roll back to their pre-turn leaf on host-side (outer-catch)
106
107
  failures. These are correctness fixes with no API surface change.
107
108
 
109
+ ## 7. Sandbox enforcement is now an injectable seam (agent-runtime has zero workspace-package dependencies)
110
+
111
+ `@mono-agent/agent-runtime` does not depend on `@mono-agent/runtime-adapter`. Sandbox
112
+ enforcement (command sandboxing, network-policy checks, and monotonic policy
113
+ merging) is now driven through an injectable `RuntimeSandbox` seam
114
+ (`agent/sandbox-seam.js`): `createRuntime({sandbox})` / `createRouterRuntime({host: {sandbox}})`
115
+ accept an implementation. `@mono-agent/runtime-adapter` injects the real
116
+ sandbox implementation automatically for every
117
+ `createMonoRuntime(...)` call, so behavior is **byte-identical** for existing
118
+ mono-agent hosts — no action needed if you build your runtime through
119
+ `@mono-agent/runtime-adapter`.
120
+
121
+ - **No sandbox policy configured, no implementation injected:** unchanged —
122
+ every tool runs unsandboxed, exactly as before.
123
+ - **A sandbox policy IS configured, but no `RuntimeSandbox` implementation is
124
+ injected** (only possible if you call `@mono-agent/agent-runtime`'s
125
+ `createRuntime` directly, bypassing `@mono-agent/runtime-adapter`): **this
126
+ now fails closed** with a `sandbox_unavailable` error instead of silently
127
+ running the command unsandboxed. Previously `@mono-agent/agent-runtime`
128
+ always bundled the real sandbox implementation and always enforced the policy; a
129
+ host that built on `createRuntime` directly and relied on that implicit
130
+ availability must now also inject a `RuntimeSandbox` implementation (the
131
+ real one from `@mono-agent/runtime-adapter`, or a custom one) to keep policies
132
+ enforced. **Action:** if you configure `sandboxPolicy` and call
133
+ `createRuntime`/`createRouterRuntime` directly instead of going through
134
+ `@mono-agent/runtime-adapter`, also pass a `sandbox` implementation, or drop
135
+ the policy.
136
+
137
+ ## 8. Typed run options replace the `settings` bag (`toolLimits` / `compaction` / `prompts`)
138
+
139
+ The flat `options.settings` bag is **deprecated** as the way to configure
140
+ tool-output clamps and context compaction. The supported replacements are typed,
141
+ per-run objects on `RuntimeRunOptions`:
142
+
143
+ - **`options.toolLimits`** (`RuntimeToolLimits`) — `toolTextLimitChars`,
144
+ `bashOutputLimitChars`, `mcpTextLimitChars`, `searchResultLimit`,
145
+ `imageInlineMaxBytes`, `toolPayloadMaxBytes`, `mcpCallTimeoutMs`,
146
+ `mcpCallMaxTotalTimeoutMs`, `bashTimeoutMs`.
147
+ - **`options.compaction`** (`RuntimeCompactionPolicy`) — `enabled`,
148
+ `triggerRatio`, `keepRecentTokens`, `summaryMaxTokens`, `minSavingsTokens`,
149
+ `fixedOverheadEnabled`, `contextWindowOverride`.
150
+
151
+ Precedence is **per-group**: a present typed object wins wholesale for its group
152
+ and that group's legacy `settings` keys are ignored; an absent typed object lets
153
+ its group's `settings` keys through as a fallback. Consuming **any** legacy
154
+ `settings` key emits exactly one `runtime_warning` with
155
+ **`warning_kind: "deprecated_settings_option"`** per run (listing the consumed
156
+ keys). Passing no `settings` — or an empty/irrelevant bag — never warns, so a host
157
+ that never passed `settings` is byte-for-byte unchanged (mono-agent hosts do not
158
+ pass it, so this is a no-op there).
159
+
160
+ `resolveAgentCompactionPolicy(settings, model)` stays exported (the canonical
161
+ clamp/mapper both paths route through), and `@mono-agent/runtime-adapter` exposes
162
+ `resolveRuntimePolicies(settings)` to map a legacy bag to the typed objects.
163
+ **Action:** migrate `settings` → `toolLimits` / `compaction`; until then the shim
164
+ keeps working with one deprecation warning per run.
165
+
166
+ ## 9. New per-run overrides: `sandbox`, `sandboxPolicy`, `prompts`
167
+
168
+ Beyond `toolLimits` / `compaction`, `RuntimeRunOptions` gained:
169
+
170
+ - **`sandbox`** — a per-run `RuntimeSandbox` implementation override. Precedence
171
+ is run > host > passthrough; it overrides only the *enforcing code*, while the
172
+ policy **data** still merges monotonically (I13, section 7).
173
+ - **`sandboxPolicy`** — per-run policy data, merged monotonically with the host
174
+ policy (it can **tighten**, never weaken or disable).
175
+ - **`prompts`** (`RuntimePromptOverrides`) — per-run overrides of the kernel's
176
+ built-in prompt fragments: `structuredOutputInstruction(systemPrompt)`,
177
+ `structuredOutputFinalization()`, `liveInputGuidance(body)`. Run wins over the
178
+ host-level `prompts` default; an absent field keeps the built-in string
179
+ (byte-identical default). These are also accepted on `AgentRuntimeHostOptions`
180
+ as the host-level default.
181
+
182
+ ## 10. Pi 0.80 auth: `Models` credential store (`resolvePiApiKey` semantics preserved)
183
+
184
+ Pi 0.80 removed the harness `getApiKeyAndHeaders` hook; request auth now resolves
185
+ through a `Models` collection's `CredentialStore`. The bridge's **per-run
186
+ key-resolution contract is unchanged**: an `apiKeys` map entry wins, else the host
187
+ `resolvePiApiKey(provider)` callback is consulted; a callback failure emits a
188
+ `pi_auth_failed` runtime warning and proceeds keyless (a builtin provider then
189
+ falls back to its own env vars, exactly as returning `undefined` from the old hook
190
+ did). **No host action needed** — `resolvePiApiKey` behaves as before.
191
+
192
+ Dependency bump: **`@earendil-works/pi-ai` and `@earendil-works/pi-agent-core` are
193
+ now `^0.80.x`** (were `^0.79.1`). Compaction is driven natively (section 3).
194
+
195
+ ## 11. Exports map: wildcards removed (explicit deep-path map)
196
+
197
+ The package's `./ai/*` and `./agent/*` **wildcard exports were replaced by an
198
+ explicit `exports` map**: 3 barrels (`.`, `./ai`, `./agent`) plus **21 named deep
199
+ `.js` subpaths**, each carrying its own generated `types` condition. A deep import
200
+ that is not on the map **no longer resolves** — a wildcard used to silently
201
+ resolve anything under `src/`, so a moved/renamed/mistyped subpath is now a loud
202
+ failure (guarded by `scripts/verify-deep-imports.mjs`).
203
+
204
+ The 21 supported deep paths:
205
+
206
+ ```
207
+ ./ai/failure.js ./agent/tools/index.js
208
+ ./ai/cost.js ./agent/tools/shared/runtime-context.js
209
+ ./ai/backend.js ./agent/tools/shared/ripgrep.js
210
+ ./ai/runtime/model-refs.js ./agent/prompt/skill-index.js
211
+ ./ai/runtime/registry.js ./agent/allowlists.js
212
+ ./ai/runtime/context-windows.js ./agent/transcript.js
213
+ ./ai/runtime/fast-mode.js ./agent/compaction.js
214
+ ./ai/streaming/codex-events.js
215
+ ./ai/live-input-prompt.js
216
+ ./ai/file-change-stats.js
217
+ ./ai/providers/claude-sdk.js
218
+ ./ai/providers/claude-cli.js
219
+ ./ai/providers/codex-app.js
220
+ ./ai/providers/opencode-discovery.js
221
+ ```
222
+
223
+ **Action:** if you deep-import a subpath not in this list, switch to the closest
224
+ supported one, a barrel (`./ai` / `./agent`), or the public runtime registry.
225
+ `pi-sdk.js` is gone and remains intentionally unexported (section 1). Worklab
226
+ ports should import `generatePiNativeResponse` from `@mono-agent/agent-runtime/ai`
227
+ instead of adding a `pi-sdk.js` compatibility subpath.
228
+
108
229
  ---
109
230
 
110
231
  ## Version
@@ -113,3 +234,60 @@ These changes ship in the first `agent-runtime` release after `0.3.0` on the
113
234
  `feat/runtime-live-sessions` line (a minor/major bump; see the release tag). The
114
235
  paired `@mono-agent/runtime-adapter` drops the `piReasoningSummary` field from its
115
236
  run-options type in lockstep.
237
+
238
+ ---
239
+
240
+ ## Appendix — Porting this kernel to a new scope/host (worklab port-readiness)
241
+
242
+ This kernel is designed to be vendored into a differently-scoped host (the
243
+ concrete target is **worklab**, `@worklab-ai/agent-runtime`, GPL-3.0-only, npm
244
+ workspaces, pure-JS no-build, consuming this package's raw `src/`). The port
245
+ itself is a follow-up; this is the executable checklist, with the port-readiness
246
+ dry-run results recorded inline (verified against the worklab tree read-only).
247
+
248
+ Run these before/at the port:
249
+
250
+ 1. **Scope rename `@mono-agent/` → `@worklab-ai/`.** Touches `package.json`
251
+ (`name` + the package-name prefix inside each `exports` key's consumer
252
+ specifier) only — the kernel's own source uses **relative** imports, so no
253
+ source import references the scope. *(Verified: zero `@mono-agent/*` specifiers
254
+ in `src/`.)*
255
+ 2. **Dependencies.** Post-decoupling the kernel has **zero workspace-package
256
+ deps**; only the third-party pins need aligning: `@earendil-works/pi-ai` +
257
+ `@earendil-works/pi-agent-core` (`^0.80.x`), `@modelcontextprotocol/sdk`,
258
+ `@opencode-ai/sdk`, `@anthropic-ai/claude-agent-sdk`, `zod`.
259
+ 3. **Pi bump `^0.74.0` → `^0.80.x` in lockstep.** worklab tests that use old pi
260
+ APIs are rewritten at the port. Do not restore the old `pi-sdk.js` deep
261
+ import; use `generatePiNativeResponse` from `@mono-agent/agent-runtime/ai`.
262
+ 4. **Sandbox.** worklab passes **no** `sandbox` implementation → `passthroughSandbox`,
263
+ and **never sets `sandboxPolicy`** *(verified: zero `sandboxPolicy` /
264
+ `sandbox:` in worklab `src/`)*, so with no policy every tool runs unsandboxed
265
+ exactly as today — behavior is byte-identical. (If worklab later adds a policy,
266
+ it must also inject a `RuntimeSandbox` impl — section 7's fail-closed rule.)
267
+ 5. **License / packaging.** GPL-3.0-only stays; `files` includes `types/`
268
+ (additive — worklab consumes raw `src/`, `.d.ts` generation is optional).
269
+ 6. **Deep imports resolve.** `node scripts/verify-deep-imports.mjs` (default +
270
+ types conditions) is green. Every worklab **non-test** deep import resolves in
271
+ the explicit exports map *(verified — no gap)*, and the Worklab-test provider
272
+ bridge imports for `claude-sdk.js`, `claude-cli.js`, and `codex-app.js` are
273
+ supported as exported subpaths. The only worklab deep import NOT in the map is
274
+ the removed **test-only** `pi-sdk.js`; those tests are rewritten at the port
275
+ (step 3), so no export entry is added for it.
276
+ 7. **Contract supersets.** `HOST_KEYS` ⊇ worklab's host bag *(verified:
277
+ worklab passes `resolveCustomPricing`, `onCompactionRecorded`, `persistArtifact`,
278
+ `resolvePiApiKey`, `observers` — all covered)*; the deep-import
279
+ `configureToolRuntime` accepts worklab's keys *(verified: `workspace`,
280
+ `repoRoot`, `runId`, `toolArtifactDir`, `ripgrepPath`, `qaOutputDir` ⊂
281
+ `TOOL_CONTEXT_KEYS`)*; and every `RuntimeResult` field worklab's
282
+ `worker/agent-turn.js` reads exists on the result *(verified: `cancelled`,
283
+ `providerSessionId`, `error`, `failureKind`, `errorDetails`, `diagnostics`,
284
+ `runtimeWarnings`, plus `text`/`usage`/`model`/`effort`/`numTurns`/
285
+ `structuredResult`/`capabilitiesUsed`/`durationMs`/`failoverHistory`;
286
+ `observerSnapshot` is worklab-side, folded from its own metrics observer)*.
287
+ 8. **`options.settings` day one.** Works via the deprecated shim (section 8) with
288
+ one `deprecated_settings_option` warning per run; worklab later maps
289
+ `settings` → the typed policy objects in its `core/ai.js`.
290
+ 9. **Test layout + no-build consumption.** `src/__tests__` + vitest already match;
291
+ the package is fully consumable from raw `src/` with **no build**
292
+ *(verified: a smoke import of `createRuntime` / `createRouterRuntime` from
293
+ `src/index.js` constructs a runtime with no model call)*.
package/README.md CHANGED
@@ -6,7 +6,7 @@ Category: `runtime`
6
6
 
7
7
  ## Responsibility
8
8
 
9
- Provides the multi-backend agent runtime bridges (Claude SDK, Claude Code CLI, Codex app-server, Pi SDK) with provider session support. This is the runtime layer that `@mono-agent/runtime-adapter` wraps behind runtime contracts, and it enforces optional `@mono-agent/sandbox` policy for runtime-owned tools.
9
+ Provides the multi-backend agent runtime bridges (Claude SDK, Claude Code CLI, Codex app-server, Pi SDK) with provider session support. This is the runtime layer that `@mono-agent/runtime-adapter` wraps behind runtime contracts, and it enforces an optional sandbox policy for runtime-owned tools through an injectable `RuntimeSandbox` seam (a fail-closed passthrough by default; `@mono-agent/runtime-adapter` injects the real sandbox implementation for mono-agent hosts).
10
10
 
11
11
  ## Public API
12
12
 
@@ -15,17 +15,17 @@ Provides the multi-backend agent runtime bridges (Claude SDK, Claude Code CLI, C
15
15
  - `ai/runtime/registry.js` — `listRuntimeBridges`
16
16
  - Provider bridges for `claude` (SDK + CLI), `codex` (app-server), `pi` (Pi SDK), and `opencode`
17
17
  - Provider session support: bridges accept `sessionId` in run options and report `provider_session_id`; the runtime exposes `disposeSession` / `disposeAllSessions`
18
- - Sandbox-aware built-in tools and stdio MCP startup through `@mono-agent/sandbox`
18
+ - Sandbox-aware built-in tools and stdio MCP startup through an injectable `RuntimeSandbox` seam (`agent/sandbox-seam.js`) — no direct dependency on `@mono-agent/runtime-adapter`
19
19
 
20
20
  ## Dependency Boundary
21
21
 
22
- Depends on external provider SDKs (`@anthropic-ai/claude-agent-sdk`, `@earendil-works/pi-agent-core`, `@earendil-works/pi-ai`, `@modelcontextprotocol/sdk`, `@opencode-ai/sdk`, `zod`) plus `@mono-agent/sandbox` for runtime-owned command preparation and network/path policy checks.
22
+ Depends on external provider SDKs only (`@anthropic-ai/claude-agent-sdk`, `@earendil-works/pi-agent-core`, `@earendil-works/pi-ai`, `@modelcontextprotocol/sdk`, `@opencode-ai/sdk`, `zod`) **zero `@mono-agent/*` workspace-package dependencies**. Sandbox enforcement for runtime-owned command preparation and network/path policy checks is an injectable `RuntimeSandbox` seam; `@mono-agent/runtime-adapter` wires in the real sandbox implementation automatically for mono-agent hosts.
23
23
 
24
24
  ## What This Package Does Not Own
25
25
 
26
26
  - runtime contracts and backend descriptors (`@mono-agent/runtime-adapter`)
27
27
  - Conversation history, context building, or host-side session TTL policy (`@mono-agent/agent-harness`)
28
- - Host configuration (`@mono-agent/config`, `@mono-agent/agent-host`)
28
+ - Host configuration (`@mono-agent/config`, `@mono-agent/agent-app`)
29
29
 
30
30
  ## Verification
31
31
 
@@ -42,7 +42,7 @@ Generic agent runtime that supports four backends out of the box:
42
42
  - **Pi SDK** (`@earendil-works/pi-agent-core`, used for OpenAI / Codex / Gemini / OpenRouter / Ollama / etc. via Pi providers)
43
43
  - **Codex CLI** (the `codex` app-server)
44
44
 
45
- Hosts wire in their own pricing, persistence, and credential callbacks (plus a legacy compaction-recording hook that is inert on the current pi bridge see "Context compaction"). The runtime returns raw text + raw structured output; hosts that want a domain-specific contract parse it on their end.
45
+ Hosts wire in their own pricing, persistence, and credential callbacks (plus an `onCompactionRecorded` hook that fires on every automatic compaction — proactive or reactive — the pi bridge drives; see "Context compaction"). The runtime returns raw text + raw structured output; hosts that want a domain-specific contract parse it on their end.
46
46
 
47
47
  See [ARCHITECTURE.md](./ARCHITECTURE.md) for the package boundary, runtime
48
48
  selection flow, lifecycle diagrams, and host responsibilities. Upgrading from
@@ -153,7 +153,11 @@ createRuntime({
153
153
  repoRoot, // secondary allowed root
154
154
  ripgrepPath, // explicit path to `rg`; falls back to vendored binary, then PATH
155
155
  qaOutputDir, // fallback dir for Playwright MCP filename routing
156
- sandboxPolicy, // optional @mono-agent/sandbox policy for tools and stdio MCP
156
+ sandboxPolicy, // optional SandboxPolicy for tools and stdio MCP (enforced
157
+ // through the injectable RuntimeSandbox seam, not a bundled dep)
158
+ sandbox, // optional RuntimeSandbox implementation override (defaults to
159
+ // the zero-dependency passthroughSandbox; runtime-adapter injects
160
+ // the real runtime-adapter sandbox implementation for mono-agent hosts)
157
161
 
158
162
  // -- observers (multi-subscriber telemetry) --
159
163
  // Optional. Each observer receives every event the runtime emits.
@@ -315,8 +319,9 @@ console.log(result.failoverHistory);
315
319
  Behaviour:
316
320
 
317
321
  - Successful run on entry N → returns the result with `failoverHistory` set to attempts 0..N-1.
318
- - Retryable failure → emits `provider_failover_started`, builds a transcript snapshot, and retries on the next entry.
319
- - Non-retryable failure (auth, billing, invalid request) returns immediately with `failoverHistory` containing the one attempt.
322
+ - Retryable provider failure → emits `provider_failover_started`, builds a transcript snapshot, and retries on the next entry.
323
+ - Provider auth failure retries the next chain entry and preserves `failureKind: "provider_auth"` in `failoverHistory` for the failed attempt.
324
+ - Malformed request/config/billing-type non-retryable failure → returns immediately with `failoverHistory` containing the one attempt.
320
325
  - Cancellation → returns immediately.
321
326
  - Chain exhausted → `failureKind: "provider_unavailable_exhausted"`, `failoverHistory` lists every attempt.
322
327
 
@@ -398,7 +403,7 @@ Approval lifecycle is observable via `onEvent`:
398
403
 
399
404
  ## Tool-result bloat handling
400
405
 
401
- `@mono-agent/agent-runtime/agent/tool-bloat.js` enforces a 256 KB default cap per `tool_result`. When a payload exceeds the cap, the kernel:
406
+ The kernel's tool-bloat guard (`agent/tool-bloat.js`, internal) enforces a 256 KB default cap per `tool_result`. When a payload exceeds the cap, the kernel:
402
407
 
403
408
  1. Calls your `persistArtifact({ filename, buffer, toolName, toolUseId })` callback (if you supplied one).
404
409
  2. Substitutes a compact text reference in the agent's transcript.
@@ -416,7 +421,7 @@ recovery). The context window auto-tracks the model actually serving the request
416
421
  (`harness.getModel()`), self-correcting from any real ceiling stated in an overflow error.
417
422
  Runs report `context_compaction_applied: true` (fired), `false` (enabled but not needed),
418
423
  or `null` (disabled). The other backends manage their windows per their own behavior.
419
- (`docs/feature-registry.md` is the source of truth for this row.)
424
+ (`docs/reference/feature-registry.md` is the source of truth for this row.)
420
425
 
421
426
  `resolveAgentCompactionPolicy(...)` (the `agent_compaction_*` settings: trigger ratio,
422
427
  keep-recent, enable/disable) and the `onCompactionRecorded(record)` host callback (fired
@@ -425,14 +430,19 @@ on each automatic compaction) are exported from
425
430
 
426
431
  ## Advanced exports
427
432
 
428
- The package exposes its inner pieces via subpath imports:
433
+ The package exposes a fixed set of inner pieces via subpath imports. The
434
+ `exports` map is explicit (no `./ai/*` / `./agent/*` wildcards): only the mapped
435
+ subpaths resolve, each carrying generated `.d.ts` types. `node
436
+ scripts/verify-deep-imports.mjs` asserts every mapped subpath still loads.
429
437
 
430
438
  ```js
431
- import { resolveRuntimeBridge, listRuntimeBridges, runtimeCapabilities } from "@mono-agent/agent-runtime/ai/runtime/registry.js";
432
- import { generateClaudeResponse } from "@mono-agent/agent-runtime/ai/providers/claude-sdk.js";
439
+ import { resolveRuntimeBridge, listRuntimeBridges } from "@mono-agent/agent-runtime/ai/runtime/registry.js";
440
+ import { parseRuntimeModelReference } from "@mono-agent/agent-runtime/ai/runtime/model-refs.js";
441
+ import { classifyFailure, FAILURE_KINDS } from "@mono-agent/agent-runtime/ai/failure.js";
442
+ import { resolvePricing, estimateCost } from "@mono-agent/agent-runtime/ai/cost.js";
433
443
  import { resolveAgentCompactionPolicy, isLikelyContextTermination } from "@mono-agent/agent-runtime/agent/compaction.js";
434
444
  import { configureToolRuntime, readToolRuntime } from "@mono-agent/agent-runtime/agent/tools/shared/runtime-context.js";
435
- // ...
445
+ // see package.json "exports" for the full mapped set
436
446
  ```
437
447
 
438
448
  These are stable but treated as advanced API. Most consumers should reach for `createRuntime` first.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mono-agent/agent-runtime",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "Agent runtime supporting Claude SDK, Claude CLI, Codex CLI, and PI SDK out of the box",
5
5
  "type": "module",
6
6
  "license": "GPL-3.0-only",
@@ -14,16 +14,109 @@
14
14
  "access": "public"
15
15
  },
16
16
  "exports": {
17
- ".": "./src/index.js",
18
- "./ai": "./src/ai/index.js",
19
- "./agent": "./src/agent/index.js",
20
- "./ai/*": "./src/ai/*",
21
- "./agent/*": "./src/agent/*"
17
+ ".": {
18
+ "types": "./types/index.d.ts",
19
+ "default": "./src/index.js"
20
+ },
21
+ "./ai": {
22
+ "types": "./types/ai/index.d.ts",
23
+ "default": "./src/ai/index.js"
24
+ },
25
+ "./agent": {
26
+ "types": "./types/agent/index.d.ts",
27
+ "default": "./src/agent/index.js"
28
+ },
29
+ "./ai/failure.js": {
30
+ "types": "./types/ai/failure.d.ts",
31
+ "default": "./src/ai/failure.js"
32
+ },
33
+ "./ai/cost.js": {
34
+ "types": "./types/ai/cost.d.ts",
35
+ "default": "./src/ai/cost.js"
36
+ },
37
+ "./ai/backend.js": {
38
+ "types": "./types/ai/backend.d.ts",
39
+ "default": "./src/ai/backend.js"
40
+ },
41
+ "./ai/runtime/model-refs.js": {
42
+ "types": "./types/ai/runtime/model-refs.d.ts",
43
+ "default": "./src/ai/runtime/model-refs.js"
44
+ },
45
+ "./ai/runtime/registry.js": {
46
+ "types": "./types/ai/runtime/registry.d.ts",
47
+ "default": "./src/ai/runtime/registry.js"
48
+ },
49
+ "./ai/runtime/context-windows.js": {
50
+ "types": "./types/ai/runtime/context-windows.d.ts",
51
+ "default": "./src/ai/runtime/context-windows.js"
52
+ },
53
+ "./ai/runtime/fast-mode.js": {
54
+ "types": "./types/ai/runtime/fast-mode.d.ts",
55
+ "default": "./src/ai/runtime/fast-mode.js"
56
+ },
57
+ "./ai/streaming/codex-events.js": {
58
+ "types": "./types/ai/streaming/codex-events.d.ts",
59
+ "default": "./src/ai/streaming/codex-events.js"
60
+ },
61
+ "./ai/live-input-prompt.js": {
62
+ "types": "./types/ai/live-input-prompt.d.ts",
63
+ "default": "./src/ai/live-input-prompt.js"
64
+ },
65
+ "./ai/file-change-stats.js": {
66
+ "types": "./types/ai/file-change-stats.d.ts",
67
+ "default": "./src/ai/file-change-stats.js"
68
+ },
69
+ "./ai/providers/claude-sdk.js": {
70
+ "types": "./types/ai/providers/claude-sdk.d.ts",
71
+ "default": "./src/ai/providers/claude-sdk.js"
72
+ },
73
+ "./ai/providers/claude-cli.js": {
74
+ "types": "./types/ai/providers/claude-cli.d.ts",
75
+ "default": "./src/ai/providers/claude-cli.js"
76
+ },
77
+ "./ai/providers/codex-app.js": {
78
+ "types": "./types/ai/providers/codex-app.d.ts",
79
+ "default": "./src/ai/providers/codex-app.js"
80
+ },
81
+ "./ai/providers/opencode-discovery.js": {
82
+ "types": "./types/ai/providers/opencode-discovery.d.ts",
83
+ "default": "./src/ai/providers/opencode-discovery.js"
84
+ },
85
+ "./agent/tools/index.js": {
86
+ "types": "./types/agent/tools/index.d.ts",
87
+ "default": "./src/agent/tools/index.js"
88
+ },
89
+ "./agent/tools/shared/runtime-context.js": {
90
+ "types": "./types/agent/tools/shared/runtime-context.d.ts",
91
+ "default": "./src/agent/tools/shared/runtime-context.js"
92
+ },
93
+ "./agent/tools/shared/ripgrep.js": {
94
+ "types": "./types/agent/tools/shared/ripgrep.d.ts",
95
+ "default": "./src/agent/tools/shared/ripgrep.js"
96
+ },
97
+ "./agent/prompt/skill-index.js": {
98
+ "types": "./types/agent/prompt/skill-index.d.ts",
99
+ "default": "./src/agent/prompt/skill-index.js"
100
+ },
101
+ "./agent/allowlists.js": {
102
+ "types": "./types/agent/allowlists.d.ts",
103
+ "default": "./src/agent/allowlists.js"
104
+ },
105
+ "./agent/transcript.js": {
106
+ "types": "./types/agent/transcript.d.ts",
107
+ "default": "./src/agent/transcript.js"
108
+ },
109
+ "./agent/compaction.js": {
110
+ "types": "./types/agent/compaction.d.ts",
111
+ "default": "./src/agent/compaction.js"
112
+ }
22
113
  },
23
114
  "main": "./src/index.js",
115
+ "types": "./types/index.d.ts",
24
116
  "files": [
25
117
  "src/**/*.js",
26
118
  "!src/__tests__/**",
119
+ "types/**/*.d.ts",
27
120
  "ARCHITECTURE.md",
28
121
  "MIGRATION.md",
29
122
  "README.md",
@@ -34,14 +127,14 @@
34
127
  },
35
128
  "dependencies": {
36
129
  "@anthropic-ai/claude-agent-sdk": "^0.1.0",
37
- "@earendil-works/pi-agent-core": "^0.79.1",
38
- "@earendil-works/pi-ai": "^0.79.1",
39
- "@mono-agent/sandbox": "0.4.0",
130
+ "@earendil-works/pi-agent-core": "^0.80.3",
131
+ "@earendil-works/pi-ai": "^0.80.3",
40
132
  "@modelcontextprotocol/sdk": "^1.12.0",
41
133
  "@opencode-ai/sdk": "^1.15.13",
42
134
  "zod": "^4.3.6"
43
135
  },
44
136
  "scripts": {
45
- "test": "pnpm --filter @mono-agent/sandbox run build && vitest run --passWithNoTests"
137
+ "build": "tsc -p tsconfig.types.json",
138
+ "test": "vitest run --passWithNoTests"
46
139
  }
47
140
  }
@@ -24,6 +24,9 @@ export function parseStoredAllowlist(value) {
24
24
  }
25
25
  }
26
26
 
27
+ /**
28
+ * @param {{mode?: string, list?: any, fallback?: string}} [options]
29
+ */
27
30
  export function inferAllowlistMode({ mode, list, fallback = ALLOWLIST_MODE_ALL } = {}) {
28
31
  if (mode !== undefined) return normalizeAllowlistMode(mode);
29
32
  return normalizeList(list).length > 0
@@ -29,6 +29,9 @@ export const RISK_TIERS = Object.freeze(["low", "medium", "high"]);
29
29
 
30
30
  const DEFAULT_TIMEOUT_MS = 60_000;
31
31
 
32
+ /**
33
+ * @param {{onToolApprovalRequest?: any, defaultRiskTier?: string, timeoutMs?: number, onEvent?: (event: any) => void, riskTiersByTool?: any, alwaysAllowTools?: any}} [options]
34
+ */
32
35
  export function createApprovalManager({
33
36
  onToolApprovalRequest = null,
34
37
  defaultRiskTier = "medium",