@magpie-community/opencode-zcode-auth 0.1.21 → 0.1.23

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 (2) hide show
  1. package/index.mjs +73 -29
  2. package/package.json +1 -1
package/index.mjs CHANGED
@@ -29,7 +29,7 @@ const BIGMODEL_API = "https://bigmodel.cn" // BigModel's business API, where ZCo
29
29
  const ZAI_BASE = "https://api.z.ai/api/anthropic"
30
30
  const BIGMODEL_BASE = "https://open.bigmodel.cn/api/anthropic"
31
31
  const START_BASE = ZCODE + "/api/v1/zcode-plan/anthropic"
32
- const APP_VERSION = "3.14.3" // the ZCode whose sign-in this makes
32
+ const APP_VERSION = "3.16.3" // the ZCode whose sign-in this makes
33
33
  const UA = "ZCode/" + APP_VERSION
34
34
 
35
35
  // ZCode's models before its config is read; the Start Plan has all but GLM-5.3.
@@ -578,13 +578,16 @@ async function claimHint(s) {
578
578
 
579
579
  // startUsage is a gift-only account's card: its buckets, or the words
580
580
  // for having none to show. The card's header already names the plan, so
581
- // the windows keep their own names.
581
+ // the windows of one plan keep their own names; with several plans each
582
+ // bucket is named after its plan (see byPlan).
582
583
  const NO_START = "this account has no GLM Coding Plan, and ZCode's Start Plan has ended or was never started"
583
584
  async function startUsage(s) {
584
585
  const g = await giftOf(s)
585
586
  if (!g) return { error: NO_START }
586
587
  const best = bestBuckets(g.windows)
587
- g.windows = g.windows.map(({ _plan, _spent, ...w }, i) => {
588
+ const label = byPlan(g.windows)
589
+ g.windows = countedFirst(g.windows.map(({ _plan, _spent, ...w }, i) => {
590
+ w.name = label(w.name, _plan)
588
591
  if (!w.models?.length) return w
589
592
  // a model two plans give (Trust Build's and the Start Plan's Flash)
590
593
  // counts on the bucket ZCode spends now; the other stays on the card
@@ -595,10 +598,28 @@ async function startUsage(s) {
595
598
  return { ...w, aside: true }
596
599
  }
597
600
  return { ...w, models: [...models, ...models.map(giftID)] }
598
- })
601
+ }))
599
602
  return g
600
603
  }
601
604
 
605
+ // byPlan names a bucket after its plan ("ZCode 1024 Dev Day · GLM-5.3")
606
+ // when the gift's buckets come from more than one plan: two plans each
607
+ // give a GLM-5.3, and named alike a spent one and a live one can't be
608
+ // told apart (01huadalang, Discord: the new-user plan's spent GLM-5.3
609
+ // showed, the 1024 plan's own GLM-5.3 didn't). One plan's buckets keep
610
+ // their own names, as the card's header names the plan.
611
+ function byPlan(windows) {
612
+ const several = new Set(windows.map((w) => w._plan || "")).size > 1
613
+ return (name, plan) => (several && plan ? plan + " · " + name : name)
614
+ }
615
+
616
+ // countedFirst puts the buckets a request spends before those set aside
617
+ // (a spent bucket another plan's live one stands in for), each group in
618
+ // the balance's order: magpie's account row shows a card's first two
619
+ // windows and leaves the rest to its tooltip, so a spent plan listed first
620
+ // hid the live plan's allowance for the same model.
621
+ const countedFirst = (ws) => [...ws.filter((w) => !w.aside), ...ws.filter((w) => w.aside)]
622
+
602
623
  // bestBuckets is, for each model the gift's buckets serve, the index of
603
624
  // the one a request spends: a live one before a spent one, the least
604
625
  // used of those. The server picks among an account's buckets itself
@@ -641,19 +662,21 @@ async function dualUsage(s) {
641
662
  if (notModels.length) out.windows = out.windows.map((w) => w.aside ? w : { ...w, notModels })
642
663
  // Several buckets may serve one model: one spent sibling cannot block it.
643
664
  const best = bestBuckets(g.windows)
644
- out.windows.push(...g.windows.map(({ _plan: p, _spent, ...w }, i) => {
665
+ const label = byPlan(g.windows)
666
+ out.windows.push(...countedFirst(g.windows.map(({ _plan: p, _spent, ...w }, i) => {
645
667
  const selected = gift.allModels.filter((m) => best.get(m.toLowerCase()) === i)
646
668
  const models = selected.map(giftID)
647
669
  const scoped = models.length ? { ...w, models } : { ...w, aside: true }
648
670
  // the card names a bucket's model as the picker does (GLM-5.3-Flash-Trial);
649
- // no plan prefix — the card's section header already says the account
671
+ // no plan prefix while one plan gives them all — the card's section
672
+ // header already says the account; with several, byPlan names each
650
673
  let name = w.name
651
674
  for (const m of selected) {
652
675
  const at = name.toLowerCase().indexOf(m.toLowerCase())
653
676
  if (at >= 0) name = name.slice(0, at) + giftID(m) + name.slice(at + m.length)
654
677
  }
655
- return { ...scoped, name }
656
- }))
678
+ return { ...scoped, name: label(name, p) }
679
+ })))
657
680
  }
658
681
  } catch {
659
682
  if (cached) {
@@ -1400,28 +1423,48 @@ function intl() {
1400
1423
  }
1401
1424
  }
1402
1425
 
1403
- // startHeaders puts ZCode's headers on a Start Plan request, jwt its key.
1426
+ // startHeaders is a Start Plan request's headers, jwt its key: ZCode's
1427
+ // own (3.16.3's Frn and Vdt in glm/zcode.cjs) and the body's content-type,
1428
+ // and nothing else. The agent's headers never go on: Claude Code's
1429
+ // anthropic-beta, x-app, x-stainless-*, anthropic-dangerous-direct-browser-
1430
+ // access and x-claude-code-session-id reach the plugin through magpie's
1431
+ // gateway, and ZCode sends none of them (no anthropic-beta at all on the
1432
+ // Start Plan: its tool search beta is for coding plans only). Accept and
1433
+ // accept-encoding are left to the HTTP client, as ZCode leaves them to
1434
+ // Node's.
1404
1435
  function startHeaders(h, jwt) {
1405
- h.delete("x-api-key")
1406
- h.delete("authorization")
1407
- h.delete("X-Device-Mid")
1408
- h.set("Authorization", "Bearer " + jwt)
1409
- h.set("anthropic-version", "2023-06-01")
1410
- h.set("HTTP-Referer", ZCODE)
1411
- h.set("User-Agent", UA + " ai-sdk/anthropic/3.0.81")
1412
- h.set("X-ZCode-App-Version", APP_VERSION)
1413
- h.set("X-Title", "Z Code@cli")
1414
- h.set("X-Release-Channel", "production")
1436
+ const out = new Headers()
1437
+ out.set("content-type", h.get("content-type") || "application/json")
1438
+ out.set("Authorization", "Bearer " + jwt)
1439
+ out.set("anthropic-version", "2023-06-01")
1440
+ out.set("HTTP-Referer", ZCODE)
1441
+ out.set("User-Agent", UA + " ai-sdk/anthropic/3.0.81")
1442
+ out.set("X-ZCode-App-Version", APP_VERSION)
1443
+ out.set("X-Title", "Z Code@cli")
1444
+ out.set("X-Release-Channel", "production")
1415
1445
  const o = intl()
1416
- h.set("X-Client-Language", o.locale || "unknown")
1417
- if (o.timeZone) h.set("X-Client-Timezone", o.timeZone)
1418
- h.set("X-ZCode-Agent", "glm")
1419
- h.set("X-Platform", platform())
1420
- h.set("X-Os-Category", osCategory())
1421
- h.set("X-Os-Version", osVersion())
1422
- h.set("x-request-id", uuid())
1423
- h.set("x-zcode-session-type", "main")
1424
- h.set("x-zcode-trace-id", uuid())
1446
+ out.set("X-Client-Language", o.locale || "unknown")
1447
+ out.set("X-Client-Timezone", o.timeZone || "unknown")
1448
+ out.set("X-ZCode-Agent", "glm")
1449
+ out.set("X-Platform", platform())
1450
+ out.set("X-Os-Category", osCategory())
1451
+ // os.release() alone, as ZCode's buildZCodeSourceHeadersFromContext
1452
+ // has it; the prompt's OS line is osVersion()
1453
+ out.set("X-Os-Version", release())
1454
+ out.set("x-request-id", uuid())
1455
+ out.set("x-zcode-session-type", "main")
1456
+ out.set("x-zcode-trace-id", uuid())
1457
+ // 3.16's createModelRequestAttributionHeaders: what asked the model
1458
+ out.set("x-zcode-query-source", "main_turn")
1459
+ return out
1460
+ }
1461
+
1462
+ // startURL is a Start Plan request's URL without the query the agent put
1463
+ // on it: Claude Code asks /v1/messages?beta=true, which magpie passes on,
1464
+ // and ZCode asks /v1/messages alone.
1465
+ function startURL(url) {
1466
+ const i = url.indexOf("?")
1467
+ return i < 0 ? url : url.slice(0, i)
1425
1468
  }
1426
1469
 
1427
1470
  // WORK_DIR and WORK_GIT are where magpie tells a plugin's fetch the agent
@@ -1660,7 +1703,8 @@ export async function ZCodeAuthPlugin({ client }) {
1660
1703
  if (!s.jwt) throw new Error("ZCode's sign-in has no key; sign in again")
1661
1704
  swap(START_BASE)
1662
1705
  // the Start Plan is served only to what looks like ZCode's own request
1663
- startHeaders(h, s.jwt)
1706
+ url = startURL(url)
1707
+ h = startHeaders(h, s.jwt)
1664
1708
  if (opts.body != null) {
1665
1709
  const text = orig ?? (typeof opts.body === "string" ? opts.body : await new Response(opts.body).text())
1666
1710
  opts.body = dress(text, s.site, s.device, place)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@magpie-community/opencode-zcode-auth",
3
- "version": "0.1.21",
3
+ "version": "0.1.23",
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",