@mono-agent/agent-runtime 0.13.0 → 0.15.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.
package/ARCHITECTURE.md CHANGED
@@ -24,6 +24,11 @@ a plain-data/plain-function seam the host wires up, not an import.
24
24
 
25
25
  ## Package Boundary
26
26
 
27
+ **Diagram summary:** A host constructs `createRuntime()` or `createRouterRuntime()`.
28
+ The runtime selects one of five provider bridges while sharing observability,
29
+ failure normalization, and capability-specific agent-kernel services. It returns
30
+ a provider-neutral result for the host to interpret.
31
+
27
32
  ```mermaid
28
33
  flowchart TB
29
34
  HostApp["Host app<br/>API / coordinator / worker / UI / DB"] --> CoreAI["host runtime composition"]
@@ -39,6 +44,7 @@ flowchart TB
39
44
  Registry --> ClaudeCLI["Claude Code CLI bridge"]
40
45
  Registry --> PiSDK["Pi SDK bridge<br/>OpenAI, Codex, Gemini, OpenRouter,<br/>Ollama, custom providers"]
41
46
  Registry --> CodexApp["Codex app-server CLI bridge"]
47
+ Registry --> OpenCodeApp["OpenCode app-server CLI bridge"]
42
48
 
43
49
  AgentKernel --> Builtins["Read / Write / Edit / Glob / Grep / Bash<br/>NodeRepl / WebFetch / WebSearch"]
44
50
  AgentKernel --> MCP["MCP stdio / SSE / HTTP tools"]
@@ -49,6 +55,7 @@ flowchart TB
49
55
  ClaudeCLI --> Providers
50
56
  PiSDK --> Providers
51
57
  CodexApp --> Providers
58
+ OpenCodeApp --> Providers
52
59
 
53
60
  Runtime --> Result["RuntimeResult<br/>text, structuredResult, events,<br/>usage, diagnostics, failureKind"]
54
61
  Result --> CoreAI
@@ -61,16 +68,24 @@ and pre-resolved settings into the runtime instead.
61
68
 
62
69
  ## Runtime Selection
63
70
 
71
+ **Diagram summary:** Hosts may use `parseRuntimeModelReference()` to turn a
72
+ canonical string into the object required by `run()`. The static registry then
73
+ matches that object plus execution mode and lazily imports Claude SDK, Claude
74
+ Code CLI, Pi SDK, Codex app-server, or OpenCode app-server code. Capability
75
+ descriptors are available without loading those provider implementations.
76
+
64
77
  ```mermaid
65
78
  flowchart LR
66
- ModelRef["options.model<br/>claude:* / pi:*:* / codex:*"] --> Parse["parseRuntimeModelReference()"]
67
- Parse --> Mode["options.executionMode<br/>sdk or cli"]
79
+ AuthoredRef["authored model string"] --> Parse["parseRuntimeModelReference()"]
80
+ Parse --> ModelRef["options.model<br/>parsed RuntimeModelRef"]
81
+ ModelRef --> Mode["options.executionMode<br/>sdk or cli"]
68
82
  Mode --> Resolve["resolveRuntimeBridge()"]
69
83
 
70
84
  Resolve -->|sdk=claude + sdk mode| ClaudeSDK["claude bridge<br/>@anthropic-ai/claude-agent-sdk"]
71
85
  Resolve -->|sdk=claude + cli mode| ClaudeCLI["claude-code bridge<br/>claude binary"]
72
86
  Resolve -->|sdk=pi| PiSDK["pi bridge<br/>@earendil-works/pi-agent-core"]
73
87
  Resolve -->|sdk=codex + cli mode| CodexApp["codex-app bridge<br/>codex app-server"]
88
+ Resolve -->|sdk=opencode + cli mode| OpenCodeApp["opencode-app bridge<br/>isolated OpenCode server"]
74
89
 
75
90
  Resolve --> Caps["runtimeCapabilities()<br/>static backend features"]
76
91
  Caps --> Used["capabilitiesUsed<br/>per-call observed features"]
@@ -82,6 +97,10 @@ Canonical active model references are:
82
97
  `executionMode`
83
98
  - `pi:<providerId>:<modelName>` for Pi SDK providers
84
99
  - `codex:<modelId>` for Codex app-server CLI
100
+ - `opencode:<providerId>:<modelName>` for the isolated OpenCode app-server CLI
101
+
102
+ `createRuntime().run()` expects this already-parsed object; it does not parse a
103
+ string implicitly.
85
104
 
86
105
  Legacy aliases are canonicalized at host ingress when needed. The strict parser
87
106
  keeps the package boundary honest by rejecting reserved runtime IDs such as
@@ -89,6 +108,11 @@ keeps the package boundary honest by rejecting reserved runtime IDs such as
89
108
 
90
109
  ## Run Lifecycle
91
110
 
111
+ **Diagram summary:** The host calls `run()`, the runtime lazily loads one bridge,
112
+ and that bridge talks to its SDK or subprocess. Supported tool calls pass through
113
+ the shared kernel, provider events are normalized, and the host receives a result
114
+ that it must validate for its domain.
115
+
92
116
  ```mermaid
93
117
  sequenceDiagram
94
118
  participant Host as Host app
@@ -105,15 +129,19 @@ sequenceDiagram
105
129
  Runtime->>Observer: create hub from host + call observers
106
130
  Runtime->>Bridge: execute(systemPrompt, normalized options)
107
131
 
108
- Bridge->>Kernel: prepare tools, MCP, approvals, limits
109
- Kernel-->>Bridge: provider-specific tool surface
132
+ opt bridge supports managed or MCP tool dispatch
133
+ Bridge->>Kernel: prepare tools, MCP, approvals, limits
134
+ Kernel-->>Bridge: provider-specific tool surface
135
+ end
110
136
  Bridge->>Provider: send prompt, messages, tools, schema, settings
111
137
 
112
138
  loop streaming events
113
139
  Provider-->>Bridge: assistant/tool/result/provider events
114
140
  Bridge->>Observer: normalized runtime events
115
- Bridge->>Kernel: execute built-in/MCP tools as needed
116
- Kernel-->>Bridge: tool results or tool errors
141
+ opt provider requests host-dispatched tools
142
+ Bridge->>Kernel: execute built-in/MCP tools
143
+ Kernel-->>Bridge: tool results or tool errors
144
+ end
117
145
  end
118
146
 
119
147
  Bridge-->>Runtime: RuntimeResult
@@ -122,12 +150,20 @@ sequenceDiagram
122
150
  Host->>Host: validate/parse host-specific contract
123
151
  ```
124
152
 
125
- The package forwards provider structured output as `structuredResult`, but it
126
- does not validate that output against a host domain schema. Hosts own that
127
- validation and any state-machine side effects.
153
+ Claude SDK, Claude CLI, and Pi SDK can return provider-captured output as
154
+ `structuredResult`. Codex app-server receives the schema but returns its output
155
+ as text for the host to parse; direct OpenCode rejects the option. The package
156
+ does not validate any captured output against a host domain schema. Hosts own
157
+ that validation and all state-machine side effects.
128
158
 
129
159
  ## Main Subsystems
130
160
 
161
+ **Diagram summary:** The public barrels lead to the runtime factory, fallback
162
+ router, AI registry, and agent-kernel helpers. The registry owns five lazy
163
+ provider loaders. Shared agent modules own tools, context, approvals,
164
+ compaction, transcript snapshots, and result-size guards; shared AI modules own
165
+ failure, cost, observation, and capability metadata.
166
+
131
167
  ```mermaid
132
168
  flowchart TB
133
169
  Public["Public API<br/>src/index.js"] --> RuntimeFactory["runtime.js<br/>createRuntime()"]
@@ -142,6 +178,7 @@ flowchart TB
142
178
  Providers --> ClaudeCode["claude-cli.js"]
143
179
  Providers --> Pi["pi-native.js<br/>pi-models/messages/events"]
144
180
  Providers --> Codex["codex-app.js"]
181
+ Providers --> OpenCode["opencode-app.js<br/>opencode-server.js"]
145
182
 
146
183
  AgentExports --> Tools["agent/tools/*"]
147
184
  Tools --> ToolContext["shared/tool-context.js<br/>per-instance ToolContext<br/>workspace, repoRoot, rg, sandbox, brand"]
@@ -164,8 +201,9 @@ Key responsibilities by subsystem:
164
201
  - `runtime.js`: binds host callbacks once, builds a per-instance `ToolContext`
165
202
  (`agent/tools/shared/tool-context.js`) threaded to every bridge call via
166
203
  `options.toolContext`, and routes each call to the resolved bridge.
167
- - `ai/runtime/registry.js`: maps model reference plus execution mode to one of
168
- the built-in provider bridges.
204
+ - `ai/runtime/registry.js`: keeps the five static bridge descriptors, exposes
205
+ their metadata for introspection, and lazily imports the one whose model
206
+ reference plus execution mode matches a run.
169
207
  - `ai/runtime/router.js`: retries across an ordered fallback chain on retryable
170
208
  provider failures, carrying a transcript-tail resume snapshot forward.
171
209
  - `ai/providers/*`: owns provider-specific request shapes, event conversion,
@@ -199,6 +237,11 @@ Key responsibilities by subsystem:
199
237
 
200
238
  ## Host Responsibilities
201
239
 
240
+ **Diagram summary:** The host injects pricing, Pi credentials, artifact and
241
+ compaction persistence, tool-approval decisions, runtime branding, and allowed
242
+ filesystem roots. The runtime returns raw normalized data; the host owns domain
243
+ validation, durable state, and UI effects.
244
+
202
245
  ```mermaid
203
246
  flowchart LR
204
247
  Host["Host app"] --> Pricing["resolveCustomPricing"]
@@ -265,22 +308,21 @@ compaction fired), `false` (enabled but not needed), or `null` (disabled via
265
308
 
266
309
  | Provider | Warm session | Resume across turns | Survives process restart |
267
310
  |---|---|---|---|
268
- | **pi** | Yes (pi `AgentHarness` + JSONL session repo) | session repo | **Yes** (only one) |
311
+ | **pi** | Yes (pi `AgentHarness` + JSONL session repo) | session repo | Yes only with `piSessionsRoot` and the durable history/session transaction contract |
269
312
  | **claude-sdk** | No persistent process (stream closes at turn end) | `queryOptions.resume` | No (Anthropic-side id) |
270
313
  | **claude-cli** | No — respawns `claude --resume` per turn (re-inits MCP) | `--resume` replay | No |
271
314
  | **codex-app** | Live subprocess thread (dies with the subprocess) | next turn on the thread, else replay | No |
315
+ | **opencode-app** | No — every run uses an isolated server and private database | Unsupported | No |
272
316
 
273
- claude-cli and codex only *approximate* a warm session (resume/replay), so do
274
- not assume warm-session latency wins there. Recall (memory embeddings) is bounded
275
- by a timeout + circuit breaker and degrades to empty (with a `memory_degraded`
276
- warning) rather than blocking or failing a turn; selected skills are mtime-cached
277
- across turns.
317
+ Claude CLI and Codex only *approximate* a warm session (resume/replay), so do
318
+ not assume warm-session latency wins there. Direct OpenCode is intentionally
319
+ stateless across runs.
278
320
 
279
321
  ## Essential Takeaway
280
322
 
281
323
  Think of `@mono-agent/agent-runtime` as the portable agent process engine
282
324
  underneath a host app. The host decides what a task means, which agent should
283
325
  run, how state changes, and how results are persisted. The runtime decides how
284
- to talk to Claude, Pi, and Codex execution surfaces; how tools are exposed; how
285
- provider failures are normalized; and how enough telemetry is returned for a
286
- host to make reliable orchestration decisions.
326
+ to talk to Claude, Pi, Codex, and OpenCode execution surfaces; how tools are
327
+ exposed; how provider failures are normalized; and how enough telemetry is
328
+ returned for a host to make reliable orchestration decisions.
package/MIGRATION.md CHANGED
@@ -1,15 +1,26 @@
1
1
  # `@mono-agent/agent-runtime` — Migration Guide
2
2
 
3
- Breaking and behavioral changes for consumers upgrading **from `0.3.x`** (the
4
- `feat/runtime-live-sessions` line). The public entry points are unchanged —
5
- `createRuntime` / `createMonoRuntime`, the run-options contract, and provider
6
- session support (`sessionId` in, `provider_session_id` out, `disposeSession` /
7
- `disposeAllSessions`) all keep their shapes. The changes below affect the **Pi
8
- runtime bridge, a few run options, durable-session semantics, the fallback
9
- router, and some diagnostics**.
3
+ Breaking and behavioral changes for consumers upgrading from `0.3.x` to the
4
+ current pre-1.0 contract. `createRuntime()` remains the package entry point;
5
+ `createMonoRuntime()` remains the typed facade in
6
+ `@mono-agent/runtime-adapter`. Provider-session input/output uses
7
+ `providerSessionId`, with `disposeSession()` and `disposeAllSessions()` retained.
10
8
 
11
- If you only use the Claude SDK / Claude CLI / Codex backends and do not touch Pi
12
- or durable sessions, this is a no-op upgrade.
9
+ Review every section that matches your usage. The package now has an explicit
10
+ exports map, a five-bridge lazy registry, typed policy objects, stricter sandbox
11
+ behavior, and revised provider-session semantics even when Pi is not your
12
+ primary route.
13
+
14
+ ---
15
+
16
+ ## Pre-1.0 public-surface cleanup
17
+
18
+ The compatibility entrypoints `./ai/backend.js` and `./ai/registry.js` were
19
+ removed after repository-wide reachability checks found no supported caller.
20
+ The old `findProviderForModel` / `listProviders` aliases and provider/backend
21
+ constant objects were removed at the same time. Import `resolveRuntimeBridge`
22
+ or `listRuntimeBridges` from `@mono-agent/agent-runtime` (or its `./ai` barrel)
23
+ instead. Runtime behavior and the canonical bridge descriptors are unchanged.
13
24
 
14
25
  ---
15
26
 
@@ -23,13 +34,14 @@ registry resolves `pi` → the native bridge unconditionally; there is no
23
34
  - **Public runtime API** (`createRuntime`, model reference `"pi:<provider>:<model>"`)
24
35
  is unchanged — `pi:openai:gpt-5.5` etc. still work.
25
36
  - **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.
37
+ longer resolve**: the compatibility shim was removed and the explicit exports
38
+ map has no provider wildcard. **Action:** import
39
+ `generatePiNativeResponse` / `piNativeRuntimeBridge` from
40
+ `@mono-agent/agent-runtime/ai`, or select Pi through the public runtime
41
+ registry. `pi-errors.js` is internal and is not an exported replacement; use
42
+ the normalized `RuntimeResult.failureKind` or the public failure helpers at
43
+ `@mono-agent/agent-runtime/ai/failure.js`. The `pi*Backend` aliases are gone
44
+ all Pi routes through the native bridge.
33
45
 
34
46
  ## 2. Removed run options: `piReasoningSummary`, `piCodexTransport`
35
47
 
@@ -37,10 +49,9 @@ These were Pi-bridge knobs the native path does not consume.
37
49
 
38
50
  - `piReasoningSummary` is **no longer read** and was removed from the run-options
39
51
  type. Pi-native derives reasoning from `effort` (`thinkingLevel`); the
40
- codex/claude CLIs emit reasoning summaries on their own. **Action:** stop
41
- passing `piReasoningSummary` it was already a no-op on the native path; remove
42
- it from your call sites. (Host config `runtime.reasoningSummary` still validates
43
- for back-compat but is not wired to a runtime option.)
52
+ Codex and Claude CLI bridges emit their own reasoning events. **Action:**
53
+ remove `piReasoningSummary` from call sites. The former
54
+ `runtime.reasoningSummary` config field has also been removed.
44
55
  - `piCodexTransport` was doc-only and is removed. No replacement is needed.
45
56
 
46
57
  ## 3. Pi context compaction: bridge-driven via AgentHarness.compact()
@@ -67,15 +78,15 @@ These were Pi-bridge knobs the native path does not consume.
67
78
 
68
79
  ## 4. Durable Pi session resume: create-on-miss semantics
69
80
 
70
- When a run supplies a `sessionId` **and** durable storage is configured
71
- (`piSessionsRoot`), Pi-native now **creates the session with that id if no
72
- on-disk JSONL exists** (create-on-miss), instead of returning
81
+ When a run supplies a `providerSessionId` (or the legacy `sessionId` alias) **and**
82
+ durable storage is configured (`piSessionsRoot`), Pi-native now **creates the
83
+ session with that id if no on-disk JSONL exists** (create-on-miss), instead of returning
73
84
  `session_not_found`. An existing JSONL is reopened and resumed as before.
74
85
 
75
86
  This makes a **stable, conversation-derived session id resume across process
76
87
  restarts** (the on-disk transcript is the durable history; the in-memory
77
88
  conversation→session map is no longer required to resume). **Action:** if you
78
- passed an arbitrary `sessionId` to a durable run expecting a hard
89
+ passed an arbitrary `providerSessionId` to a durable run expecting a hard
79
90
  `session_not_found` on first use, note it now succeeds by creating that session.
80
91
  The in-memory (non-durable) resume path still fast-fails `session_not_found` on a
81
92
  miss.
@@ -155,9 +166,7 @@ and that group's legacy `settings` keys are ignored; an absent typed object lets
155
166
  its group's `settings` keys through as a fallback. Consuming **any** legacy
156
167
  `settings` key emits exactly one `runtime_warning` with
157
168
  **`warning_kind: "deprecated_settings_option"`** per run (listing the consumed
158
- keys). Passing no `settings` — or an empty/irrelevant bag — never warns, so a host
159
- that never passed `settings` is byte-for-byte unchanged (mono-agent hosts do not
160
- pass it, so this is a no-op there).
169
+ keys). Passing no `settings` — or an empty/irrelevant bag — never warns.
161
170
 
162
171
  `resolveAgentCompactionPolicy(settings, model)` stays exported (the canonical
163
172
  clamp/mapper both paths route through), and `@mono-agent/runtime-adapter` exposes
@@ -211,7 +220,7 @@ now a loud failure (guarded by `scripts/verify-deep-imports.mjs`).
211
220
  <!-- public-api-js-subpaths:start -->
212
221
  <!-- Generated by scripts/generate-public-api-docs.mjs. Do not edit by hand. -->
213
222
 
214
- The package exposes **22 named deep `.js` subpaths**:
223
+ The package exposes **21 named deep `.js` subpaths**:
215
224
 
216
225
  ```text
217
226
  @mono-agent/agent-runtime/agent/allowlists.js
@@ -221,7 +230,6 @@ The package exposes **22 named deep `.js` subpaths**:
221
230
  @mono-agent/agent-runtime/agent/tools/shared/ripgrep.js
222
231
  @mono-agent/agent-runtime/agent/tools/shared/runtime-context.js
223
232
  @mono-agent/agent-runtime/agent/transcript.js
224
- @mono-agent/agent-runtime/ai/backend.js
225
233
  @mono-agent/agent-runtime/ai/cost.js
226
234
  @mono-agent/agent-runtime/ai/failure.js
227
235
  @mono-agent/agent-runtime/ai/file-change-stats.js
@@ -241,18 +249,18 @@ The package exposes **22 named deep `.js` subpaths**:
241
249
 
242
250
  **Action:** if you deep-import a subpath not in this list, switch to the closest
243
251
  supported one, a barrel (`./ai` / `./agent`), or the public runtime registry.
244
- `pi-sdk.js` is gone and remains intentionally unexported (section 1). Worklab
245
- ports should import `generatePiNativeResponse` from `@mono-agent/agent-runtime/ai`
246
- instead of adding a `pi-sdk.js` compatibility subpath.
252
+ `pi-sdk.js` is gone and remains intentionally unexported (section 1). Import
253
+ `generatePiNativeResponse` from `@mono-agent/agent-runtime/ai` instead of adding
254
+ a compatibility subpath.
247
255
 
248
256
  ---
249
257
 
250
258
  ## Version
251
259
 
252
- These changes ship in the first `agent-runtime` release after `0.3.0` on the
253
- `feat/runtime-live-sessions` line (a minor/major bump; see the release tag). The
254
- paired `@mono-agent/runtime-adapter` drops the `piReasoningSummary` field from its
255
- run-options type in lockstep.
260
+ This guide describes the published `0.13.x` package contract. Keep
261
+ `@mono-agent/agent-runtime`, `@mono-agent/runtime-adapter`, and other
262
+ `@mono-agent/*` packages on the same lockstep version when upgrading. The paired
263
+ runtime adapter no longer exposes `piReasoningSummary` in its run-options type.
256
264
 
257
265
  ---
258
266