@magpie-community/opencode-zcode-auth 0.1.25 → 0.1.27
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 +21 -8
- package/index.mjs +70 -25
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -25,12 +25,14 @@ over Anthropic's Messages API. Provider id: `zcode`.
|
|
|
25
25
|
agent's system prompt at the end of the third (a fourth block is
|
|
26
26
|
refused, #343), the day in a `<system-reminder>` turn before the agent's
|
|
27
27
|
turns, and the sign-in's device id in `metadata.user_id`. GLM Coding
|
|
28
|
-
Plan and team requests go as the agent sent them.
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
group
|
|
28
|
+
Plan and team requests go as the agent sent them. zcode.z.ai also
|
|
29
|
+
answers 405 code 3012 to every request of an account its risk control
|
|
30
|
+
blocked, ZCode's own app's included (plugins#348). That answer comes
|
|
31
|
+
back as ZCode's words, then "ZCode's risk control blocked this account
|
|
32
|
+
for unusual activity (code 3012); …", which magpie reads as the account
|
|
33
|
+
restricted: it rests, and the group's other providers are used. Only
|
|
34
|
+
ZCode support lifts such a block. A block page from ZCode's edge
|
|
35
|
+
firewall says this network's address was blocked instead.
|
|
34
36
|
- The Start Plan's token can't be refreshed. When it runs out, sign in
|
|
35
37
|
again.
|
|
36
38
|
- **ZCode: a team's GLM Coding Plan**
|
|
@@ -57,7 +59,9 @@ over Anthropic's Messages API. Provider id: `zcode`.
|
|
|
57
59
|
Start Plan, ZCode 1024 Dev Day) are served to ZCode's own session,
|
|
58
60
|
which a key doesn't carry: for an account with only a gift plan, the
|
|
59
61
|
card and each refused request (1113) say to sign in with ZCode
|
|
60
|
-
instead.
|
|
62
|
+
instead. For an account with a GLM Coding Plan, the card says the
|
|
63
|
+
gift plans' `-Trial` models need ZCode's sign-in, since a key lists
|
|
64
|
+
none of them.
|
|
61
65
|
|
|
62
66
|
## Where the sign-in is kept
|
|
63
67
|
|
|
@@ -139,12 +143,21 @@ that fails, or lists nothing, adds no line at all, and a card that is an
|
|
|
139
143
|
error keeps its error. Claim the plan in the ZCode app (open it once);
|
|
140
144
|
the next read shows it as an ordinary gift bucket.
|
|
141
145
|
|
|
146
|
+
**No ZCode session.** A card read with a key, or with a sign-in whose
|
|
147
|
+
ZCode session has run out (it can't be renewed), sets aside a line named
|
|
148
|
+
"ZCode gift plans (-Trial models) need ZCode's sign-in", with why in its
|
|
149
|
+
display: such an account reads no gift and lists no `-Trial` entries.
|
|
150
|
+
Sign in again with ZCode to get them back. A gift read that fails
|
|
151
|
+
otherwise is asked again a minute later, not ten.
|
|
152
|
+
|
|
142
153
|
## Models
|
|
143
154
|
|
|
144
155
|
The models are the ones ZCode offers for the account's plan. They come
|
|
145
156
|
from ZCode's provider config: the release zcode.z.ai names, or an
|
|
146
157
|
installed ZCode's copy if that one is newer. The list is kept for 10
|
|
147
|
-
minutes. When the config can't be read, the plugin falls back to this list
|
|
158
|
+
minutes. When the config can't be read, the plugin falls back to this list
|
|
159
|
+
(and magpie keeps the list it was told last, unless the account's gift
|
|
160
|
+
plans add `-Trial` entries, which are told as read):
|
|
148
161
|
|
|
149
162
|
| Model | Context | Output | Efforts |
|
|
150
163
|
|---|---|---|---|
|
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
|
|
@@ -616,6 +623,21 @@ async function claimHint(s) {
|
|
|
616
623
|
return { name: CLAIM_HINT, used: 0, aside: true, display: `${n} · ${plan}` }
|
|
617
624
|
}
|
|
618
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
|
+
|
|
619
641
|
// startUsage is a gift-only account's card: its buckets, or the words
|
|
620
642
|
// for having none to show. The card's header already names the plan, so
|
|
621
643
|
// the windows of one plan keep their own names; with several plans each
|
|
@@ -1416,39 +1438,51 @@ function model(m, url) {
|
|
|
1416
1438
|
}
|
|
1417
1439
|
|
|
1418
1440
|
// ---- the Start Plan's requests ----------------------------------------------------
|
|
1419
|
-
// zcode.z.ai
|
|
1420
|
-
//
|
|
1421
|
-
//
|
|
1441
|
+
// zcode.z.ai answers 405 "request has been blocked due to unusual
|
|
1442
|
+
// activity" (code 3012) to a request that doesn't look like ZCode's own
|
|
1443
|
+
// (#343: the agent's system prompt as a fourth block), and to every
|
|
1444
|
+
// request of an account its risk control blocked, ZCode's own app's too
|
|
1445
|
+
// (plugins#348). A Start Plan request goes as the plugin
|
|
1422
1446
|
// the plan serves (ARNO's "Freeflow", provider zcode-start) sends it: its
|
|
1423
1447
|
// headers (startHeaders) and its body (dress). The texts are prompt.mjs.
|
|
1424
1448
|
|
|
1425
|
-
//
|
|
1426
|
-
//
|
|
1427
|
-
//
|
|
1428
|
-
//
|
|
1429
|
-
//
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
const
|
|
1433
|
-
|
|
1434
|
-
//
|
|
1435
|
-
//
|
|
1436
|
-
const
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1449
|
+
// START_RESTRICTED is what ZCode's 3012, "request has been blocked due to
|
|
1450
|
+
// unusual activity", means: ZCode's risk control blocked the account
|
|
1451
|
+
// (ZCode's support says so, and ZCode's own app gets the same 405 on such
|
|
1452
|
+
// an account, plugins#348), not that the request was sent wrong. Word for
|
|
1453
|
+
// word magpie's provider.ZCodeRestrictedHint: the gateway reads it as the
|
|
1454
|
+
// account restricted, rests it and asks the group's next member, and the
|
|
1455
|
+
// Routing page says it in the user's language.
|
|
1456
|
+
const START_RESTRICTED = "ZCode's risk control blocked this account for unusual activity (code 3012); it rests, and the group's other providers are used. If the ZCode app fails on this account too, only ZCode support can lift the block"
|
|
1457
|
+
// START_EDGE is what a block page from ZCode's edge firewall (Aliyun's)
|
|
1458
|
+
// means: this network's address, not the account. Word for word magpie's
|
|
1459
|
+
// provider.BlockedHint.
|
|
1460
|
+
const START_EDGE = "the provider's network firewall blocked requests from this IP; wait a while, or switch to another network or proxy"
|
|
1461
|
+
const EDGE_PAGE = /errors\.aliyun\.com|<html/i
|
|
1462
|
+
const START_REFUSED = /unusual activity|request has been blocked|"code"\s*:\s*"?3012\b/i
|
|
1463
|
+
|
|
1464
|
+
// startRefused says a Start Plan answer is a refusal: a 405, a block page
|
|
1465
|
+
// or code 3012.
|
|
1466
|
+
const startRefused = (status, text) => status >= 400 && (status === 405 || START_REFUSED.test(text))
|
|
1467
|
+
|
|
1468
|
+
// startBlocked is the refusal's answer: what the vendor said (its status
|
|
1469
|
+
// for a block page), then what it means. A block page is the network's;
|
|
1470
|
+
// anything else, ZCode's JSON 3012 or a bare 405, the account's.
|
|
1440
1471
|
function startBlocked(res, text) {
|
|
1472
|
+
const page = EDGE_PAGE.test(text)
|
|
1441
1473
|
let said = ""
|
|
1442
|
-
if (!
|
|
1474
|
+
if (!page) {
|
|
1443
1475
|
try {
|
|
1444
1476
|
const v = JSON.parse(text)
|
|
1445
1477
|
said = first(v?.error?.message, typeof v?.error === "string" ? v.error : "", v?.message, v?.msg)
|
|
1478
|
+
const code = v?.code ?? v?.error?.code
|
|
1479
|
+
if (said && code != null && !String(said).includes(String(code))) said = `${said} (${res.status}, code ${code})`
|
|
1446
1480
|
} catch {}
|
|
1447
1481
|
}
|
|
1448
1482
|
said ||= `${res.status} ${STATUS_TEXT[res.status] ?? res.statusText}`.trim()
|
|
1449
1483
|
const h = new Headers(res.headers)
|
|
1450
1484
|
h.set("content-type", "application/json")
|
|
1451
|
-
const error = { type: "permission_error", message: `${said} — ${
|
|
1485
|
+
const error = { type: "permission_error", message: `${said} — ${page ? START_EDGE : START_RESTRICTED}` }
|
|
1452
1486
|
return new Response(JSON.stringify({ type: "error", error }), { status: res.status, statusText: res.statusText, headers: h })
|
|
1453
1487
|
}
|
|
1454
1488
|
|
|
@@ -1781,7 +1815,11 @@ export async function ZCodeAuthPlugin({ client }) {
|
|
|
1781
1815
|
if (out[id]) continue
|
|
1782
1816
|
out[id] = model({ ...about(raw), id }, url)
|
|
1783
1817
|
}
|
|
1784
|
-
|
|
1818
|
+
// a fallback tells magpie to keep the list it was told last, which
|
|
1819
|
+
// predates the gift read just made: an account whose gift lists
|
|
1820
|
+
// trial entries is told this list, so ZCode's config out of reach
|
|
1821
|
+
// (a remote box that can't get its CDN) never hides them
|
|
1822
|
+
if (fell && !giftNames(gift).length) out[Symbol.for("magpie.fellBack")] = true
|
|
1785
1823
|
return out
|
|
1786
1824
|
},
|
|
1787
1825
|
},
|
|
@@ -1874,7 +1912,7 @@ export async function ZCodeAuthPlugin({ client }) {
|
|
|
1874
1912
|
}
|
|
1875
1913
|
let res = await fetch(url, { ...opts, headers: h })
|
|
1876
1914
|
// the Start Plan turning the request away says what to do about
|
|
1877
|
-
// it,
|
|
1915
|
+
// it: the account blocked, or the network
|
|
1878
1916
|
if (start && res.status >= 400) {
|
|
1879
1917
|
const text = await res.text()
|
|
1880
1918
|
if (startRefused(res.status, text)) return kept(startBlocked(res, text))
|
|
@@ -1953,6 +1991,10 @@ export async function ZCodeAuthPlugin({ client }) {
|
|
|
1953
1991
|
if (!card.error) {
|
|
1954
1992
|
const hint = await claimHint(s)
|
|
1955
1993
|
if (hint) card.windows = [...(card.windows ?? []), hint]
|
|
1994
|
+
// a key, or a ZCode session that ran out: no gift read, so no
|
|
1995
|
+
// -Trial models, said on the card rather than left out unsaid
|
|
1996
|
+
const need = start ? null : giftSignIn(s, auth?.type === "api")
|
|
1997
|
+
if (need) card.windows = [...(card.windows ?? []), need]
|
|
1956
1998
|
}
|
|
1957
1999
|
return card
|
|
1958
2000
|
} catch (e) {
|
|
@@ -2002,4 +2044,7 @@ export async function ZCodeAuthPlugin({ client }) {
|
|
|
2002
2044
|
}
|
|
2003
2045
|
|
|
2004
2046
|
// for tests
|
|
2005
|
-
|
|
2047
|
+
// config sets what zcodeConfig has read, for tests: null is ZCode's config
|
|
2048
|
+
// out of reach, undefined forgets it
|
|
2049
|
+
const config = (cfg) => (cfgCache = cfg === undefined ? null : { cfg, at: Date.now() })
|
|
2050
|
+
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.27",
|
|
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",
|