@magpie-community/opencode-zcode-auth 0.1.19 → 0.1.21
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 +12 -2
- package/index.mjs +55 -14
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -21,8 +21,9 @@ over Anthropic's Messages API. Provider id: `zcode`.
|
|
|
21
21
|
- zcode.z.ai serves the Start Plan only to requests that look like the
|
|
22
22
|
ZCode client's own, and refuses others with HTTP 405 "request has been
|
|
23
23
|
blocked due to unusual activity". So a Start Plan request goes as
|
|
24
|
-
ZCode's does: ZCode's headers, ZCode's system
|
|
25
|
-
agent's
|
|
24
|
+
ZCode's does: ZCode's headers, ZCode's three system blocks with the
|
|
25
|
+
agent's system prompt at the end of the third (a fourth block is
|
|
26
|
+
refused, #343), the day in a `<system-reminder>` turn before the agent's
|
|
26
27
|
turns, and the sign-in's device id in `metadata.user_id`. GLM Coding
|
|
27
28
|
Plan and team requests go as the agent sent them. One it still turns
|
|
28
29
|
away (a 405, the block page or code 3012) comes back with what to do
|
|
@@ -32,6 +33,15 @@ over Anthropic's Messages API. Provider id: `zcode`.
|
|
|
32
33
|
group".
|
|
33
34
|
- The Start Plan's token can't be refreshed. When it runs out, sign in
|
|
34
35
|
again.
|
|
36
|
+
- **ZCode: a team's GLM Coding Plan**
|
|
37
|
+
- For an account with a plan of its own and a seat on a team's plan
|
|
38
|
+
(#285). The sign-ins above take the account's own plan, as ZCode does
|
|
39
|
+
by default; this one asks which site, signs in the same way, and
|
|
40
|
+
takes the team seat's `zcode-team-api-key`, as ZCode does when its
|
|
41
|
+
plan picker is switched to the team's plan.
|
|
42
|
+
- It is kept as an account of its own, named `<email> (team)`, beside
|
|
43
|
+
the account's own plan, so both can be used.
|
|
44
|
+
- With no seat on a team's plan, it says so and signs in to nothing.
|
|
35
45
|
- **ZCode app's sign-in**
|
|
36
46
|
- Uses the account the ZCode app on this computer is signed in to. For
|
|
37
47
|
every request it reads ZCode's own credentials (`~/.zcode/v2`), so it
|
package/index.mjs
CHANGED
|
@@ -847,13 +847,29 @@ async function teamSignIn(site, root, auth, info) {
|
|
|
847
847
|
|
|
848
848
|
// signedIn is what a sign-in gives: the account's coding plan key and plan;
|
|
849
849
|
// or, with none of its own, a seat on a team's plan; or else ZCode's token
|
|
850
|
-
// for its Start Plan while the account has one.
|
|
851
|
-
|
|
850
|
+
// for its Start Plan while the account has one. Asked for the team's plan
|
|
851
|
+
// (onTeam), it is the team seat alone, as ZCode's plan picker gives a team
|
|
852
|
+
// plan beside the account's own (a "team-coding-plan" selection): an
|
|
853
|
+
// account with both is signed in to each as an account of its own (#285).
|
|
854
|
+
async function signedIn(site, token, jwt, device, onTeam = false) {
|
|
852
855
|
const name = SITES[site].name
|
|
853
856
|
const root = SITES[site].api
|
|
854
857
|
let s = null
|
|
855
858
|
let err = null
|
|
856
859
|
let team = ""
|
|
860
|
+
if (onTeam) {
|
|
861
|
+
const auth = await bizAuth(site, token)
|
|
862
|
+
let info
|
|
863
|
+
try {
|
|
864
|
+
info = await call("GET", root + "/api/biz/customer/getCustomerInfo", { auth })
|
|
865
|
+
} catch (e) {
|
|
866
|
+
throw new Error(`${name} account: ${e.message}`)
|
|
867
|
+
}
|
|
868
|
+
const t = await teamSignIn(site, root, auth, info)
|
|
869
|
+
if (t.s) return { ...t.s, jwt, plan: t.plan }
|
|
870
|
+
if (t.none) throw new Error(`this ${name} account has no seat on a team's GLM Coding Plan — sign in with "ZCode: ${name} GLM Coding Plan" for its own plan`)
|
|
871
|
+
throw new Error(t.why ?? t.err)
|
|
872
|
+
}
|
|
857
873
|
try {
|
|
858
874
|
const auth = await bizAuth(site, token)
|
|
859
875
|
let info
|
|
@@ -891,11 +907,15 @@ async function signedIn(site, token, jwt, device) {
|
|
|
891
907
|
)
|
|
892
908
|
}
|
|
893
909
|
|
|
910
|
+
// TEAM marks a team seat's account name beside the account's own.
|
|
911
|
+
const TEAM = "team"
|
|
894
912
|
const who = (u) => first(String(u?.email ?? "").replace(/@phone\.local$/, ""), u?.name, u?.user_id, "ZCode")
|
|
895
913
|
const sleep = (ms) => new Promise((r) => setTimeout(r, ms))
|
|
896
914
|
|
|
897
915
|
// authorize opens ZCode's sign-in flow on site; its callback polls it.
|
|
898
|
-
|
|
916
|
+
// onTeam signs in to the account's seat on a team's plan, named apart from
|
|
917
|
+
// the account's own plan (the host keeps one entry per account name).
|
|
918
|
+
async function authorize(site, log, onTeam = false) {
|
|
899
919
|
const poll = "Bearer " + Buffer.from(crypto.getRandomValues(new Uint8Array(32))).toString("hex")
|
|
900
920
|
const device = uuid()
|
|
901
921
|
let flow
|
|
@@ -936,7 +956,7 @@ async function authorize(site, log) {
|
|
|
936
956
|
if (got.status !== "ready" || !token) return fail("ZCode sign-in: unexpected answer " + got.status)
|
|
937
957
|
let s
|
|
938
958
|
try {
|
|
939
|
-
s = await signedIn(site, token, first(got.token), device)
|
|
959
|
+
s = await signedIn(site, token, first(got.token), device, onTeam)
|
|
940
960
|
} catch (e) {
|
|
941
961
|
return fail(e.message)
|
|
942
962
|
}
|
|
@@ -947,7 +967,7 @@ async function authorize(site, log) {
|
|
|
947
967
|
access: s.key || s.jwt || "",
|
|
948
968
|
// the key doesn't run out; ZCode's token, when it is all there is, does
|
|
949
969
|
expires: s.key || isTeam(s) ? 0 : jwtExpiry(s.jwt),
|
|
950
|
-
accountId: who(got.user),
|
|
970
|
+
accountId: onTeam ? `${who(got.user)} (${TEAM})` : who(got.user),
|
|
951
971
|
}
|
|
952
972
|
}
|
|
953
973
|
},
|
|
@@ -1464,7 +1484,8 @@ function contextPrefix() {
|
|
|
1464
1484
|
}
|
|
1465
1485
|
|
|
1466
1486
|
// dress is a Messages request body as ZCode sends it: ZCode's three cached
|
|
1467
|
-
// system blocks,
|
|
1487
|
+
// system blocks and no more, the agent's own system text at the end of the
|
|
1488
|
+
// third (#343); the context
|
|
1468
1489
|
// prefix as the first turn; no cache mark in the turns but on the last
|
|
1469
1490
|
// block of the last; none on the tools; metadata.user_id naming the
|
|
1470
1491
|
// sign-in's device. site names the powered-by line's provider, place where
|
|
@@ -1482,18 +1503,20 @@ function dress(text, site, device, place) {
|
|
|
1482
1503
|
const cached = (t) => ({ type: "text", text: t, cache_control: { type: "ephemeral" } })
|
|
1483
1504
|
const provider = site === "bigmodel" ? "bigmodel-api" : "zai-api"
|
|
1484
1505
|
const model = typeof b.model === "string" ? b.model : ""
|
|
1506
|
+
// The agent's own system text joins the third block, as ZCode's
|
|
1507
|
+
// ContextBuilder (3.14.3, glm/zcode.cjs assembleSystemMessages) joins
|
|
1508
|
+
// every dynamic system section, an added one too, with "\n\n" into
|
|
1509
|
+
// that one block: ZCode never sends more than three. zcode.z.ai turns a
|
|
1510
|
+
// fourth block away with 405/3012 (#343), and the first two must stay
|
|
1511
|
+
// byte for byte ZCode's.
|
|
1485
1512
|
const own = []
|
|
1486
1513
|
if (typeof b.system === "string") {
|
|
1487
|
-
if (b.system.trim()) own.push(
|
|
1514
|
+
if (b.system.trim()) own.push(b.system)
|
|
1488
1515
|
} else if (Array.isArray(b.system)) {
|
|
1489
|
-
for (const x of b.system) if (x?.type === "text" && typeof x.text === "string" && x.text) own.push(
|
|
1516
|
+
for (const x of b.system) if (x?.type === "text" && typeof x.text === "string" && x.text.trim()) own.push(x.text)
|
|
1490
1517
|
}
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
cached(PROMPT.stableSections.join("\n\n")),
|
|
1494
|
-
cached("\n\n" + [PROMPT.beforeEnvironment, environment(provider, model, place), PROMPT.afterEnvironment].join("\n\n")),
|
|
1495
|
-
...own,
|
|
1496
|
-
]
|
|
1518
|
+
const dynamic = [PROMPT.beforeEnvironment, environment(provider, model, place), PROMPT.afterEnvironment, ...own]
|
|
1519
|
+
b.system = [cached(PROMPT.cliPrefix), cached(PROMPT.stableSections.join("\n\n")), cached("\n\n" + dynamic.join("\n\n"))]
|
|
1497
1520
|
b.messages = [contextPrefix(), ...b.messages]
|
|
1498
1521
|
let last = null
|
|
1499
1522
|
for (const m of b.messages) {
|
|
@@ -1733,6 +1756,24 @@ export async function ZCodeAuthPlugin({ client }) {
|
|
|
1733
1756
|
methods: [
|
|
1734
1757
|
oauth("zai"),
|
|
1735
1758
|
oauth("bigmodel"),
|
|
1759
|
+
// a team's plan beside the account's own (#285): the sign-ins above
|
|
1760
|
+
// take the account's own plan when it has one
|
|
1761
|
+
{
|
|
1762
|
+
type: "oauth",
|
|
1763
|
+
label: "ZCode: a team's GLM Coding Plan",
|
|
1764
|
+
prompts: [
|
|
1765
|
+
{
|
|
1766
|
+
type: "select",
|
|
1767
|
+
key: "site",
|
|
1768
|
+
message: "Where is the team's plan?",
|
|
1769
|
+
options: [
|
|
1770
|
+
{ label: "Z.ai", value: "zai", hint: "z.ai" },
|
|
1771
|
+
{ label: "BigModel (智谱)", value: "bigmodel", hint: "bigmodel.cn" },
|
|
1772
|
+
],
|
|
1773
|
+
},
|
|
1774
|
+
],
|
|
1775
|
+
authorize: (inputs) => authorize(inputs?.site === "bigmodel" ? "bigmodel" : "zai", log, true),
|
|
1776
|
+
},
|
|
1736
1777
|
{ type: "oauth", label: "ZCode app's sign-in", authorize: async () => asZCode() },
|
|
1737
1778
|
{
|
|
1738
1779
|
type: "api",
|
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.21",
|
|
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",
|