Repository navigation
zcode: freeFirst, the plain model spends the account's gift first - #505
Conversation
|
Thanks for this. I reviewed 371ce97 line by line and ran it. It isn't ready to merge yet; here is what I found. What was run (on macOS, Bun 1.4.2, with a temp HOME): 1. With tool search on, a JSON reply loses the ToolSearch rename (
2. The alias never reaches magpie's model list or the agents' pickers. The So the README's " 3. Many ZCode accounts have no
For those accounts, That is a vendor 400 for a name the vendor never had. It also says nothing about why the alias didn't apply. Please also match on the account's 4. What this adds over magpie's routing groups. A magpie routing group whose members are Smaller notes, not blocking:
I'd merge this once 1 to 3 are fixed and each has a test that is red on this head. |
371ce97 to
d0f02d3
Compare
|
Thanks for the careful review — I ran your probes against the reworked head before answering. The per-account alias option is withdrawn, so points 1–3 were resolved by removal rather than patching: What replaced it is Five new tests (red first): gift-first while quota lasts with no coding-plan request; fallback once spent; provider-level option honored with a blocked model waiting on the plan; a model the gift does not serve stays on the plan; and off unless asked. 156 pass, |
d0f02d3 to
829b150
Compare
|
Thanks for the rework. What was run. On macOS (Bun 1.4.2, temp HOME): What holds: the option is off unless it is set (both off forms send to the plan exactly as before). The provider's options win over the plugin's. API-key accounts (no 1. With no gift, or a failed balance read, every request throws (
|
|
All four findings fixed on 4c56bc3, with your probe list as tests, red first. 1. No gift / failed balance read. The branch no longer calls 2. Gift-only accounts. The branch now requires 3. The race. A spent gift ( 4. Options merge. -Trial with freeFirst on is pinned too: a spent gift still answers its local 429, no plan request. Full |
|
Re-reviewed 4c56bc3 line by line and ran it. The four points from the last review are fixed, and the new tests guard them. Two things in the new replay still break a request that works with What was run (mote, macOS, Bun 1.4.2, temp HOME):
1. The replay skips the plan's busy wait (
|
|
Both fixed on 1a8be2e, your scenarios as tests, red first. 1. The replay now waits out the plan's cap. The plan path's ask-and-wait moved into a module-level 2. Any gift failure is answered from the plan. The freeGift branch now distinguishes: a spent answer (
|
|
Re-reviewed 1a8be2e line by line and ran it. Both points from the last review are fixed, and the new tests guard them. One gap of the same kind as point 2 is left, so this isn't merged yet. What was run (mote, macOS, Bun 1.4.2, temp HOME):
A gift request that throws is never answered from the plan (
|
|
Fixed on 6a48562, your two tests red first. The gift's ask sits in a try whose catch answers from the plan when Not left out:
|
…ent, not a failed check-in
hykql (Discord, magpie v0.1.2143, zcode 0.1.36) saw every ZCode account's
daily check-in fail with "gift plans to claim: no plan list in the reply",
a Start Plan account and one with no GLM Coding Plan alike. ZCode's
GET /billing/preview answers an account with nothing to claim with no
data at all, not data.plans []:
{"code":0,"msg":"","logid":"202610300535585c4e3de75769b684da87"}
(the owner's account, read 10-30 with GETs only, with and without the
X-ZCode-App-Version / X-Platform headers; both the same). #503's capture
of 10-29 had "plans": [], so 0.1.35 took a missing list as unreadable.
previewPlans now reads the list for both the claim and the card's claim
line: no data, data null, or data without plans (or plans null) is a
list of none, so the check-in is "inactive" (magpie shows "No check-in
event now"). call has already judged the code, so only a code 0 reply
gets here. Data that isn't an object, or plans that aren't a list, still
don't read and stay failed, never claimed.
Run (wsl-run on magpie-desktop, HOME=$(mktemp -d); mote was at load
220-250): `bun test` in packages/zcode, 152 pass 0 fail; the whole
repo's `bun test`, 3720 pass 0 fail of 3727 across 298 files;
`bun scripts/check.mjs zcode` ok. The new checkin test (the real
no-data reply, data null, data without plans, plans null) is red on
0.1.36's index.mjs (1 fail). Broken by hand: plans that aren't a list
read as none turns "a preview that doesn't read is failed" red; put
back, green.
Not tried: a real claim (no account has a plan to claim now), and the
official ZCode client's own parse of this reply (no ZCode app on hand);
the fixture is the vendor's real bytes. Not changed: #505 (freeFirst)
touches other parts of index.mjs.
|
Re-reviewed 6a48562 line by line, against current main (7673cd0, zcode 0.1.37) as well as against 1a8be2e, and ran it. The fix itself is right: a gift that throws is answered from the plan, and the route is dropped. Two things still stop the merge. What was run (mote, macOS, Bun 1.4.2, temp HOME, on 6a48562 merged into main 7673cd0, which merges clean):
1. The version collides with main's 0.1.37 (
|
The gift's allowance would lapse unused behind an agent that only ever asks the plain model: spending the gift took renaming the request to <model>-Trial by hand. freeFirst turns the preference around: the plain model spends the account's own live gift first — under the name the gift lists — and falls back to the coding plan when the gift cannot serve it. Set it for the whole plugin in magpie's Plugins › Options, or per provider under provider.zcode.options; the provider's word stands. The -Trial entries keep their strict semantics, and a gift that runs out between the balance read and the send answers 429 once, rests the model a minute, then the plan takes the traffic.
…g else Review probes against the real plugin host found three ways freeFirst broke requests that work today: a gift that could not be read made every request throw (the branch now reads the route's cache alone, so a failed read keeps the plan with no read per request); a gift-only account was renamed and flagged where it was already on the gift (the branch now skips it); and a gift that ran out between its balance read and the send answered the agent 429 (its refusal is now replayed on the coding plan inside the same fetch, the model as the agent sent it and the plan's headers, with the minute's block and a dropped route read sending the requests behind it straight to the plan). freeFirst in a provider's options no longer overrides the plugin's until it says something, and the README names plugins.json's config as the provider-level place.
…gift failure Review found the replay returning the plan's first answer: a replay that landed on a busy plan handed magpie the raw 3008/3009 429. The plan path's ask-and-wait is now a module-level askBusy the replay goes through too. And the freeGift answer only replayed spent answers: a 500, a 401, a 400, or the gift's own waited-out busy cap went to the agent instead of the plan whose quota the request was never meant to spend. The block page and a spent answer rest the model a minute and drop the route read; a 401/403 drops the read alone, so the next request learns whether the session is gone.
…plan A throw from the gift's ask — the network, the host — went to magpie with the plan never tried, though the two live on different hosts: with freeFirst the request is replayed on the plan and the route read is dropped, so the next request learns whether the host is back. A caller's abort stays an abort, replay or no replay.
Rebased on main (7673cd0) and bumped past the 0.1.37 npm already has. The abort tests threw on every URL, so the reads failed and the request never reached the gift at all — the abort guard went untested. They now throw on the gift's messages alone, an AbortError for a signal aborted before the ask and an abort-then-TypeError for one aborted in flight, counting their tries where the fetch fake cannot see them.
6a48562 to
7ae2ea1
Compare
|
Both done on 7ae2ea1. Version. Rebased onto main (7673cd0 — clean, as you said) and bumped to 0.1.38. The abort tests now reach the gift.
With the guard reduced to |
|
Thanks @jinpy666! Merged at 7ae2ea1 after re-running it: 173/173 zcode tests pass, and both abort tests go red without the abort check. zcode 0.1.38 is on npm, and magpie v0.1.2160 raises the ZCode mover's min to it, so moved ZCode users get freeFirst on their next update. Not tried yet against a real account that has both a coding plan and a gift; if you see anything off there, please open an issue. |
What
A boolean option,
freeFirst: a plain model request spends the account's own live gift first, under the model name the gift lists, and falls back to the coding plan when the gift cannot serve it. Set it for the whole plugin in magpie's Plugins › Options{ "freeFirst": true }or per provider under
provider.zcode.options; where both say something, the provider's word stands.Why
The gift's allowance lapses unused behind an agent that only ever asks the plain model: spending the gift meant renaming the request to
<model>-Trialby hand. Turning the preference around needs no new model names, no per-account rules, nouids: an account with a coding plan and a gift spends the gift until it is spent, then the plan; a gift-only account already goes to the gift by its plain names; and across the accounts magpie rotates, each spends its own gift before its own plan.Semantics
giftUsablethe trial entries use): spent bucket, a model the gift does not serve, no ZCode session, or a model in its minute's rest after a refusal — the request stays on the coding plan.-Trialentries keep their strict semantics: an explicit pick of the gift alone, never the plan.Tests
Five new cases in
dual.test.mjs(written red first): the plain model goes to the Start Plan dressed while the gift has quota (and no coding-plan request is made); falls back to the coding plan once the gift is spent; honors the provider-level option and lets a blocked model wait on the plan; leaves a model the gift does not serve on the coding plan; and stays off unless asked. Fullpackages/zcodesuite 156 pass on current main (HOME=$(mktemp -d) bun test packages/zcode);bun scripts/check.mjsclean.This replaces the per-account alias option this PR carried before: the review's points 1–3 (the
modelNamedpromise chaining, the alias missing fromprovider.models, no-uidaccounts sending the logical name upstream) were all about that mechanism and no longer apply. The README documents the option and its boundaries.