@magpie-community/opencode-zcode-auth 0.1.24 → 0.1.26
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 +17 -1
- package/index.mjs +86 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -53,6 +53,13 @@ over Anthropic's Messages API. Provider id: `zcode`.
|
|
|
53
53
|
another's credentials: to use both, add the app's sign-in once for each.
|
|
54
54
|
- **GLM Coding Plan API key**
|
|
55
55
|
- Paste a key (`<id>.<secret>`) and say which site it is from.
|
|
56
|
+
- A key reaches the GLM Coding Plan alone. ZCode's gift plans (the
|
|
57
|
+
Start Plan, ZCode 1024 Dev Day) are served to ZCode's own session,
|
|
58
|
+
which a key doesn't carry: for an account with only a gift plan, the
|
|
59
|
+
card and each refused request (1113) say to sign in with ZCode
|
|
60
|
+
instead. For an account with a GLM Coding Plan, the card says the
|
|
61
|
+
gift plans' `-Trial` models need ZCode's sign-in, since a key lists
|
|
62
|
+
none of them.
|
|
56
63
|
|
|
57
64
|
## Where the sign-in is kept
|
|
58
65
|
|
|
@@ -134,12 +141,21 @@ that fails, or lists nothing, adds no line at all, and a card that is an
|
|
|
134
141
|
error keeps its error. Claim the plan in the ZCode app (open it once);
|
|
135
142
|
the next read shows it as an ordinary gift bucket.
|
|
136
143
|
|
|
144
|
+
**No ZCode session.** A card read with a key, or with a sign-in whose
|
|
145
|
+
ZCode session has run out (it can't be renewed), sets aside a line named
|
|
146
|
+
"ZCode gift plans (-Trial models) need ZCode's sign-in", with why in its
|
|
147
|
+
display: such an account reads no gift and lists no `-Trial` entries.
|
|
148
|
+
Sign in again with ZCode to get them back. A gift read that fails
|
|
149
|
+
otherwise is asked again a minute later, not ten.
|
|
150
|
+
|
|
137
151
|
## Models
|
|
138
152
|
|
|
139
153
|
The models are the ones ZCode offers for the account's plan. They come
|
|
140
154
|
from ZCode's provider config: the release zcode.z.ai names, or an
|
|
141
155
|
installed ZCode's copy if that one is newer. The list is kept for 10
|
|
142
|
-
minutes. When the config can't be read, the plugin falls back to this list
|
|
156
|
+
minutes. When the config can't be read, the plugin falls back to this list
|
|
157
|
+
(and magpie keeps the list it was told last, unless the account's gift
|
|
158
|
+
plans add `-Trial` entries, which are told as read):
|
|
143
159
|
|
|
144
160
|
| Model | Context | Output | Efforts |
|
|
145
161
|
|---|---|---|---|
|
package/index.mjs
CHANGED
|
@@ -214,8 +214,15 @@ async function plansOf(s) {
|
|
|
214
214
|
let sure = false
|
|
215
215
|
try {
|
|
216
216
|
if (!(await plan(s))) start = true
|
|
217
|
-
else
|
|
218
|
-
|
|
217
|
+
else {
|
|
218
|
+
// a gift read that failed is unknown, not "no gift": asked again in
|
|
219
|
+
// a minute, so its trial entries come back with the next list (an
|
|
220
|
+
// expired session is known: the card says to sign in again)
|
|
221
|
+
let failed = false
|
|
222
|
+
gift = await startPlan(s.jwt, s.device).catch(() => ((failed = !jwtExpired(s.jwt)), null))
|
|
223
|
+
sure = !failed
|
|
224
|
+
}
|
|
225
|
+
if (start) sure = true
|
|
219
226
|
} catch {
|
|
220
227
|
// the plan list could not be read: a key account takes the dual route
|
|
221
228
|
// (start stays false, the gift is kept, a minute's ttl), so a gift
|
|
@@ -437,14 +444,54 @@ async function codingUsage(s) {
|
|
|
437
444
|
if (level) out.plan = "GLM Coding " + level[0].toUpperCase() + level.slice(1)
|
|
438
445
|
out.windows = limitWindows(d)
|
|
439
446
|
const resets = personalResets(root, s.key)
|
|
447
|
+
let subs = null
|
|
440
448
|
try {
|
|
441
|
-
|
|
449
|
+
subs = await call("GET", root + "/api/biz/subscription/list", { auth: s.key })
|
|
450
|
+
Object.assign(out, termOf(subs))
|
|
442
451
|
} catch {}
|
|
443
452
|
const r = await resets
|
|
444
453
|
if (r) out.resets = r
|
|
454
|
+
// a key whose account has no plan in force, read as such, says so
|
|
455
|
+
// rather than showing an empty card: what a key can spend is a GLM
|
|
456
|
+
// Coding Plan alone (a ZCode gift plan is never one, see NO_PLAN_KEY).
|
|
457
|
+
// A list that couldn't be read, a level, a counted window or a plan
|
|
458
|
+
// the sign-in saved keeps the card as it was.
|
|
459
|
+
const valid = (Array.isArray(subs) ? subs : []).some((x) => String(x?.status ?? "").toUpperCase() === "VALID")
|
|
460
|
+
if (subs !== null && !valid && !level && !s.plan && !out.windows.some((w) => !w.aside)) return { error: NO_PLAN_KEY }
|
|
445
461
|
return out
|
|
446
462
|
}
|
|
447
463
|
|
|
464
|
+
// NO_PLAN_KEY is a key with no GLM Coding Plan behind it. ZCode's gift
|
|
465
|
+
// plans (its Start Plan, ZCode 1024 Dev Day) are served by zcode.z.ai
|
|
466
|
+
// to ZCode's own session token, which a sign-in with ZCode (the app's,
|
|
467
|
+
// or Z.ai's or BigModel's in the browser) carries and a key never does:
|
|
468
|
+
// with a key, a gift-only account has nothing to spend, and Z.ai answers
|
|
469
|
+
// each request 1113 (rtbeilin on X, 10-24).
|
|
470
|
+
const NO_PLAN_KEY =
|
|
471
|
+
"this key's account has no GLM Coding Plan; ZCode's gift plans (the Start Plan, ZCode 1024 Dev Day) are spent only with ZCode's sign-in, never with a key — add the account with \"ZCode app's sign-in\" or a ZCode sign-in in the browser"
|
|
472
|
+
|
|
473
|
+
// noPlanKey is a coding plan's 1113 refusal (no plan, no resource
|
|
474
|
+
// package) to a sign-in with no ZCode session, its message followed by
|
|
475
|
+
// NO_PLAN_KEY; anything else goes on as it came. Read only once the
|
|
476
|
+
// answer has failed.
|
|
477
|
+
function noPlanKey(res, text) {
|
|
478
|
+
let v
|
|
479
|
+
try {
|
|
480
|
+
v = JSON.parse(text)
|
|
481
|
+
} catch {
|
|
482
|
+
return null
|
|
483
|
+
}
|
|
484
|
+
// Z.ai names the code in error.code ("1113", as magpie's
|
|
485
|
+
// zhipu_coding_test has it) or error.type (its 401's "1000"), BigModel's
|
|
486
|
+
// envelope in code
|
|
487
|
+
if (![v?.error?.code, v?.error?.type, v?.code].some((c) => String(c ?? "") === "1113")) return null
|
|
488
|
+
const said = first(v?.error?.message, v?.msg, v?.message)
|
|
489
|
+
const out = v?.error && typeof v.error === "object" ? { ...v, error: { ...v.error, message: (said ? said + " — " : "") + NO_PLAN_KEY } } : { ...v, msg: (said ? said + " — " : "") + NO_PLAN_KEY }
|
|
490
|
+
const h = new Headers(res.headers)
|
|
491
|
+
h.set("content-type", "application/json")
|
|
492
|
+
return new Response(JSON.stringify(out), { status: res.status, statusText: res.statusText, headers: h })
|
|
493
|
+
}
|
|
494
|
+
|
|
448
495
|
// startNum reads a number the balance gives as a number or a string.
|
|
449
496
|
function startNum(v) {
|
|
450
497
|
if (isNum(v)) return v
|
|
@@ -576,6 +623,21 @@ async function claimHint(s) {
|
|
|
576
623
|
return { name: CLAIM_HINT, used: 0, aside: true, display: `${n} · ${plan}` }
|
|
577
624
|
}
|
|
578
625
|
|
|
626
|
+
// GIFT_SIGN_IN is the card's line for an account whose gift plans can't
|
|
627
|
+
// be read: ZCode's gift plans (the Start Plan, ZCode 1024 Dev Day, ZCode
|
|
628
|
+
// Trust Build) are served by zcode.z.ai to ZCode's own session alone, so
|
|
629
|
+
// a GLM Coding Plan key, or a sign-in whose ZCode session has run out
|
|
630
|
+
// (that token can't be renewed), lists no <model>-Trial entries and
|
|
631
|
+
// spends the coding plan alone. A fixed sentence, so magpie can
|
|
632
|
+
// translate it; why goes in the display. Set aside: it stops nothing.
|
|
633
|
+
const GIFT_SIGN_IN = "ZCode gift plans (-Trial models) need ZCode's sign-in"
|
|
634
|
+
function giftSignIn(s, key) {
|
|
635
|
+
if (isTeam(s)) return null
|
|
636
|
+
if (!s.jwt) return { name: GIFT_SIGN_IN, used: 0, aside: true, display: key ? "not read with an API key: add the account with a ZCode sign-in" : "this sign-in has no ZCode session: sign in again" }
|
|
637
|
+
if (jwtExpired(s.jwt)) return { name: GIFT_SIGN_IN, used: 0, aside: true, display: "ZCode's sign-in has expired: sign in again" }
|
|
638
|
+
return null
|
|
639
|
+
}
|
|
640
|
+
|
|
579
641
|
// startUsage is a gift-only account's card: its buckets, or the words
|
|
580
642
|
// for having none to show. The card's header already names the plan, so
|
|
581
643
|
// the windows of one plan keep their own names; with several plans each
|
|
@@ -1741,7 +1803,11 @@ export async function ZCodeAuthPlugin({ client }) {
|
|
|
1741
1803
|
if (out[id]) continue
|
|
1742
1804
|
out[id] = model({ ...about(raw), id }, url)
|
|
1743
1805
|
}
|
|
1744
|
-
|
|
1806
|
+
// a fallback tells magpie to keep the list it was told last, which
|
|
1807
|
+
// predates the gift read just made: an account whose gift lists
|
|
1808
|
+
// trial entries is told this list, so ZCode's config out of reach
|
|
1809
|
+
// (a remote box that can't get its CDN) never hides them
|
|
1810
|
+
if (fell && !giftNames(gift).length) out[Symbol.for("magpie.fellBack")] = true
|
|
1745
1811
|
return out
|
|
1746
1812
|
},
|
|
1747
1813
|
},
|
|
@@ -1840,6 +1906,14 @@ export async function ZCodeAuthPlugin({ client }) {
|
|
|
1840
1906
|
if (startRefused(res.status, text)) return kept(startBlocked(res, text))
|
|
1841
1907
|
res = new Response(text, { status: res.status, statusText: res.statusText, headers: res.headers })
|
|
1842
1908
|
}
|
|
1909
|
+
// a key with no plan behind it: what Z.ai said, and why a
|
|
1910
|
+
// ZCode gift plan can't be had with a key (NO_PLAN_KEY)
|
|
1911
|
+
if (!start && !s.jwt && res.status >= 400) {
|
|
1912
|
+
const text = await res.text()
|
|
1913
|
+
const why = noPlanKey(res, text)
|
|
1914
|
+
if (why) return done(kept(why))
|
|
1915
|
+
res = new Response(text, { status: res.status, statusText: res.statusText, headers: res.headers })
|
|
1916
|
+
}
|
|
1843
1917
|
// a trial entry's gift answer that can't serve the request is
|
|
1844
1918
|
// the agent's answer, not the coding plan's: the user picked the
|
|
1845
1919
|
// gift, so a spent bucket says 429 (its quota error inside a 200
|
|
@@ -1905,6 +1979,10 @@ export async function ZCodeAuthPlugin({ client }) {
|
|
|
1905
1979
|
if (!card.error) {
|
|
1906
1980
|
const hint = await claimHint(s)
|
|
1907
1981
|
if (hint) card.windows = [...(card.windows ?? []), hint]
|
|
1982
|
+
// a key, or a ZCode session that ran out: no gift read, so no
|
|
1983
|
+
// -Trial models, said on the card rather than left out unsaid
|
|
1984
|
+
const need = start ? null : giftSignIn(s, auth?.type === "api")
|
|
1985
|
+
if (need) card.windows = [...(card.windows ?? []), need]
|
|
1908
1986
|
}
|
|
1909
1987
|
return card
|
|
1910
1988
|
} catch (e) {
|
|
@@ -1954,4 +2032,7 @@ export async function ZCodeAuthPlugin({ client }) {
|
|
|
1954
2032
|
}
|
|
1955
2033
|
|
|
1956
2034
|
// for tests
|
|
1957
|
-
|
|
2035
|
+
// config sets what zcodeConfig has read, for tests: null is ZCode's config
|
|
2036
|
+
// out of reach, undefined forgets it
|
|
2037
|
+
const config = (cfg) => (cfgCache = cfg === undefined ? null : { cfg, at: Date.now() })
|
|
2038
|
+
export const _internal = { config, 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.26",
|
|
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",
|