@magpie-community/opencode-cursor-auth 0.2.31 → 0.2.32

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 +7 -2
  2. package/index.mjs +34 -9
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -240,6 +240,11 @@ go without the list for 5 minutes instead of each waiting for it again.
240
240
  ## Usage
241
241
 
242
242
  magpie shows Cursor Models, Other Models and Total for the billing period.
243
+ A plan of Cursor's merged billing (`GetPlanInfo`'s `isMerged`, the newer
244
+ plans) has no Other Models pool: its included usage is one allowance every
245
+ model draws on, as the dashboard's "Weekly usage limit" shows it. magpie
246
+ shows that as one window, Weekly (Monthly on a monthly plan), for every
247
+ model.
243
248
  Accounts with a Grok Bot allowance also show its usage and reset time;
244
249
  active trials are labelled separately. A spent Bot allowance doesn't stop
245
250
  Cursor requests.
@@ -273,8 +278,8 @@ In magpie, open the Cursor provider, turn on **Included usage only** under
273
278
  applies to every Cursor account, and takes effect at each account's next
274
279
  usage reading.
275
280
 
276
- When on, Cursor Models and Other Models (an Enterprise account's allowance)
277
- are what keep an account in routing: once one is used up, magpie moves its
281
+ When on, Cursor Models and Other Models (a merged plan's Weekly, an
282
+ Enterprise account's allowance) are what keep an account in routing: once one is used up, magpie moves its
278
283
  models to the next account until the period resets, even when on-demand
279
284
  could still pay for them. On-demand and Total are still shown but never
280
285
  keep an account in routing. Use it when on-demand is a shared or paid pool
package/index.mjs CHANGED
@@ -316,18 +316,27 @@ async function whoIs(tok) {
316
316
 
317
317
  // plans are the plan each token's account is on, as `cursor-agent about`
318
318
  // names it (GetPlanInfo's planName, magpie's card title), asked again after
319
- // an hour.
319
+ // an hour. merged is GetPlanInfo's isMerged: a plan of Cursor's merged
320
+ // (xAI) billing, whose included usage is one allowance for every model,
321
+ // most of them a week long (includedUsagePeriod), and has no Other Models
322
+ // pool (majiang_ai on X). The dashboard's usage page shows such a plan one
323
+ // meter, the period's totalPercentUsed. period is "weekly", "monthly" or
324
+ // "" (not said). A reply that couldn't be read keeps the last one, else
325
+ // says nothing: undefined merged, which the pools are kept for.
320
326
  const plans = new Map()
321
327
  const PLAN_TTL = 3600_000
328
+ const PERIODS = { INCLUDED_USAGE_PERIOD_WEEKLY: "weekly", INCLUDED_USAGE_PERIOD_MONTHLY: "monthly", 1: "monthly", 2: "weekly" }
322
329
  async function planOf(tok) {
323
330
  const had = plans.get(tok)
324
- if (had && Date.now() - had.at < PLAN_TTL) return had.plan
331
+ if (had && Date.now() - had.at < PLAN_TTL) return had
325
332
  try {
326
- const plan = String((await unary(API, "aiserver.v1.DashboardService/GetPlanInfo", tok))?.planInfo?.planName ?? "").trim()
327
- if (plan) plans.set(tok, { plan, at: Date.now() })
328
- return plan || had?.plan || ""
333
+ const info = await unary(API, "aiserver.v1.DashboardService/GetPlanInfo", tok)
334
+ const plan = String(info?.planInfo?.planName ?? "").trim()
335
+ const got = { plan: plan || had?.plan || "", merged: info?.isMerged === true, period: PERIODS[info?.planInfo?.includedUsagePeriod] ?? "", at: Date.now() }
336
+ if (plan || got.merged) plans.set(tok, got)
337
+ return got
329
338
  } catch {
330
- return had?.plan ?? ""
339
+ return had ?? { plan: "" }
331
340
  }
332
341
  }
333
342
 
@@ -617,7 +626,9 @@ async function enterpriseUsage(tok, includedOnly = false) {
617
626
  // the pools are the allowance whatever on-demand allows, and On-demand is
618
627
  // shown only. An Enterprise account's period has no planUsage; its
619
628
  // allowance comes from usage-summary instead.
620
- async function usage(tok, ids, includedOnly = false) {
629
+ // plan is planOf's answer, asked alongside (a promise): a merged plan's
630
+ // included usage is one window, Weekly on a weekly plan, for every model.
631
+ async function usage(tok, ids, includedOnly = false, plan = undefined) {
621
632
  const [res, hard] = await Promise.all([
622
633
  fetch(API + "/aiserver.v1.DashboardService/GetCurrentPeriodUsage", {
623
634
  method: "POST",
@@ -661,6 +672,19 @@ async function usage(tok, ids, includedOnly = false) {
661
672
  : od.kind === "unlimited"
662
673
  ? [{ name: "On-demand", used: 0, display: dollars(od.usedDollars), ...resets, aside: true }]
663
674
  : []
675
+ // A merged plan has no pools: its included usage is one allowance every
676
+ // model draws on, which the dashboard shows as the period's
677
+ // totalPercentUsed, autoPercentUsed the same and apiPercentUsed 0 always.
678
+ const info = await plan
679
+ if (info?.merged === true) {
680
+ const weekly = info.period === "weekly"
681
+ return {
682
+ windows: [
683
+ { name: weekly ? "Weekly" : info.period === "monthly" ? "Monthly" : "Included", used: num(u.totalPercentUsed), ...resets, ...(weekly ? { span: 604800 } : {}), ...pooled },
684
+ ...onDemand,
685
+ ],
686
+ }
687
+ }
664
688
  // the two pools fit the line; the total goes in its tooltip
665
689
  return {
666
690
  windows: [
@@ -3233,7 +3257,7 @@ export async function CursorAuthPlugin(input) {
3233
3257
  key: INCLUDED_ONLY,
3234
3258
  label: "Included usage only",
3235
3259
  description:
3236
- "Keeps an account in routing only while its included usage lasts: once Cursor Models or Other Models is used up, magpie moves those models to the next account until the period resets, even if on-demand could pay. On-demand and Total are still shown but never keep an account in routing.",
3260
+ "Keeps an account in routing only while its included usage lasts: once an included pool (Cursor Models, Other Models, a newer plan's Weekly) is used up, magpie moves its models to the next account until it resets, even if on-demand could pay. On-demand and Total never keep an account in routing.",
3237
3261
  },
3238
3262
  ],
3239
3263
  // magpie's: how much of the plan's included usage is gone (the plan
@@ -3246,7 +3270,8 @@ export async function CursorAuthPlugin(input) {
3246
3270
  } catch (e) {
3247
3271
  return { error: e.message, windows: [], signIn: "kept" }
3248
3272
  }
3249
- const [u, plan, bot] = await Promise.all([usage(tok, Object.keys(provider?.models ?? {}), includedOnly()), planOf(tok), botUsage(tok)])
3273
+ const info = planOf(tok)
3274
+ const [u, { plan }, bot] = await Promise.all([usage(tok, Object.keys(provider?.models ?? {}), includedOnly(), info), info, botUsage(tok)])
3250
3275
  // Bot goes among magpie's three menu-bar rings: before Total, and
3251
3276
  // before an On-demand with no limit, which is only a dollar figure on
3252
3277
  // a ring that never fills (magpie #2213, Morganwan90). An On-demand
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@magpie-community/opencode-cursor-auth",
3
- "version": "0.2.31",
3
+ "version": "0.2.32",
4
4
  "description": "Cursor subscriptions (Pro, Pro+, Ultra, Teams) in OpenCode and magpie, through the API cursor-agent talks to",
5
5
  "type": "module",
6
6
  "main": "./index.mjs",