@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
package/ARCHITECTURE.md CHANGED
@@ -106,6 +106,34 @@ Legacy aliases are canonicalized at host ingress when needed. The strict parser
106
106
  keeps the package boundary honest by rejecting reserved runtime IDs such as
107
107
  `openai:*`, `vercel:*`, and `claude-code:*`.
108
108
 
109
+ ## Host prompt assembly and replay
110
+
111
+ The harness's complete `prompt` and typed `sections` describe inspection context.
112
+ Dispatch uses its separate `systemPrompt`: core/SOUL → identity → stable skill
113
+ index/guidance → selected skill bodies → fixed host-envelope instruction. The
114
+ runtime adds its structured-output instruction without moving it into host
115
+ history. Session facts and the conditional warm-skill paragraph live in the
116
+ leading `<host_turn_context>` envelope on every current user message. That
117
+ latest envelope supersedes older copies; quoted surface labels, user/history,
118
+ memory and tool output remain untrusted. Tool enforcement and delivery routes
119
+ do not derive authority from envelope text.
120
+
121
+ Every harness-prepared cold run and stale-session retry supplies chronological canonical
122
+ messages with deterministic speaker/timestamp labels, then the bounded untrusted
123
+ tool-history projection, then one current user message (envelope, existing
124
+ speaker/preceding-message/user/attachment text, recall suffix). Legacy system/tool
125
+ history is labeled untrusted text, not system authority or native tool calls.
126
+ Inspection, canonical history and provider transcripts remain distinct: the host
127
+ never persists the envelope into canonical user text or memory capture and does
128
+ not use it as a recall query. Configured last-64 retention is unchanged.
129
+
130
+ Only the primary's first router attempt may retain a provider session. A retry or
131
+ backup after a warm primary failure has the current message and bounded
132
+ failed-attempt snapshot, without the earlier conversation. Its answer retires the
133
+ coordinated durable epoch; the next turn reseeds from canonical history. Fresh
134
+ stateless Pi calls use a private in-memory repository so their stable attribution
135
+ id cannot collide with or delete the primary's transcript.
136
+
109
137
  ## Run Lifecycle
110
138
 
111
139
  **Diagram summary:** The host calls `run()`, the runtime lazily loads one bridge,
@@ -298,25 +326,36 @@ provider exposes queue-after-turn), not durability/cost:
298
326
 
299
327
  The pi runtime is built on pi-agent-core's native `AgentHarness` (the hand-rolled
300
328
  bridge was removed once native reached parity); it owns the session and
301
- pi-ai-managed retry. `AgentHarness` itself has **no** automatic compaction, so
302
- the pi bridge drives it through a one-shot `session_before_compact` hook: before
329
+ pi-ai-managed retry. `AgentHarness` supports native checkpoint and overflow compaction; mono-agent
330
+ disables that path and drives its own guarded policy through a one-shot `session_before_compact` hook: before
303
331
  each turn it compares the full request estimate with an adaptive trigger, and if
304
332
  a turn still overflows it retries exactly once only after a preview verifies a
305
333
  positive reduction. Runs report `context_compaction_applied` as `true` (a
306
334
  compaction fired), `false` (enabled but not needed), or `null` (disabled via
307
335
  `runtime.compaction.enabled: false`).
308
336
 
309
- | Provider | Warm session | Resume across turns | Survives process restart |
337
+ `ai/providers/pi-native/compaction-summary.js` prepares copies for Pi's public
338
+ `compact()`: bounded tool-result heads/tails, confirmed built-in file operations,
339
+ and supplemental summary focus. Its model facade changes only summary context;
340
+ model, options, request context and other model methods are forwarded. Each
341
+ completion is accounted once at return or rejection. The driver attaches these
342
+ rows to terminal compaction events, preserving spend even when a preview rejects
343
+ persistence. File metadata and generated prose are measured separately. Native
344
+ cut rules and reserve math remain Pi-owned. Payload diagnostics correlate
345
+ assistant usage independently of these operation-scoped summary requests.
346
+
347
+ | Active bridge | Warm session | Resume across turns | Survives process restart |
310
348
  |---|---|---|---|
311
349
  | **pi** | Yes (pi `AgentHarness` + JSONL session repo) | session repo | Yes only with `piSessionsRoot` and the durable history/session transaction contract |
312
- | **claude-sdk** | No persistent process (stream closes at turn end) | `queryOptions.resume` | No (Anthropic-side id) |
313
- | **claude-cli** | No respawns `claude --resume` per turn (re-inits MCP) | `--resume` replay | No |
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 |
316
-
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.
350
+
351
+ The current registry contains only Pi. A confirmed warm session omits host replay.
352
+ An unconfirmed durable reopen refreshes the handle and supplies canonical history:
353
+ true native resume skips seeding; missing JSONL creates an empty session and seeds
354
+ once. Native resume preserves assistant blocks, tool ids/arguments/results and
355
+ reasoning signatures. Cold reconstruction has only canonical text, so byte identity
356
+ with the original native transcript is not promised. Compaction replaces an older
357
+ prefix and keeps a tail; it may remove loaded skill bodies. Fallback routes remain
358
+ isolated and stateless, with the same cancellation/reset/failed-commit barriers.
320
359
 
321
360
  ## Essential Takeaway
322
361
 
package/MIGRATION.md CHANGED
@@ -6,10 +6,9 @@ current pre-1.0 contract. `createRuntime()` remains the package entry point;
6
6
  `@mono-agent/runtime-adapter`. Provider-session input/output uses
7
7
  `providerSessionId`, with `disposeSession()` and `disposeAllSessions()` retained.
8
8
 
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.
9
+ Review every section that matches your usage. As of `0.21.0` the package runs
10
+ exactly one runtime Pi behind an explicit exports map, with typed policy
11
+ objects, stricter sandbox behavior, and revised provider-session semantics.
13
12
 
14
13
  Migration policy: every newly introduced fail-closed validation belongs in the
15
14
  first affected version section, even when it tightens behavior without changing
@@ -17,6 +16,278 @@ the configuration schema.
17
16
 
18
17
  ---
19
18
 
19
+ ## 0.21.0
20
+
21
+ **This is the largest breaking change since `0.3.x`.** mono-agent shipped six
22
+ runtime bridges behind a dispatch table; it now runs only its Pi implementation.
23
+ Read the whole section before upgrading a live agent, and migrate its config
24
+ before restarting one.
25
+
26
+ ### Pi 0.85 dependency migration
27
+
28
+ The runtime exact-pins Pi AI and Pi Agent Core at `0.85.1`; the TUI pins Pi TUI
29
+ at the same version. Pi's harness is now created asynchronously and exposes
30
+ prompt, navigation, compaction, abort, event, and transcript operations through
31
+ its `main` lane with an explicit operation context. mono-agent absorbs that API
32
+ change in its Pi compatibility adapter; hosts do not need a config migration.
33
+
34
+ Pi's JSONL store now writes v4 transcripts. Existing v3 transcripts are
35
+ upgraded by Pi when opened and retain their conversation context. An unfinished
36
+ durable operation is aborted before mono-agent accepts a new prompt because
37
+ mono-agent tools do not yet use Pi's replay-memo contract; this prevents an
38
+ interrupted side-effecting tool from being executed twice.
39
+
40
+ ### Deleted runtime bridges
41
+
42
+ `claude-sdk`, `claude-code-cli`, `codex-app-cli`, `opencode-app-cli` and
43
+ `acp-stdio` are gone. `pi-sdk` remains and is no longer *a* backend — it is the
44
+ runtime. The backend descriptor table, the selection table and
45
+ `MonoRuntimeBackendId` are removed with them.
46
+
47
+ ### What is NOT deleted
48
+
49
+ Four surfaces share names with the deleted bridges and are unaffected. If you
50
+ use any of them, nothing changes:
51
+
52
+ - **The ACP *server* bridge** (`mono-agent bridge acp`) — mono-agent still
53
+ serves ACP to clients. Only the ACP *client* backend was removed.
54
+ - **`install-skill --target claude|codex`** — writes skills into those tools'
55
+ directories.
56
+ - **`docs-mcp-pairing`** — pairs the docs MCP with Claude Code and Codex.
57
+ - **The Codex web-search backend** (`tools.web.search.backend: "codex"`) — it
58
+ drives a real Codex app-server through an extracted client.
59
+
60
+ Note also that `openai-codex` and `opencode-go` are **Pi provider ids**, not
61
+ references to the deleted bridges. Routes naming them keep working.
62
+
63
+ ### Web research configuration
64
+
65
+ SearXNG remains supported in strict mode and as the first configured `auto`
66
+ route. Its canonical JSON setting is now provider-scoped:
67
+
68
+ ```json
69
+ { "tools": { "web": { "search": {
70
+ "backend": "searxng",
71
+ "searxng": { "endpoint": "http://127.0.0.1:8088" }
72
+ } } } }
73
+ ```
74
+
75
+ The former `tools.web.search.endpoint` and
76
+ `MONO_AGENT_WEB_SEARCH_ENDPOINT` spellings remain compatibility aliases; no
77
+ immediate migration is required. Prefer `tools.web.search.searxng.endpoint` or
78
+ `MONO_AGENT_WEB_SEARCH_SEARXNG_ENDPOINT` when editing config. If both spellings
79
+ are present they must normalize to the same URL.
80
+
81
+ Ollama Web Search is additive and explicit-only: select `backend: "ollama"`.
82
+ It never joins `auto`. Local mode defaults to `http://127.0.0.1:11434`; hosted
83
+ `https://ollama.com` additionally requires `ollama.apiKeyEnv`. A hosted key is
84
+ never sent to a local or custom origin.
85
+
86
+ ### Model reference grammar
87
+
88
+ Old: `<sdk>:[<provider>:]<model>`. New: **`<provider>:<model>`**, split at the
89
+ first colon only.
90
+
91
+ | before | after |
92
+ | --- | --- |
93
+ | `pi:openai-codex:gpt-5.6-sol` | `openai-codex:gpt-5.6-sol` |
94
+ | `pi:anthropic:claude-opus-5` | `anthropic:claude-opus-5` |
95
+ | `ollama:llama3.1:8b` | unchanged — only the first colon splits |
96
+ | `codex:gpt-5.6-terra` | **rejected**; no mechanical replacement |
97
+
98
+ A leading `pi:` is canonicalized away automatically, so those refs keep working
99
+ and stripping the prefix is optional tidying rather than a migration step.
100
+ `codex:`, `claude:`, `claude-code:`, `codex-cli:`, `acp:` and `vercel:` are
101
+ rejected at load with the replacement named in the message `doctor`,
102
+ `mono-agent validate`, `mono-agent config` and the startup error all print. They
103
+ are **not** migrated automatically: `codex:gpt-5.6-terra` →
104
+ `openai-codex:gpt-5.6-terra` looks mechanical but changes which auth store the
105
+ agent reads, and refs paired with `executionMode: "cli"` have no Pi equivalent
106
+ at all. A human has to choose.
107
+
108
+ ### Retired configuration keys
109
+
110
+ Each has an environment twin, and both now fail at load with the repair for the
111
+ surface they were set on, instead of a generic unknown-key error. A single load
112
+ is exhaustive *within one class*: every retired key present is named in one
113
+ message, and every retired variable set is named in one message — not one per
114
+ run. It is not exhaustive *across* classes. A config carrying both a retired key
115
+ and a retired variable stops at the key, and names the variable only on the next
116
+ run; see [Migrating a config](#migrating-a-config) for the order the classes are
117
+ checked in. An empty assignment (`KEY=`) is treated as unset and does not fail.
118
+
119
+ | key | environment twin | replacement |
120
+ | --- | --- | --- |
121
+ | `runtime.executionMode` | `MONO_AGENT_EXECUTION_MODE` | delete it — only the Pi runtime remains |
122
+ | `memory.llm.executionMode` | `MONO_AGENT_MEMORY_LLM_EXECUTION_MODE` | delete it, same reason |
123
+ | `runtime.routeSafety` | `MONO_AGENT_ROUTE_SAFETY` | delete it — every route is Pi-native, so `per-route-native` has no meaning |
124
+ | `runtime.fallbackModels` | `MONO_AGENT_FALLBACK_MODELS` | `runtime.fallbacks: [{ "model": "..." }]` for the key, `MONO_AGENT_FALLBACKS_JSON` for the variable |
125
+
126
+ `runtime.fallbacks` stays uncapped: `runtime.model` plus its fallbacks are the
127
+ default route and its backups, nothing more.
128
+
129
+ ### New: `providers`
130
+
131
+ `providers` declares which providers the agent supports, and widens what is
132
+ *selectable* to those providers' full catalogs — previously you could only pick
133
+ `runtime.model` or a declared fallback, so trying a new model meant editing
134
+ config and restarting. `ollama` and `lmstudio` are zero-config autodiscovered on
135
+ `localhost:11434` and `localhost:1234`; an explicit entry only overrides
136
+ endpoint or credentials. `providers.local[]` migrates on load.
137
+
138
+ Agents advertise the catalog additively: a slim `providers` array on `/v1/info`
139
+ plus a lazy `GET /v1/models`. `TUI_WIRE_SCHEMA` is **not** bumped, so existing
140
+ consoles keep working.
141
+
142
+ ### Removed deep exports
143
+
144
+ Subpath exports went from 26 to 17. The removed subpaths all belonged to deleted
145
+ bridges; import the Pi equivalents from the package root.
146
+
147
+ ### Removed host options
148
+
149
+ Three `createRuntime()` host options went with the ACP *client* backend that was
150
+ their only consumer: `resolveAcpProfile`, `onAcpInteractionRequest` and
151
+ `acpSessionTokenKey`. The `0.18.0` and `0.18.1` sections below still describe
152
+ them as required — that is a correct record of what those releases needed, and
153
+ those sections are deliberately unchanged. As of `0.21.0` the runtime no longer
154
+ binds them, and passing them is inert.
155
+
156
+ This does **not** affect the ACP *server* bridge (`mono-agent bridge acp`),
157
+ which never used them; see [What is NOT deleted](#what-is-not-deleted).
158
+
159
+ ### Web console store
160
+
161
+ Schema v10 → v12, in two guarded steps: v11 adds per-thread `run_model` /
162
+ `run_effort`, and v12 adds `agents.providers_json`, the persisted summary of the
163
+ providers an agent advertises. Each step is guarded on `PRAGMA table_info` and
164
+ re-runnable, and adds columns only — no rows are rewritten. Per-conversation
165
+ model and effort overrides now persist server-side, so they roam between devices
166
+ instead of living in one browser's localStorage.
167
+
168
+ ### Migrating a config
169
+
170
+ There is no codemod. `mono-agent migrate-config` was written for this release and
171
+ then removed before it shipped: it rewrote a live agent's config while the agent
172
+ itself could be writing the same file, and that race could not be closed — only
173
+ narrowed. Migrating by hand is a few minutes per agent and cannot lose data.
174
+
175
+ The loader does the finding for you. Every retired key, retired environment
176
+ variable and rejected model reference fails at load naming its own repair, so an
177
+ unmigrated agent refuses to start and tells you what to change:
178
+
179
+ ```text
180
+ MonoAgentConfigError: invalid_json
181
+ `runtime.executionMode` was removed; mono-agent runs only the Pi runtime (SDK).
182
+ Delete the key.
183
+
184
+ MonoAgentConfigError: invalid_env
185
+ `MONO_AGENT_FALLBACK_MODELS` was replaced by `MONO_AGENT_FALLBACKS_JSON`, a JSON
186
+ array of `{ "model": "..." }` objects. Remove the variable and re-express the
187
+ chain there, or drop it into `runtime.fallbacks` in mono-agent.config.json.
188
+
189
+ MonoAgentConfigError: invalid_model_reference
190
+ runtime.model `codex:gpt-5.6-terra` is not a valid runtime model reference:
191
+ codex is no longer a runtime backend; use openai-codex:gpt-5.6-terra
192
+ ```
193
+
194
+ A model supplied through the environment is attributed to the variable
195
+ (`MONO_AGENT_MODEL ...`) rather than the JSON path, so the message always names
196
+ the place you edit to fix it.
197
+
198
+ What it does *not* do is report everything at once. Within a class it is
199
+ exhaustive — all retired JSON keys in one message, all retired environment
200
+ variables in one message, all unknown keys in one message — but the load stops at
201
+ the first failing class, in this order: retired JSON keys, unknown JSON keys,
202
+ retired environment variables, model references, then the remaining shape checks.
203
+ Expect to run `mono-agent validate` a few times per agent, not once.
204
+
205
+ #### Required — the load fails until each of these is done
206
+
207
+ In `mono-agent.config.json`:
208
+
209
+ 1. Delete `runtime.executionMode`, `memory.llm.executionMode` and
210
+ `runtime.routeSafety`.
211
+ 2. Convert `runtime.fallbackModels: ["a", "b"]` to
212
+ `runtime.fallbacks: [{ "model": "a" }, { "model": "b" }]`.
213
+ 3. Replace every `codex:`, `claude:`, `claude-code:`, `codex-cli:`, `acp:`,
214
+ `vercel:<provider>:<model>` and nested `opencode:<provider>:<model>` reference
215
+ — in `runtime.model`, every `runtime.fallbacks[].model`, every
216
+ `subagents.definitions[].model`, an `agent-host` `memory.llm.model`, and every
217
+ per-trigger `model` override. The `vercel:`/`opencode:` wrappers unwrap to the
218
+ inner pair; the rest do not — `codex:gpt-5.6-terra` becomes
219
+ `openai-codex:gpt-5.6-terra`, which is a different auth store, so that
220
+ substitution is a decision, not a rename. The load error names the exact
221
+ replacement for each form.
222
+
223
+ In the environment — the shell, the `.env` the agent is started with, and any
224
+ `EnvironmentVariables` block in its launchd plist:
225
+
226
+ 4. Remove `MONO_AGENT_EXECUTION_MODE`, `MONO_AGENT_ROUTE_SAFETY` and
227
+ `MONO_AGENT_MEMORY_LLM_EXECUTION_MODE`. There is no replacement variable.
228
+ 5. Remove `MONO_AGENT_FALLBACK_MODELS` and re-express the chain as
229
+ `MONO_AGENT_FALLBACKS_JSON` (a JSON array of `{ "model": "..." }` objects), or
230
+ move it into `runtime.fallbacks` in the config file. Pointing this one at the
231
+ JSON key alone is not a repair: an operator whose chain lives only in `.env`
232
+ has no `runtime.fallbackModels` key to rewrite.
233
+ 6. Apply step 3 to any model reference carried in `MONO_AGENT_MODEL`,
234
+ `MONO_AGENT_FALLBACKS_JSON`, `MONO_AGENT_SUBAGENTS_JSON` or
235
+ `MONO_AGENT_MEMORY_LLM_MODEL`.
236
+
237
+ And in trigger frontmatter:
238
+
239
+ 7. The same step-3 fix to `model:` in every `*.md` under the cron and webhook
240
+ trigger folders (`cron.dir` / `webhook.dir` if renamed, resolved from the
241
+ agent root).
242
+
243
+ An empty assignment (`KEY=`) is *not* a migration item: every reader here treats
244
+ an empty environment value as unset, so an inert leftover line in a deployed
245
+ `.env` neither configured anything before nor fails the load now.
246
+
247
+ #### Optional — accepted either way
248
+
249
+ 8. A leading `pi:` on a runtime reference is canonicalized away at load, so
250
+ `pi:openai-codex:gpt-5.6-terra` loads today and resolves to
251
+ `openai-codex:gpt-5.6-terra`. Stripping it from `runtime.model` and
252
+ `runtime.fallbacks[].model` is cosmetic — do it if you want the file to match
253
+ what `mono-agent config` prints. `pi:codex:...` is still rejected: the inner
254
+ pair is checked after the wrapper comes off.
255
+ 9. Strip `pi:` from `memory.llm.model` **only** when `memory.llm.provider` is
256
+ `agent-host`. Under the default `ollama` provider that field is a raw service
257
+ model string, where the colon in `qwen3:8b` is a tag separator — rewriting it
258
+ would repoint memory at a model that does not exist.
259
+
260
+ #### `configVersion: 1` files are not covered by this checklist
261
+
262
+ `configVersion` belonged to an experimental schema (`runtimes`, `routing`,
263
+ `policy`, `state`, `$use` dependency injection) that the shipped loader has never
264
+ accepted. None of steps 1–9 apply, because none of those keys exist in such a
265
+ file; it is rejected whole, as unknown keys:
266
+
267
+ ```text
268
+ mono-agent.config.json contains unknown keys: agent.id, agent.instructions,
269
+ agent.workspace, channels.operator, configVersion, context.skills, policy,
270
+ routing, runtimes, session, state. Remove or correct them; unknown keys are not
271
+ ignored.
272
+ ```
273
+
274
+ Re-author such a config against the current schema (or `mono-agent init` a fresh
275
+ one and port the values across); there is no `configVersion: 1` upgrade path.
276
+
277
+ ### Deployment order
278
+
279
+ ```text
280
+ merge → release 0.21.0 → per agent: stop it, edit the config, mono-agent validate
281
+ → mono-agent start
282
+ ```
283
+
284
+ Edit with the agent stopped. `mono-agent validate` runs the same load as startup
285
+ without starting a turn or spending a model call, so it finds these problems for
286
+ free — but it reports one failing class per run (see above), so re-run it after
287
+ each edit until it comes back clean.
288
+
289
+ ---
290
+
20
291
  ## 0.19.0
21
292
 
22
293
  - **Oversized `Read` images:** raster image results with an edge above 8,000
@@ -422,17 +693,16 @@ key-resolution contract is unchanged**: an `apiKeys` map entry wins, else the ho
422
693
  falls back to its own env vars, exactly as returning `undefined` from the old hook
423
694
  did). **No host action needed** — `resolvePiApiKey` behaves as before.
424
695
 
425
- Dependency bump: **`@earendil-works/pi-ai` is now `0.84.3`; `@earendil-works/pi-agent-core` remains `0.83.0`**
426
- (the initial Pi 0.80 migration landed at `0.80.5`, from `^0.79.1`, ran at
427
- `0.80.6` until the 0.83 upgrade, and then at `0.83.0`). Agent Core 0.84.3 is
428
- held back because its replacement durable harness does not yet implement the
429
- prompt, subscription, compaction, or abort paths used here. Compaction is driven
430
- natively (section 3), and model-native `max` reasoning plus Pi's request-wide
696
+ Current dependency pins: **`@earendil-works/pi-ai` and
697
+ `@earendil-works/pi-agent-core` are both `0.85.1`** (the initial Pi 0.80
698
+ migration landed at `0.80.5`, from `^0.79.1`). Pi 0.85's durable lane harness is
699
+ adapted behind the runtime's existing public API. Compaction remains owned by
700
+ mono-agent policy, and model-native `max` reasoning plus Pi's request-wide
431
701
  pricing tiers are preserved.
432
702
 
433
- Packed npm consumers consequently retain Agent Core's nested Pi AI 0.83.0
434
- compatibility copy beside the runtime-owned Pi AI 0.84.3 catalog/provider copy.
435
- The release guard resolves and verifies both exact paths independently.
703
+ Packed npm consumers resolve the runtime-owned exact Pi AI 0.85.1 copy for both
704
+ the runtime and Agent Core's `^0.85.1` dependency. The release guard verifies
705
+ both resolution paths independently.
436
706
 
437
707
  The 0.83 upgrade carries two upstream removals, both absorbed inside the runtime
438
708
  so hosts need no action:
@@ -458,7 +728,7 @@ now a loud failure (guarded by `scripts/verify-deep-imports.mjs`).
458
728
  <!-- public-api-js-subpaths:start -->
459
729
  <!-- Generated by scripts/generate-public-api-docs.mjs. Do not edit by hand. -->
460
730
 
461
- The package exposes **22 named deep `.js` subpaths**:
731
+ The package exposes **14 named deep `.js` subpaths**:
462
732
 
463
733
  ```text
464
734
  @mono-agent/agent-runtime/agent/allowlists.js
@@ -472,17 +742,9 @@ The package exposes **22 named deep `.js` subpaths**:
472
742
  @mono-agent/agent-runtime/ai/failure.js
473
743
  @mono-agent/agent-runtime/ai/file-change-stats.js
474
744
  @mono-agent/agent-runtime/ai/live-input-prompt.js
475
- @mono-agent/agent-runtime/ai/providers/acp.js
476
- @mono-agent/agent-runtime/ai/providers/claude-cli.js
477
- @mono-agent/agent-runtime/ai/providers/claude-sdk-discovery.js
478
- @mono-agent/agent-runtime/ai/providers/claude-sdk.js
479
- @mono-agent/agent-runtime/ai/providers/codex-app.js
480
- @mono-agent/agent-runtime/ai/providers/opencode-discovery.js
481
- @mono-agent/agent-runtime/ai/runtime/context-windows.js
482
- @mono-agent/agent-runtime/ai/runtime/fast-mode.js
745
+ @mono-agent/agent-runtime/ai/providers/codex/app-server-client.js
483
746
  @mono-agent/agent-runtime/ai/runtime/model-refs.js
484
747
  @mono-agent/agent-runtime/ai/runtime/registry.js
485
- @mono-agent/agent-runtime/ai/streaming/codex-events.js
486
748
  ```
487
749
  <!-- public-api-js-subpaths:end -->
488
750
 
@@ -496,7 +758,7 @@ a compatibility subpath.
496
758
 
497
759
  ## Version
498
760
 
499
- This guide describes the published `0.20.x` package contract. Keep
761
+ This guide describes the published `0.21.x` package contract. Keep
500
762
  `@mono-agent/agent-runtime`, `@mono-agent/runtime-adapter`, and other
501
763
  `@mono-agent/*` packages on the same lockstep version when upgrading. The paired
502
764
  runtime adapter no longer exposes `piReasoningSummary` in its run-options type.
@@ -517,7 +779,7 @@ Worklab's runtime fork:
517
779
  `@earendil-works/pi-ai`, its separate Pi version constraint, and local copies
518
780
  of provider bridge code. Move tests off Pi's faux-provider helpers too; until
519
781
  that is complete, isolate the fixture or pin its development-only dependencies
520
- to the exact Pi AI `0.84.3` and Pi Agent Core `0.83.0` compatibility pins
782
+ to the exact Pi AI `0.85.1` and Pi Agent Core `0.85.1` compatibility pins
521
783
  rather than floating ranges. Do not restore the
522
784
  removed `pi-sdk.js` subpath.
523
785
  3. **Use the public Pi surfaces.** Run models through
@@ -525,7 +787,7 @@ Worklab's runtime fork:
525
787
  `listPiBuiltinModels`, `getPiBuiltinModel`,
526
788
  `reasoningLevelsForPiModel`, `resolvePiOAuthApiKey`, and `loginPiOAuth` for
527
789
  catalog and OAuth integration. Those façades keep Pi provider objects and the
528
- exact Pi AI `0.84.3` and Pi Agent Core `0.83.0` compatibility pins inside the runtime. OAuth login adapters
790
+ exact Pi AI `0.85.1` and Pi Agent Core `0.85.1` compatibility pins inside the runtime. OAuth login adapters
529
791
  must supply `onAuth`, `onDeviceCode`, `onPrompt`, and `onSelect`; the façade
530
792
  rejects an incomplete callback contract before starting provider login.
531
793
  4. **Inject Claude tests.** Replace package-level mocks of