@magpie-community/opencode-cursor-auth 0.2.0 → 0.2.2

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 +3 -1
  2. package/index.mjs +35 -3
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -87,7 +87,9 @@ minutes), the way pi-cursor-sdk lists Cursor's catalog:
87
87
  sent as the model's effort parameter. `none` turns a Claude's thinking off.
88
88
  - Fast is not a model of its own either: a `service_tier` of `priority`
89
89
  or `fast` sends `fast=true`, anything else `fast=false` (it costs more,
90
- so only when asked).
90
+ so only when asked). A model listed at a size Cursor has a fast variant
91
+ of (served to the account) says `fast: true`, which magpie offers its
92
+ Fast switch for (yetone/magpie#1360).
91
93
  - A request goes as the picker's variant those parameters pick, in Max Mode
92
94
  when that variant is Max Mode's (a 1M size, say), as the CLI turns it on.
93
95
  A size with no variant goes in Max Mode when it is over Cursor's limit
package/index.mjs CHANGED
@@ -542,17 +542,26 @@ function modelsOf(picker, ids) {
542
542
  const id = m.name + "@" + c
543
543
  if (used.has(id)) continue
544
544
  used.add(id)
545
- out.push({ ...base, id, name: base.title + " @ " + c, context: tokensOf(c) || DEFAULT_CONTEXT, size: c })
545
+ out.push({ ...base, id, name: base.title + " @ " + c, context: tokensOf(c) || DEFAULT_CONTEXT, size: c, offersFast: fastAt(variants, c) })
546
546
  }
547
547
  } else if (!used.has(m.name)) {
548
548
  used.add(m.name)
549
549
  const limit = needsMax(m, def) ? m.contextTokenLimitForMaxMode || m.contextTokenLimit : m.contextTokenLimit
550
- out.push({ ...base, id: m.name === "default" ? "auto" : m.name, name: base.title, context: limit > 0 ? limit : DEFAULT_CONTEXT, size: "" })
550
+ out.push({ ...base, id: m.name === "default" ? "auto" : m.name, name: base.title, context: limit > 0 ? limit : DEFAULT_CONTEXT, size: "", offersFast: fastAt(variants, "") })
551
551
  }
552
552
  }
553
553
  return out
554
554
  }
555
555
 
556
+ // fastAt is whether Cursor has a fast variant the account is served at
557
+ // the context size (any, for a model without sizes): what magpie offers
558
+ // fast for, which 0.1.x said with a -fast model of its own.
559
+ const fastAt = (variants, size) =>
560
+ variants.some((v) => {
561
+ const have = valuesOf(v)
562
+ return have.fast === "true" && (!size || have.context === undefined || have.context === size)
563
+ })
564
+
556
565
  // nearest is the variant of vs most like the parameters wanted, one at
557
566
  // their context size before any other.
558
567
  function nearest(vs, want) {
@@ -592,7 +601,7 @@ function pick(entry, effort, fast, seed) {
592
601
  const have = valuesOf(v)
593
602
  return Object.keys({ ...have, ...want }).every((k) => have[k] === undefined || want[k] === undefined || have[k] === want[k])
594
603
  }
595
- const v = entry.variants.find(same) ?? (entry.partial ? nearest(entry.variants, want) : undefined)
604
+ const v = entry.variants.find(same) ?? (seed ? branch(entry, want) : undefined) ?? (entry.partial ? nearest(entry.variants, want) : undefined)
596
605
  const params = Object.entries(v ? { ...want, ...valuesOf(v) } : want).map(([id, value]) => ({ id, value }))
597
606
  // no variant: Max Mode when the size is more than Cursor allows outside it
598
607
  const maxMode = v ? needsMax(entry.model, v) : needsMax(entry.model, def) || tokensOf(entry.size) > (entry.model.contextTokenLimit || Infinity)
@@ -603,6 +612,26 @@ function pick(entry, effort, fast, seed) {
603
612
  return { id, params, maxMode }
604
613
  }
605
614
 
615
+ // branch is, for an id of Cursor's own asked at an effort no variant has
616
+ // with the rest of its parameters (claude-opus-5-low at xhigh: Opus 5
617
+ // without thinking stops at high), the variant with those parameters at the
618
+ // nearest effort it has, not the default's id with parameters that
619
+ // contradict it (claude-opus-5-thinking-high with thinking=false). Where
620
+ // the default differs from what is asked in the effort alone, the effort
621
+ // goes as asked, as for a listed model.
622
+ function branch(entry, want) {
623
+ if (!entry.pid || entry.pid === "thinking") return undefined
624
+ const def = valuesOf(entry.def)
625
+ if (Object.keys(want).every((k) => k === entry.pid || k === "context" || def[k] === undefined || def[k] === want[k])) return undefined
626
+ const vs = entry.variants.filter((v) => {
627
+ const have = valuesOf(v)
628
+ return entry.pid in have && Object.keys(want).every((k) => k === entry.pid || have[k] === undefined || have[k] === want[k])
629
+ })
630
+ const level = (x) => (x === "extra-high" ? "xhigh" : x)
631
+ const at = fitEffort(level(want[entry.pid]), vs.map((v) => level(valuesOf(v)[entry.pid])))
632
+ return at ? vs.find((v) => level(valuesOf(v)[entry.pid]) === at) : undefined
633
+ }
634
+
606
635
  // fitEffort is the nearest effort a model has to the one asked for; max
607
636
  // for ultra, and none only when asked.
608
637
  function fitEffort(want, levels) {
@@ -714,6 +743,9 @@ function runtimeModel(m) {
714
743
  },
715
744
  release_date: "",
716
745
  variants: Object.fromEntries(efforts.map((e) => [e, { reasoningEffort: e }])),
746
+ // a request's service_tier priority (or fast) runs it as Cursor's fast
747
+ // variant: magpie offers Fast for the models that have one
748
+ ...(m.offersFast ? { fast: true } : {}),
717
749
  }
718
750
  }
719
751
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@magpie-community/opencode-cursor-auth",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
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",