@dylanrussell/agent-router 2.0.1 → 2.1.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/CHANGELOG.md +15 -1
- package/README.md +98 -3
- package/dist/cli.js +1 -1
- package/dist/cli.js.map +1 -1
- package/dist/plugin.d.ts +11 -0
- package/dist/plugin.js +623 -168
- package/dist/plugin.js.map +1 -1
- package/dist/tui.d.ts +38 -1
- package/dist/tui.js +56 -20
- package/dist/tui.js.map +1 -1
- package/package.json +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
# 2.1.0
|
|
2
|
+
|
|
3
|
+
- Add opt-in account-scoped quota preflight before automatic main turns and new subagent tasks, using the usage service's credential-free RPC.
|
|
4
|
+
- Skip only fresh confirmed exhausted candidates; unknown quota keeps the primary. Paid fallback requires explicit approval.
|
|
5
|
+
- Add session-scoped `router_pin`, `router_auto`, and `router_routing_status` controls. Pins survive restarts with bounded storage and deletion cleanup.
|
|
6
|
+
- Preserve staged next-turn reactive fallback precedence, manual overrides, and completed tools. No automatic mid-task retry is enabled.
|
|
7
|
+
- Verify native main/child admission, quota recovery, durable pinning, timeout handling, and concurrent admission/disposal guards.
|
|
8
|
+
|
|
9
|
+
# 2.0.2
|
|
10
|
+
|
|
11
|
+
- Simplify stack chains to one model per line in precedence order, without Primary/Fallback labels.
|
|
12
|
+
- Highlight the live session's selected agent/model with native theme color, bold text and a marker; show out-of-chain selections separately.
|
|
13
|
+
- React to session model/agent changes, normalize default variants, and wrap full provider/model identities in narrow sidebars.
|
|
14
|
+
|
|
1
15
|
# 2.0.1
|
|
2
16
|
|
|
3
17
|
- Normalize V2's `default` variant so pending next-user-turn fallback is not disabled by an equivalent model reference.
|
|
@@ -21,6 +35,6 @@
|
|
|
21
35
|
|
|
22
36
|
- Applying/backing out stacks still requires restarting OpenCode to reload agent files.
|
|
23
37
|
- Terminal stack operations access local files; remote-server filesystem management is not supported.
|
|
24
|
-
- Fallback notices are server logs. The sidebar shows configured routing
|
|
38
|
+
- Fallback notices are server logs. The sidebar shows configured routing with the current session selection highlighted; it does not expose pending fallback state.
|
|
25
39
|
- OpenCode 2.0.8 does not identify request kind on retry hooks. The plugin conservatively tracks the last model-request kind and only handles primary requests. Concurrent auxiliary requests can suppress fallback handling.
|
|
26
40
|
- Session defaults must resolve to explicit agent/model selections before routing. Fallback routing is bounded to 1,024 tracked sessions per plugin instance.
|
package/README.md
CHANGED
|
@@ -175,7 +175,102 @@ Duplicate failures advance only once per admitted user turn. Routing budgets are
|
|
|
175
175
|
|
|
176
176
|
**Verified boundary:** compiled against the published **2.0.8** API types. Deterministic adapter tests cover next-turn selection, retry veto, auxiliary-request exclusion, variants, and no replay or persistent agent writes. These are not real-provider end-to-end tests. An LLM may choose to repeat a tool when explicitly asked to continue.
|
|
177
177
|
|
|
178
|
-
OpenCode 2.0.8 exposes no atomic compare-and-switch in the prompt hook and no request kind in the retry hook. Concurrent manual selections/admissions or auxiliary requests remain host API limitations. The sidebar displays configured routing
|
|
178
|
+
OpenCode 2.0.8 exposes no atomic compare-and-switch in the prompt hook and no request kind in the retry hook. Concurrent manual selections/admissions or auxiliary requests remain host API limitations. The sidebar displays configured routing and highlights the current session selection, not pending fallback state. Terminal stack operations require local filesystem access; remote server filesystem management is not supported.
|
|
179
|
+
|
|
180
|
+
### Opt-in quota preflight (phase 1)
|
|
181
|
+
|
|
182
|
+
The server plugin can consult the usage-tracker server's `direct-api-usage.query`
|
|
183
|
+
RPC before each new explicit main-session prompt and each new native `subagent`
|
|
184
|
+
start. Configure the server plugin using the object form:
|
|
185
|
+
|
|
186
|
+
```jsonc
|
|
187
|
+
{
|
|
188
|
+
"plugins": [
|
|
189
|
+
{
|
|
190
|
+
"package": "@dylanrussell/agent-router",
|
|
191
|
+
"options": {
|
|
192
|
+
"quotaPreflight": {
|
|
193
|
+
"enabled": true,
|
|
194
|
+
"allowPaidFallbacks": false
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
]
|
|
199
|
+
}
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
Both options default to `false`. Existing applied fallback chains supply candidate
|
|
203
|
+
order; preflight never writes agent frontmatter, router state, or stacks. A staged
|
|
204
|
+
reactive fallback has precedence on the next eligible admission, even when the
|
|
205
|
+
primary has available or unknown quota. Preflight checks that backup and later
|
|
206
|
+
candidates for known exhaustion. Otherwise, each eligible admission reconsiders
|
|
207
|
+
the configured primary. Retry hooks and same-turn retry behavior are unchanged.
|
|
208
|
+
|
|
209
|
+
- Only fresh, account-and-scope-matched `exhausted` evidence skips a candidate.
|
|
210
|
+
An available or unknown primary remains the primary. Expired observations,
|
|
211
|
+
reached resets, unavailable methods, malformed replies, and timeouts are unknown.
|
|
212
|
+
- After earlier candidates are exhausted, an unknown backup with a service-proven
|
|
213
|
+
subscription binding may be tried. Without that binding, selecting a backup
|
|
214
|
+
requires explicit `allowPaidFallbacks: true`, which permits potentially paid
|
|
215
|
+
configured backups. If no eligible candidate remains, selection is unchanged.
|
|
216
|
+
- The usage service owns shared caching, bounded stale refreshes, credential
|
|
217
|
+
resolution, explicit Headroom/Go account bindings, and model-specific OpenAI
|
|
218
|
+
scope matching. Router receives opaque references and quota decisions only;
|
|
219
|
+
it neither polls providers nor infers account equivalence from provider names.
|
|
220
|
+
- Quota queries have a 3-second caller deadline and at most 16 outstanding calls,
|
|
221
|
+
including timed-out calls that ignore cancellation. Excess admissions use
|
|
222
|
+
unknown evidence rather than joining a queue. Admission ownership is bounded
|
|
223
|
+
to 1,024 sessions and concurrent main admission checks to 64.
|
|
224
|
+
- Explicit initial model selections and observable manual selections take priority,
|
|
225
|
+
including selections equal to the configured primary. Native child overrides
|
|
226
|
+
are checked before model resolution in `tool.execute.before`; resumed children
|
|
227
|
+
are excluded. Main sessions whose agent is unresolved are left native.
|
|
228
|
+
- Automatic selection ownership is in memory. After plugin restart, a stored
|
|
229
|
+
model is conservatively treated as pinned; explicit pins also persist in
|
|
230
|
+
plugin-scoped server storage. A second session read and observed
|
|
231
|
+
selection events guard asynchronous admission, but the host offers no atomic
|
|
232
|
+
compare-and-switch.
|
|
233
|
+
|
|
234
|
+
**Explicit session controls:** with preflight enabled, the server exposes three
|
|
235
|
+
additional tools. Pin/auto tools are for explicit user requests, under the host's
|
|
236
|
+
normal tool-permission policy. They take no model or session arguments; their
|
|
237
|
+
scope is the calling session.
|
|
238
|
+
|
|
239
|
+
- `router_pin` freezes the current selection, resolving the native agent/default
|
|
240
|
+
model when no selection is stored. It disables quota preflight and clears staged
|
|
241
|
+
reactive fallback for this session. The pin persists in server plugin storage.
|
|
242
|
+
Pins share one durable value capped at 1,024 sessions across restarts. Serialized
|
|
243
|
+
writes prevent lost updates; session deletion removes its durable pin, including
|
|
244
|
+
when deletion races a pin write. Plugin cleanup drains dispatched pin writes.
|
|
245
|
+
- `router_auto` clears the explicit pin and authorizes automatic routing on the
|
|
246
|
+
**next explicit user turn**. It neither switches the model nor sends a prompt.
|
|
247
|
+
Automatic ownership is not restored across plugin restarts: use this control
|
|
248
|
+
again to opt an existing selected session back in.
|
|
249
|
+
- `router_routing_status` reports `automatic`/`pinned`, the current model, and a
|
|
250
|
+
concise reason. Admissions and controls also write concise server-log notices
|
|
251
|
+
such as `primary_unknown`, `known_exhaustion_fallback`, and
|
|
252
|
+
`staged_reactive_fallback`.
|
|
253
|
+
|
|
254
|
+
**Picker boundary:** OpenCode 2.0.8 treats selecting the already-active model as a
|
|
255
|
+
no-op and emits no selection event. Selecting an automatic fallback again in the
|
|
256
|
+
standard picker does **not** pin it. Explicitly request `router_pin` to freeze it;
|
|
257
|
+
request `router_auto` when ready to resume automatic routing. Different-model
|
|
258
|
+
picker selections remain observable and take priority.
|
|
259
|
+
|
|
260
|
+
`npm run build && npm run test:quota` exercises the production router and a fake
|
|
261
|
+
quota RPC on a private native 2.0.8 host, including true native child starts,
|
|
262
|
+
fresh/exhausted/unknown/reset evidence, explicit pin/auto controls, staged 429/503
|
|
263
|
+
precedence, timeout, recovery, and tool continuation without midtask switching.
|
|
264
|
+
It explicitly reports the native same-model picker boundary.
|
|
265
|
+
`scripts/probe-admission-v2.mjs` independently records
|
|
266
|
+
native admission/provenance behavior. Neither script contacts real quota APIs.
|
|
267
|
+
Set `USAGE_TRACKER_SOURCE` to the usage-tracker source directory to run the same
|
|
268
|
+
native main/child checks with its actual RPC definition and quota implementation,
|
|
269
|
+
using synthetic credentials and direct-provider response fixtures. Service-side
|
|
270
|
+
account approvals belong in usage-tracker's `options.quotaBindings`, whose records
|
|
271
|
+
use `{ providerID, source, models, connection: { type, id }, approval }` for saved
|
|
272
|
+
credentials (`{ type: "env", name }` for environment connections). Router options
|
|
273
|
+
do not contain credentials or binding attestations.
|
|
179
274
|
|
|
180
275
|
### Install This Checkout
|
|
181
276
|
|
|
@@ -210,8 +305,8 @@ The plugin exposes six tools the agent (or you, by asking it) can call:
|
|
|
210
305
|
|
|
211
306
|
The V2 terminal half loads from the package's `./tui` export (`cli.json`, wired up by `init`):
|
|
212
307
|
|
|
213
|
-
- **Sidebar panel** — lists available stacks with the active one checked. Under **Current Stack
|
|
214
|
-
- **
|
|
308
|
+
- **Sidebar panel** — lists available stacks with the active one checked. Under **Current Stack**, each agent has one indented model per line, in precedence order, without Primary/Fallback labels. Explicit variants appear in brackets; full model IDs wrap rather than truncate. A `⟳ restart required` badge appears when the active stack differs from the one at TUI startup. File changes update live (≤1.5s).
|
|
309
|
+
- **Current selection** — the live session's agent/model is highlighted in color and bold with `●`; out-of-chain selections get a separate Current row. Other agents are not presented as live selections. Configured chains still come from the active stack file, not the applied `state.json.fallbackAgents` snapshot. Editing a stack changes the preview but does not apply it: use the stack and restart opencode to activate changes. The marker reflects session selection, not proof that a request is running or that failover is enabled.
|
|
215
310
|
- **Commands** — type `/` or open the command palette:
|
|
216
311
|
|
|
217
312
|
| command | what it does |
|
package/dist/cli.js
CHANGED
|
@@ -17006,7 +17006,7 @@ async function exportStack(paths, name, toFile) {
|
|
|
17006
17006
|
}
|
|
17007
17007
|
|
|
17008
17008
|
// src/version.ts
|
|
17009
|
-
var VERSION = "2.0
|
|
17009
|
+
var VERSION = "2.1.0";
|
|
17010
17010
|
|
|
17011
17011
|
// src/cli.ts
|
|
17012
17012
|
var log = (...args) => console.log(...args);
|