@dylanrussell/agent-router 2.1.1 → 2.2.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 +12 -0
- package/README.md +77 -3
- package/dist/cli.js +1 -1
- package/dist/cli.js.map +1 -1
- package/dist/plugin.js +580 -243
- package/dist/plugin.js.map +1 -1
- package/dist/tui.js +2 -3
- package/dist/tui.js.map +1 -1
- package/package.json +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
# 2.2.0
|
|
2
|
+
|
|
3
|
+
- Add separately opt-in, explicitly paid-approved native same-session quota fallback for automatic main turns and positively correlated new child admissions.
|
|
4
|
+
- Require single-use, short-lived HTTP rejection evidence and structured quota errors; preserve pin/manual/cancel guards, chain bounds, native model attribution, and completed tool history.
|
|
5
|
+
- Report selected-versus-dispatched state and document best-effort correlation plus the accepted non-atomic late-veto residual selection.
|
|
6
|
+
- Add production-router native synthetic quota fallback checks and conservative correlation/control tests, including strict quota RPC projection, unresolved-request expiry, and child-ticket capacity guards.
|
|
7
|
+
|
|
8
|
+
# 2.1.2
|
|
9
|
+
|
|
10
|
+
- Remove selection-source labels from agent headings; show only the agent name.
|
|
11
|
+
- Keep selected models orange with normal font weight. Selection logic and precedence are unchanged.
|
|
12
|
+
|
|
1
13
|
# 2.1.1
|
|
2
14
|
|
|
3
15
|
- Highlight selected models for every agent in the native warning/orange color, preserving precedence order and complete identities.
|
package/README.md
CHANGED
|
@@ -231,13 +231,13 @@ the configured primary. Retry hooks and same-turn retry behavior are unchanged.
|
|
|
231
231
|
selection events guard asynchronous admission, but the host offers no atomic
|
|
232
232
|
compare-and-switch.
|
|
233
233
|
|
|
234
|
-
**Explicit session controls:** with preflight enabled, the server exposes three
|
|
234
|
+
**Explicit session controls:** with preflight or quota fallback enabled, the server exposes three
|
|
235
235
|
additional tools. Pin/auto tools are for explicit user requests, under the host's
|
|
236
236
|
normal tool-permission policy. They take no model or session arguments; their
|
|
237
237
|
scope is the calling session.
|
|
238
238
|
|
|
239
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
|
|
240
|
+
model when no selection is stored. It disables quota preflight and same-turn quota fallback, and clears staged
|
|
241
241
|
reactive fallback for this session. The pin persists in server plugin storage.
|
|
242
242
|
Pins share one durable value capped at 1,024 sessions across restarts. Serialized
|
|
243
243
|
writes prevent lost updates; session deletion removes its durable pin, including
|
|
@@ -272,6 +272,80 @@ use `{ providerID, source, models, connection: { type, id }, approval }` for sav
|
|
|
272
272
|
credentials (`{ type: "env", name }` for environment connections). Router options
|
|
273
273
|
do not contain credentials or binding attestations.
|
|
274
274
|
|
|
275
|
+
### Opt-in same-turn quota fallback (phase 2, native 2.0.8)
|
|
276
|
+
|
|
277
|
+
Configure this separately from `quotaPreflight` in the server plugin's `options`:
|
|
278
|
+
|
|
279
|
+
```json
|
|
280
|
+
{
|
|
281
|
+
"quotaFallback": {
|
|
282
|
+
"enabled": true,
|
|
283
|
+
"allowPaidFallbacks": true,
|
|
284
|
+
"maxSwitches": 8
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
Both booleans default to **false**. Phase 2 requires explicit paid-fallback approval
|
|
290
|
+
before switching, including when quota-service bindings exist. `maxSwitches` is an
|
|
291
|
+
integer from 1 to 8 (default 8); only later entries in the configured chain are
|
|
292
|
+
eligible. Each explicit main-session admission and each newly admitted automatic
|
|
293
|
+
child gets its own budget, shared by all tool continuations in that turn. There is
|
|
294
|
+
no wraparound. Confirmed, fresh, account-scoped exhausted backups are skipped;
|
|
295
|
+
unknown or unavailable quota-service evidence does not block an approved backup.
|
|
296
|
+
|
|
297
|
+
The router requests a **native same-session retry** only for a structured
|
|
298
|
+
`provider.quota` failure with matching HTTP 402/429 rejection evidence. It never
|
|
299
|
+
submits another prompt, starts a replacement child, or retries a partial stream.
|
|
300
|
+
Authentication, timeouts, generic rate limits, 5xx, WebSockets, auxiliary requests,
|
|
301
|
+
and unsupported endpoints are ineligible. Existing reactive next-turn handling
|
|
302
|
+
continues to apply to its qualifying non-quota errors. Disabling phase 2 preserves
|
|
303
|
+
the previous retry policy.
|
|
304
|
+
|
|
305
|
+
Correlation is deliberately conservative: exact request-object identity,
|
|
306
|
+
agent/model/variant and admission generation, configured base URL plus a recognized
|
|
307
|
+
`/chat/completions`, `/responses`, or `/messages` operation, no URL credentials or
|
|
308
|
+
query, single-use evidence, and a five-second monotonic expiry. Observations are
|
|
309
|
+
bounded to 1,024 sessions and periodically pruned; no response bodies are read.
|
|
310
|
+
Concurrent observations and any auxiliary traffic poison the admission, including
|
|
311
|
+
an auxiliary HTTP 200 that may still be streaming. Capacity exhaustion fails closed.
|
|
312
|
+
Expiry removes retry permission but retains an unresolved/ambiguous-request
|
|
313
|
+
tombstone until the admission ends or a new admission replaces it. Quota RPC
|
|
314
|
+
candidates contain only provider/model IDs; configured variants remain attached
|
|
315
|
+
to the eventual model selection.
|
|
316
|
+
|
|
317
|
+
Explicit main model selections, original child model overrides, and resumed child
|
|
318
|
+
tasks are not claimed merely because their models match a chain. Automatic child
|
|
319
|
+
ownership requires a fresh admission ticket, a unique running parent tool call,
|
|
320
|
+
matching parent/agent/model, and a matching digest of the native child's initial
|
|
321
|
+
user message. Parent tool metadata is checked when available. Tickets expire after
|
|
322
|
+
five seconds; ambiguous concurrent child admissions are skipped. Neither prompt
|
|
323
|
+
text nor response bodies are retained in this correlation state.
|
|
324
|
+
Native metadata binding the child to a different parent call vetoes fingerprint
|
|
325
|
+
matching. Ticket overflow disables new automatic child claims until plugin reload,
|
|
326
|
+
including claims already awaiting host reads; dropping negative evidence cannot
|
|
327
|
+
make a child eligible.
|
|
328
|
+
|
|
329
|
+
**Accepted host limits:** native 2.0.8 retry hooks lack request ID, request kind,
|
|
330
|
+
output-started, cancellation, and atomic switch-and-retry fields. Correlation and
|
|
331
|
+
observable manual/cancel guards are therefore best effort, not transactional
|
|
332
|
+
guarantees. Same-model picker no-ops remain unobservable; use `router_pin`.
|
|
333
|
+
A later retry-hook veto can leave the backup selected without dispatching it.
|
|
334
|
+
The router does not roll back that selection, which could overwrite a newer user
|
|
335
|
+
choice. Status/log reasons distinguish
|
|
336
|
+
`quota_fallback_selected_retry_requested_not_confirmed` from
|
|
337
|
+
`quota_fallback_attempt_dispatched`; the latter observes the HTTP request hook,
|
|
338
|
+
not provider acceptance or successful completion.
|
|
339
|
+
|
|
340
|
+
After building, `npm run test:quota-fallback` runs the production router in a
|
|
341
|
+
disposable native 2.0.8 host with synthetic local providers. Set
|
|
342
|
+
`ROUTER_PREFLIGHT=1` to exercise both opt-ins together. The fixture verifies first
|
|
343
|
+
quota rejection, main/child post-tool continuation with a durable counter of one,
|
|
344
|
+
chain exhaustion, partial stream, explicit selections, manual/cancel/pin gates,
|
|
345
|
+
compaction, attribution, and the accepted later-veto residual selection. Its
|
|
346
|
+
timeout control vetoes native timeout retries only after recording router policy.
|
|
347
|
+
No real inference or credentials are used.
|
|
348
|
+
|
|
275
349
|
### Install This Checkout
|
|
276
350
|
|
|
277
351
|
To test a local V2 checkout, run `npm run typecheck`, `npm test`, and `npm run build` (a fresh checkout uses `pnpm install --frozen-lockfile`). Replace the registry entry in the server `opencode.json` **plugins** array with the package directory:
|
|
@@ -306,7 +380,7 @@ The plugin exposes six tools the agent (or you, by asking it) can call:
|
|
|
306
380
|
The V2 terminal half loads from the package's `./tui` export (`cli.json`, wired up by `init`):
|
|
307
381
|
|
|
308
382
|
- **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** — every agent's selected model is highlighted in the warning/orange color
|
|
383
|
+
- **Current selection** — every agent's selected model is highlighted in the warning/orange color at normal font weight with `●`. Headings show only the agent name. Selection prefers the viewed session, then running direct children at the same location, then the native agent default, then the stack default; conflicting active children retain multiple distinct selections. Out-of-chain selections are shown separately. 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. Default highlights do not imply a running session or predict quota preflight.
|
|
310
384
|
- **Routing visibility** — the native CLI has no connected routing-status transport yet, so mode/freshness are shown as unknown rather than inferred from model selection. Use `router_routing_status` for the current session's actual Automatic/Pinned state and reason.
|
|
311
385
|
- **Commands** — type `/` or open the command palette:
|
|
312
386
|
|
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.
|
|
17009
|
+
var VERSION = "2.2.0";
|
|
17010
17010
|
|
|
17011
17011
|
// src/cli.ts
|
|
17012
17012
|
var log = (...args) => console.log(...args);
|