@magpie-community/opencode-zcode-auth 0.1.9 → 0.1.11
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/README.md +18 -0
- package/index.mjs +65 -16
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -92,6 +92,18 @@ behind an error, so a gift hiccup must not black out a working Coding
|
|
|
92
92
|
Plan. A gift that goes out of date while requests use it simply stops
|
|
93
93
|
showing.
|
|
94
94
|
|
|
95
|
+
**Gift plans ZCode holds but has not granted.** ZCode hands out one-off
|
|
96
|
+
trust-build / gift plans (a day's ZCode Trust Build, say) that are not
|
|
97
|
+
on the account until the ZCode app claims them. The plugin reads the
|
|
98
|
+
app's own list of them (`GET /api/v1/zcode-plan/billing/preview`) with
|
|
99
|
+
the card and names them there — "1 to claim · claim it in the ZCode app"
|
|
100
|
+
— set aside, so the line stops nothing and routing, usage caps and the
|
|
101
|
+
menu bar pass it over. The plugin never claims one: the claim needs the
|
|
102
|
+
Aliyun captcha attestation only the app's renderer can make. A preview
|
|
103
|
+
that fails, or lists nothing, adds no line at all, and a card that is an
|
|
104
|
+
error keeps its error. Claim the plan in the ZCode app (open it once);
|
|
105
|
+
the next read shows it as an ordinary gift bucket.
|
|
106
|
+
|
|
95
107
|
## Models
|
|
96
108
|
|
|
97
109
|
The models are the ones ZCode offers for the account's plan. They come
|
|
@@ -112,3 +124,9 @@ A gift plan's models appear again as `<model>-Trial` entries, so a
|
|
|
112
124
|
request can spend the gift's quota on purpose. A trial entry is listed
|
|
113
125
|
while any live bucket serves its model, spent buckets included (a spent
|
|
114
126
|
entry answers 429 rather than vanishing mid-session).
|
|
127
|
+
|
|
128
|
+
Two plans can give one model (ZCode Trust Build and the Start Plan both
|
|
129
|
+
give GLM-5.3-Flash). The server picks the bucket, so the usage card
|
|
130
|
+
counts the model on its live bucket, the least used, and sets a spent
|
|
131
|
+
sibling aside. A spent sibling never makes the model, or the account,
|
|
132
|
+
look used up while another bucket still has quota.
|
package/index.mjs
CHANGED
|
@@ -531,6 +531,30 @@ async function giftOf(s) {
|
|
|
531
531
|
return out
|
|
532
532
|
}
|
|
533
533
|
|
|
534
|
+
// claimHint is the card's line for gift plans ZCode is holding for the
|
|
535
|
+
// account but has not put on it: GET /billing/preview lists them, and
|
|
536
|
+
// only the ZCode app claims one — its claim takes the Aliyun captcha
|
|
537
|
+
// attestation the app's own renderer makes, so the plugin reads the list
|
|
538
|
+
// and asks the user to claim it there. A window, set aside (it is no
|
|
539
|
+
// allowance: using it up stops nothing), so the card shows it and
|
|
540
|
+
// routing, caps and the menu bar pass it over. null when there is
|
|
541
|
+
// nothing to claim, the preview failing or listing none among it: a
|
|
542
|
+
// failed read is no line at all, never a card or a refusal of its own.
|
|
543
|
+
async function claimHint(s) {
|
|
544
|
+
if (!s.jwt || jwtExpired(s.jwt)) return null
|
|
545
|
+
let d
|
|
546
|
+
try {
|
|
547
|
+
d = await call("GET", `${ZCODE}/api/v1/zcode-plan/billing/preview?app_version=${APP_VERSION}&platform=${platform()}`, { auth: "Bearer " + s.jwt, device: s.device })
|
|
548
|
+
} catch {
|
|
549
|
+
return null
|
|
550
|
+
}
|
|
551
|
+
const plans = (Array.isArray(d?.plans) ? d.plans : []).filter((p) => typeof p?.plan_id === "string" && p.plan_id.trim())
|
|
552
|
+
if (!plans.length) return null
|
|
553
|
+
const n = plans.length
|
|
554
|
+
const name = first(...plans.map((p) => (typeof p?.name === "string" ? p.name : "")), "ZCode gift plan")
|
|
555
|
+
return { name, used: 0, aside: true, display: `${n} to claim · claim ${n === 1 ? "it" : "them"} in the ZCode app` }
|
|
556
|
+
}
|
|
557
|
+
|
|
534
558
|
// startUsage is a gift-only account's card: its buckets, or the words
|
|
535
559
|
// for having none to show. The card's header already names the plan, so
|
|
536
560
|
// the windows keep their own names.
|
|
@@ -538,14 +562,38 @@ const NO_START = "this account has no GLM Coding Plan, and ZCode's Start Plan ha
|
|
|
538
562
|
async function startUsage(s) {
|
|
539
563
|
const g = await giftOf(s)
|
|
540
564
|
if (!g) return { error: NO_START }
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
565
|
+
const best = bestBuckets(g.windows)
|
|
566
|
+
g.windows = g.windows.map(({ _plan, _spent, ...w }, i) => {
|
|
567
|
+
if (!w.models?.length) return w
|
|
568
|
+
// a model two plans give (Trust Build's and the Start Plan's Flash)
|
|
569
|
+
// counts on the bucket ZCode spends now; the other stays on the card
|
|
570
|
+
// without holding the model up (ganlerk, Discord)
|
|
571
|
+
const models = w.models.filter((m) => best.get(m.toLowerCase()) === i)
|
|
572
|
+
if (!models.length) {
|
|
573
|
+
delete w.models
|
|
574
|
+
return { ...w, aside: true }
|
|
575
|
+
}
|
|
576
|
+
return { ...w, models: [...models, ...models.map(giftID)] }
|
|
577
|
+
})
|
|
546
578
|
return g
|
|
547
579
|
}
|
|
548
580
|
|
|
581
|
+
// bestBuckets is, for each model the gift's buckets serve, the index of
|
|
582
|
+
// the one a request spends: a live one before a spent one, the least
|
|
583
|
+
// used of those. The server picks among an account's buckets itself
|
|
584
|
+
// (ZCode sends no plan with a request), so one spent bucket doesn't stop
|
|
585
|
+
// a model another still has.
|
|
586
|
+
function bestBuckets(windows) {
|
|
587
|
+
const best = new Map()
|
|
588
|
+
windows.forEach((w, i) => {
|
|
589
|
+
for (const m of w.models ?? []) {
|
|
590
|
+
const key = m.toLowerCase(), old = best.get(key), prev = windows[old]
|
|
591
|
+
if (old === undefined || (prev._spent && !w._spent) || (prev._spent === w._spent && w.used < prev.used)) best.set(key, i)
|
|
592
|
+
}
|
|
593
|
+
})
|
|
594
|
+
return best
|
|
595
|
+
}
|
|
596
|
+
|
|
549
597
|
// dualUsage shows both pools but only the pool a request can use counts
|
|
550
598
|
// for its model. Live gift models don't spend the Coding windows; spent
|
|
551
599
|
// or blocked gift buckets stay visible without holding up the Coding Plan.
|
|
@@ -571,13 +619,7 @@ async function dualUsage(s) {
|
|
|
571
619
|
const notModels = gift.allModels.map((m) => giftID(m).toLowerCase())
|
|
572
620
|
if (notModels.length) out.windows = out.windows.map((w) => w.aside ? w : { ...w, notModels })
|
|
573
621
|
// Several buckets may serve one model: one spent sibling cannot block it.
|
|
574
|
-
const best =
|
|
575
|
-
g.windows.forEach((w, i) => {
|
|
576
|
-
for (const m of w.models ?? []) {
|
|
577
|
-
const key = m.toLowerCase(), old = best.get(key), prev = g.windows[old]
|
|
578
|
-
if (old === undefined || (prev._spent && !w._spent) || (prev._spent === w._spent && w.used < prev.used)) best.set(key, i)
|
|
579
|
-
}
|
|
580
|
-
})
|
|
622
|
+
const best = bestBuckets(g.windows)
|
|
581
623
|
out.windows.push(...g.windows.map(({ _plan: p, _spent, ...w }, i) => {
|
|
582
624
|
const selected = gift.allModels.filter((m) => best.get(m.toLowerCase()) === i)
|
|
583
625
|
const models = selected.map(giftID)
|
|
@@ -1505,9 +1547,16 @@ export async function ZCodeAuthPlugin({ client }) {
|
|
|
1505
1547
|
return saved(await teamUsage(s, key))
|
|
1506
1548
|
}
|
|
1507
1549
|
const { start, gift } = await plansOf(s)
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1550
|
+
const card = saved(start ? await startUsage(s) : gift ? await dualUsage(s) : await codingUsage(s))
|
|
1551
|
+
// a gift plan ZCode holds for the account but has not put on it:
|
|
1552
|
+
// named on the card, claimed in the ZCode app (its claim needs
|
|
1553
|
+
// the app's captcha attestation, see claimHint). A card that is
|
|
1554
|
+
// an error keeps its error and asks nothing
|
|
1555
|
+
if (!card.error) {
|
|
1556
|
+
const hint = await claimHint(s)
|
|
1557
|
+
if (hint) card.windows = [...(card.windows ?? []), hint]
|
|
1558
|
+
}
|
|
1559
|
+
return card
|
|
1511
1560
|
} catch (e) {
|
|
1512
1561
|
return saved({ error: e?.message ?? String(e) })
|
|
1513
1562
|
}
|
|
@@ -1537,4 +1586,4 @@ export async function ZCodeAuthPlugin({ client }) {
|
|
|
1537
1586
|
}
|
|
1538
1587
|
|
|
1539
1588
|
// for tests
|
|
1540
|
-
export const _internal = { entry, limitWindows, termOf, startUsage, routes, blocked, plansOf, giftOf, dualUsage, spentUp, giftServes, modelOf, teamKeys, ownSignIn, stateOf, dress, PROMPT }
|
|
1589
|
+
export const _internal = { entry, limitWindows, termOf, startUsage, routes, blocked, plansOf, giftOf, dualUsage, claimHint, spentUp, giftServes, modelOf, teamKeys, ownSignIn, stateOf, dress, PROMPT }
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@magpie-community/opencode-zcode-auth",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.11",
|
|
4
4
|
"description": "OpenCode provider plugin: signs in to Z.ai's or BigModel's (智谱) GLM Coding Plan as ZCode does, including team seats and ZCode's Start Plan",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./index.mjs",
|