@magpie-community/opencode-zcode-auth 0.1.19 → 0.1.20

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.
Files changed (3) hide show
  1. package/README.md +9 -0
  2. package/index.mjs +43 -5
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -32,6 +32,15 @@ over Anthropic's Messages API. Provider id: `zcode`.
32
32
  group".
33
33
  - The Start Plan's token can't be refreshed. When it runs out, sign in
34
34
  again.
35
+ - **ZCode: a team's GLM Coding Plan**
36
+ - For an account with a plan of its own and a seat on a team's plan
37
+ (#285). The sign-ins above take the account's own plan, as ZCode does
38
+ by default; this one asks which site, signs in the same way, and
39
+ takes the team seat's `zcode-team-api-key`, as ZCode does when its
40
+ plan picker is switched to the team's plan.
41
+ - It is kept as an account of its own, named `<email> (team)`, beside
42
+ the account's own plan, so both can be used.
43
+ - With no seat on a team's plan, it says so and signs in to nothing.
35
44
  - **ZCode app's sign-in**
36
45
  - Uses the account the ZCode app on this computer is signed in to. For
37
46
  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
- async function signedIn(site, token, jwt, device) {
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
- async function authorize(site, log) {
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
  },
@@ -1733,6 +1753,24 @@ export async function ZCodeAuthPlugin({ client }) {
1733
1753
  methods: [
1734
1754
  oauth("zai"),
1735
1755
  oauth("bigmodel"),
1756
+ // a team's plan beside the account's own (#285): the sign-ins above
1757
+ // take the account's own plan when it has one
1758
+ {
1759
+ type: "oauth",
1760
+ label: "ZCode: a team's GLM Coding Plan",
1761
+ prompts: [
1762
+ {
1763
+ type: "select",
1764
+ key: "site",
1765
+ message: "Where is the team's plan?",
1766
+ options: [
1767
+ { label: "Z.ai", value: "zai", hint: "z.ai" },
1768
+ { label: "BigModel (智谱)", value: "bigmodel", hint: "bigmodel.cn" },
1769
+ ],
1770
+ },
1771
+ ],
1772
+ authorize: (inputs) => authorize(inputs?.site === "bigmodel" ? "bigmodel" : "zai", log, true),
1773
+ },
1736
1774
  { type: "oauth", label: "ZCode app's sign-in", authorize: async () => asZCode() },
1737
1775
  {
1738
1776
  type: "api",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@magpie-community/opencode-zcode-auth",
3
- "version": "0.1.19",
3
+ "version": "0.1.20",
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",