@dylanrussell/agent-router 2.0.2 → 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 +8 -0
- package/README.md +95 -0
- 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/package.json +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
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
|
+
|
|
1
9
|
# 2.0.2
|
|
2
10
|
|
|
3
11
|
- Simplify stack chains to one model per line in precedence order, without Primary/Fallback labels.
|
package/README.md
CHANGED
|
@@ -177,6 +177,101 @@ Duplicate failures advance only once per admitted user turn. Routing budgets are
|
|
|
177
177
|
|
|
178
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
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.
|
|
274
|
+
|
|
180
275
|
### Install This Checkout
|
|
181
276
|
|
|
182
277
|
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:
|
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);
|