@magpie-community/opencode-cursor-auth 0.2.11 → 0.2.13
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/index.mjs +101 -48
- package/package.json +1 -1
package/index.mjs
CHANGED
|
@@ -1358,17 +1358,18 @@ function usageOf(uf) {
|
|
|
1358
1358
|
// event: its step looks for it as before, and is guessed without it.
|
|
1359
1359
|
const STEP_WAIT = { first: 1500, every: 500, until: 6000, ask: 5000, skipAfter: 3, retryEvery: 10, owedAt: 5000, owedFor: 600_000 }
|
|
1360
1360
|
|
|
1361
|
-
// claimed are the usage events already counted, by conversation
|
|
1362
|
-
// so that two steps of one conversation never count the same one.
|
|
1361
|
+
// claimed are the usage events already counted, by account, conversation
|
|
1362
|
+
// and time, so that two steps of one conversation never count the same one.
|
|
1363
1363
|
const claimed = new Map()
|
|
1364
1364
|
|
|
1365
|
-
// owed are what each conversation still owes, by
|
|
1366
|
-
// whose events are to be counted,
|
|
1367
|
-
// for from ready on; and carry, a
|
|
1365
|
+
// owed are what each account's conversation still owes, by credential
|
|
1366
|
+
// fingerprint and conversation_id: n Runs whose events are to be counted,
|
|
1367
|
+
// the earliest started at since, looked for from ready on; and carry, a
|
|
1368
|
+
// count collected that no step gave out.
|
|
1368
1369
|
const owed = new Map()
|
|
1369
1370
|
|
|
1370
|
-
// flights are each
|
|
1371
|
-
// that ends the turn waits for.
|
|
1371
|
+
// flights are each account's conversation collections still going, which
|
|
1372
|
+
// a step that ends the turn waits for.
|
|
1372
1373
|
const flights = new Map()
|
|
1373
1374
|
|
|
1374
1375
|
// unreadable are the accounts (by token) whose usage events Cursor won't
|
|
@@ -1378,6 +1379,7 @@ const flights = new Map()
|
|
|
1378
1379
|
const unreadable = new Map()
|
|
1379
1380
|
const misses = new Map()
|
|
1380
1381
|
const tokKey = (tok) => createHash("sha256").update(tok).digest("hex")
|
|
1382
|
+
const usageKey = (tok, conv) => tokKey(tok) + "\0" + conv
|
|
1381
1383
|
function canRead(tok) {
|
|
1382
1384
|
const at = unreadable.get(tokKey(tok))
|
|
1383
1385
|
if (at === undefined) return true
|
|
@@ -1394,12 +1396,12 @@ function addUsage(a, b) {
|
|
|
1394
1396
|
return a
|
|
1395
1397
|
}
|
|
1396
1398
|
|
|
1397
|
-
// owe adds to conversation
|
|
1398
|
-
function owe(
|
|
1399
|
+
// owe adds to the account/conversation's debt.
|
|
1400
|
+
function owe(key, { since = Date.now(), n = 0, ready = Date.now(), carry = null }) {
|
|
1399
1401
|
for (const [k, d] of owed) if (Date.now() - d.since > STEP_WAIT.owedFor) owed.delete(k)
|
|
1400
1402
|
if (n <= 0 && !carry) return
|
|
1401
|
-
const d = owed.get(
|
|
1402
|
-
if (!d) return void owed.set(
|
|
1403
|
+
const d = owed.get(key)
|
|
1404
|
+
if (!d) return void owed.set(key, { since, n, ready, carry: carry && { ...carry } })
|
|
1403
1405
|
d.since = Math.min(d.since, since)
|
|
1404
1406
|
d.n += n
|
|
1405
1407
|
d.ready = Math.min(d.ready, ready)
|
|
@@ -1413,6 +1415,7 @@ function owe(conv, { since = Date.now(), n = 0, ready = Date.now(), carry = null
|
|
|
1413
1415
|
// Polling, they are looked for as STEP_WAIT says, from `first` on, until
|
|
1414
1416
|
// all show; else asked for once.
|
|
1415
1417
|
async function usageEvents(tok, conv, since, want, { poll = false, first = STEP_WAIT.first, signal } = {}) {
|
|
1418
|
+
const key = usageKey(tok, conv)
|
|
1416
1419
|
const end = Date.now() + STEP_WAIT.until
|
|
1417
1420
|
const wait = (ms) => new Promise((r) => {
|
|
1418
1421
|
const t = setTimeout(r, ms)
|
|
@@ -1439,11 +1442,11 @@ async function usageEvents(tok, conv, since, want, { poll = false, first = STEP_
|
|
|
1439
1442
|
}
|
|
1440
1443
|
const evs = res.ok ? ((await res.json())?.usageEventsDisplay ?? []) : []
|
|
1441
1444
|
const found = evs
|
|
1442
|
-
.filter((e) => e?.conversationId === conv && e.tokenUsage && num(e.timestamp) >= since - 1000 && !claimed.has(
|
|
1445
|
+
.filter((e) => e?.conversationId === conv && e.tokenUsage && num(e.timestamp) >= since - 1000 && !claimed.has(key + "\0" + e.timestamp))
|
|
1443
1446
|
.sort((a, b) => num(a.timestamp) - num(b.timestamp))
|
|
1444
1447
|
.slice(0, want - got)
|
|
1445
1448
|
for (const ev of found) {
|
|
1446
|
-
claimed.set(
|
|
1449
|
+
claimed.set(key + "\0" + ev.timestamp, Date.now())
|
|
1447
1450
|
const t = ev.tokenUsage
|
|
1448
1451
|
const u = { input: num(t.inputTokens), output: num(t.outputTokens), cacheRead: num(t.cacheReadTokens), cacheWrite: num(t.cacheWriteTokens), reasoning: 0 }
|
|
1449
1452
|
usage = addUsage(usage ?? ZERO(), u)
|
|
@@ -1464,31 +1467,32 @@ async function stepUsage(tok, conv, since, signal) {
|
|
|
1464
1467
|
return (await usageEvents(tok, conv, since, 1, { poll: true, signal })).usage
|
|
1465
1468
|
}
|
|
1466
1469
|
|
|
1467
|
-
// collect takes
|
|
1468
|
-
// when poll): what was carried and what was found (usage),
|
|
1469
|
-
// carried alone (carry) and the events found (events), and whether any is
|
|
1470
|
+
// collect takes the account's debt for conversation conv and asks for its
|
|
1471
|
+
// events (polling when poll): what was carried and what was found (usage),
|
|
1472
|
+
// what was carried alone (carry) and the events found (events), and whether any is
|
|
1470
1473
|
// still owed (short), which is owed on. What comes back once the Run that
|
|
1471
1474
|
// asked is over (over() true) is carried to the next instead.
|
|
1472
1475
|
function collect(tok, conv, { poll = false, first, signal, over = () => false } = {}) {
|
|
1473
|
-
const
|
|
1476
|
+
const key = usageKey(tok, conv)
|
|
1477
|
+
const d = owed.get(key)
|
|
1474
1478
|
if (!d) return Promise.resolve({ usage: null, carry: null, events: [], short: false })
|
|
1475
|
-
owed.delete(
|
|
1479
|
+
owed.delete(key)
|
|
1476
1480
|
const p = (async () => {
|
|
1477
1481
|
let r = { usage: null, events: [], got: 0 }
|
|
1478
1482
|
if (d.n > 0 && canRead(tok)) r = await usageEvents(tok, conv, d.since, d.n, { poll, first, signal }).catch(() => r)
|
|
1479
1483
|
const short = d.n > r.got && canRead(tok)
|
|
1480
|
-
if (short) owe(
|
|
1484
|
+
if (short) owe(key, { since: d.since, n: d.n - r.got, ready: d.ready })
|
|
1481
1485
|
const carry = d.carry && { ...d.carry }
|
|
1482
1486
|
const usage = addUsage(d.carry, r.usage)
|
|
1483
1487
|
if (!over()) return { usage, carry, events: r.events ?? [], short }
|
|
1484
|
-
owe(
|
|
1488
|
+
owe(key, { carry: usage })
|
|
1485
1489
|
return { usage: null, carry: null, events: [], short }
|
|
1486
1490
|
})()
|
|
1487
|
-
const set = flights.get(
|
|
1488
|
-
flights.set(
|
|
1491
|
+
const set = flights.get(key) ?? new Set()
|
|
1492
|
+
flights.set(key, set.add(p))
|
|
1489
1493
|
p.finally(() => {
|
|
1490
1494
|
set.delete(p)
|
|
1491
|
-
if (!set.size && flights.get(
|
|
1495
|
+
if (!set.size && flights.get(key) === set) flights.delete(key)
|
|
1492
1496
|
})
|
|
1493
1497
|
return p
|
|
1494
1498
|
}
|
|
@@ -1515,6 +1519,7 @@ function collect(tok, conv, { poll = false, first, signal, over = () => false }
|
|
|
1515
1519
|
// count would be told in the wrong field, never twice nor lost.
|
|
1516
1520
|
function ledger(tok, conv, since, signal, kept) {
|
|
1517
1521
|
const key = tokKey(tok)
|
|
1522
|
+
const debtKey = usageKey(tok, conv)
|
|
1518
1523
|
let mine = null // this Run's own, collected, not given out yet
|
|
1519
1524
|
let theirs = null // earlier Runs', collected, not given out yet
|
|
1520
1525
|
let over = false
|
|
@@ -1528,7 +1533,7 @@ function ledger(tok, conv, since, signal, kept) {
|
|
|
1528
1533
|
return r
|
|
1529
1534
|
})
|
|
1530
1535
|
let collecting = null
|
|
1531
|
-
const debt = kept ? owed.get(
|
|
1536
|
+
const debt = kept ? owed.get(debtKey) : undefined
|
|
1532
1537
|
const timer = debt ? setTimeout(() => (collecting = gather()), Math.max(0, debt.ready - Date.now())) : null
|
|
1533
1538
|
timer?.unref?.()
|
|
1534
1539
|
const takeMine = () => {
|
|
@@ -1552,7 +1557,7 @@ function ledger(tok, conv, since, signal, kept) {
|
|
|
1552
1557
|
else if (!r.refused) misses.set(key, m + 1)
|
|
1553
1558
|
return r.usage ?? null
|
|
1554
1559
|
}
|
|
1555
|
-
owe(
|
|
1560
|
+
owe(debtKey, { since, n: 1, ready: Date.now() + STEP_WAIT.owedAt })
|
|
1556
1561
|
if (waits) {
|
|
1557
1562
|
const r = await gather({ poll: true, signal })
|
|
1558
1563
|
if (!canRead(tok)) return null
|
|
@@ -1565,8 +1570,8 @@ function ledger(tok, conv, since, signal, kept) {
|
|
|
1565
1570
|
if (!kept) return null
|
|
1566
1571
|
if (final) {
|
|
1567
1572
|
await collecting
|
|
1568
|
-
await Promise.all([...(flights.get(
|
|
1569
|
-
if (owed.has(
|
|
1573
|
+
await Promise.all([...(flights.get(debtKey) ?? [])])
|
|
1574
|
+
if (owed.has(debtKey)) await gather({ poll: owed.get(debtKey).n > 0, first: 0, signal })
|
|
1570
1575
|
}
|
|
1571
1576
|
return take()
|
|
1572
1577
|
},
|
|
@@ -1574,7 +1579,7 @@ function ledger(tok, conv, since, signal, kept) {
|
|
|
1574
1579
|
over = true
|
|
1575
1580
|
clearTimeout(timer)
|
|
1576
1581
|
const u = take()
|
|
1577
|
-
if (u) owe(
|
|
1582
|
+
if (u) owe(debtKey, { carry: u })
|
|
1578
1583
|
},
|
|
1579
1584
|
}
|
|
1580
1585
|
}
|
|
@@ -1666,12 +1671,21 @@ async function agentURL(tok, fresh) {
|
|
|
1666
1671
|
// connection that failed (refused, no network) or a stream the server
|
|
1667
1672
|
// refused leaves the next Run to try HTTP/2 again.
|
|
1668
1673
|
let h1Until = 0
|
|
1674
|
+
const cancelledOpen = () => ({ error: { status: 410, message: "the request was cancelled" }, h2Failed: false })
|
|
1669
1675
|
async function open(base, headers, signal) {
|
|
1676
|
+
if (signal?.aborted) return cancelledOpen()
|
|
1670
1677
|
if (Date.now() >= h1Until) {
|
|
1671
1678
|
const o = await openH2(base, headers, signal)
|
|
1679
|
+
// The head can arrive just before abort, before this continuation owns it.
|
|
1680
|
+
if (signal?.aborted) {
|
|
1681
|
+
o.req?.close(http2.constants.NGHTTP2_CANCEL)
|
|
1682
|
+
o.session?.destroy()
|
|
1683
|
+
return cancelledOpen()
|
|
1684
|
+
}
|
|
1672
1685
|
if (!o.h2Failed) return o
|
|
1673
1686
|
if (o.blocked) h1Until = Date.now() + H2.retryAfter
|
|
1674
1687
|
}
|
|
1688
|
+
if (signal?.aborted) return cancelledOpen()
|
|
1675
1689
|
return openH1(headers, signal)
|
|
1676
1690
|
}
|
|
1677
1691
|
|
|
@@ -1702,6 +1716,7 @@ function h2Blocked(e) {
|
|
|
1702
1716
|
// than by being cancelled, says h2Failed, and blocked when h2Blocked says
|
|
1703
1717
|
// so of the failure.
|
|
1704
1718
|
function openH2(base, headers, signal) {
|
|
1719
|
+
if (signal?.aborted) return Promise.resolve(cancelledOpen())
|
|
1705
1720
|
return new Promise((resolve) => {
|
|
1706
1721
|
const u = new URL(base)
|
|
1707
1722
|
const session = http2.connect(u.origin)
|
|
@@ -1710,9 +1725,11 @@ function openH2(base, headers, signal) {
|
|
|
1710
1725
|
if (done) return
|
|
1711
1726
|
done = true
|
|
1712
1727
|
clearTimeout(timer)
|
|
1728
|
+
signal?.removeEventListener("abort", abort)
|
|
1713
1729
|
session.destroy()
|
|
1714
|
-
resolve({ error: { status: 502, message: e?.message ?? String(e) }, h2Failed, blocked: h2Failed && h2Blocked(e) })
|
|
1730
|
+
resolve({ error: { status: h2Failed ? 502 : 410, message: e?.message ?? String(e) }, h2Failed, blocked: h2Failed && h2Blocked(e) })
|
|
1715
1731
|
}
|
|
1732
|
+
const abort = () => fail(new Error("the request was cancelled"), false)
|
|
1716
1733
|
const timer = setTimeout(() => fail(Object.assign(new Error(`no answer over HTTP/2 in ${H2.wait / 1000}s`), { h2Timeout: true })), H2.wait)
|
|
1717
1734
|
session.on("error", fail)
|
|
1718
1735
|
const req = session.request({
|
|
@@ -1728,9 +1745,11 @@ function openH2(base, headers, signal) {
|
|
|
1728
1745
|
if (done) return
|
|
1729
1746
|
done = true
|
|
1730
1747
|
clearTimeout(timer)
|
|
1748
|
+
signal?.removeEventListener("abort", abort)
|
|
1731
1749
|
resolve({ session, req, status: Number(h[":status"]) })
|
|
1732
1750
|
})
|
|
1733
|
-
signal?.addEventListener("abort",
|
|
1751
|
+
signal?.addEventListener("abort", abort, { once: true })
|
|
1752
|
+
if (signal?.aborted) abort()
|
|
1734
1753
|
})
|
|
1735
1754
|
}
|
|
1736
1755
|
|
|
@@ -1750,23 +1769,29 @@ function connectCode(status) {
|
|
|
1750
1769
|
// ends the stream with Connect's end frame, which runOnce reads as the
|
|
1751
1770
|
// Run's own.
|
|
1752
1771
|
function openH1(headers, signal) {
|
|
1772
|
+
if (signal?.aborted) return Promise.resolve(cancelledOpen())
|
|
1753
1773
|
const ac = new AbortController()
|
|
1754
|
-
signal?.addEventListener("abort", () => ac.abort(), { once: true })
|
|
1755
1774
|
const id = headers["x-request-id"]
|
|
1756
1775
|
const h = { ...headers, "accept-encoding": "identity", "x-cursor-streaming": "true" }
|
|
1757
1776
|
let ended = false
|
|
1758
1777
|
let seq = 0
|
|
1759
|
-
let
|
|
1778
|
+
let reader
|
|
1760
1779
|
const req = new Duplex({
|
|
1761
1780
|
read() {},
|
|
1762
1781
|
write(chunk, _enc, cb) {
|
|
1763
1782
|
// runOnce writes one whole frame each time
|
|
1764
1783
|
const msg = Buffer.from(chunk).subarray(5)
|
|
1765
1784
|
const n = seq++
|
|
1766
|
-
|
|
1767
|
-
|
|
1785
|
+
// Keep the write buffered until its append finishes, so callbacks and
|
|
1786
|
+
// drain reflect the pending upload rather than an unbounded promise chain.
|
|
1787
|
+
append(msg, n).then(() => cb(), (e) => cb(e))
|
|
1768
1788
|
},
|
|
1769
1789
|
})
|
|
1790
|
+
const cleanup = () => {
|
|
1791
|
+
signal?.removeEventListener("abort", close)
|
|
1792
|
+
ac.abort()
|
|
1793
|
+
reader?.cancel().catch(() => {})
|
|
1794
|
+
}
|
|
1770
1795
|
const end = (body) => {
|
|
1771
1796
|
if (ended || req.destroyed) return
|
|
1772
1797
|
ended = true
|
|
@@ -1774,7 +1799,7 @@ function openH1(headers, signal) {
|
|
|
1774
1799
|
f[0] = 2
|
|
1775
1800
|
req.push(f)
|
|
1776
1801
|
req.push(null)
|
|
1777
|
-
|
|
1802
|
+
cleanup()
|
|
1778
1803
|
}
|
|
1779
1804
|
const failed = async (res) => {
|
|
1780
1805
|
const text = await res.text().catch(() => "")
|
|
@@ -1788,6 +1813,7 @@ function openH1(headers, signal) {
|
|
|
1788
1813
|
// (more time for a large one) ends the Run, as cursor-agent's
|
|
1789
1814
|
// bidi_append_deadline_exceeded does: the messages after it wait on it.
|
|
1790
1815
|
const append = async (msg, n) => {
|
|
1816
|
+
if (ended || ac.signal.aborted) return
|
|
1791
1817
|
const body = pb().str(1, msg.toString("hex")).bytes(2, pb().str(1, id).done()).varint(3, n).done()
|
|
1792
1818
|
const ms = H1.appendWait + Math.ceil(body.length / 65536) * 1000
|
|
1793
1819
|
const deadline = AbortSignal.timeout(ms)
|
|
@@ -1798,6 +1824,7 @@ function openH1(headers, signal) {
|
|
|
1798
1824
|
body,
|
|
1799
1825
|
signal: AbortSignal.any([ac.signal, deadline]),
|
|
1800
1826
|
})
|
|
1827
|
+
if (ended || ac.signal.aborted) { await res.body?.cancel().catch(() => {}); return }
|
|
1801
1828
|
if (!res.ok) return failed(res)
|
|
1802
1829
|
await res.arrayBuffer()
|
|
1803
1830
|
} catch (e) {
|
|
@@ -1806,6 +1833,16 @@ function openH1(headers, signal) {
|
|
|
1806
1833
|
end(JSON.stringify({ error: { code: "unavailable", message: `BidiAppend: ${e?.message ?? e}` } }))
|
|
1807
1834
|
}
|
|
1808
1835
|
}
|
|
1836
|
+
const close = () => {
|
|
1837
|
+
ended = true
|
|
1838
|
+
cleanup()
|
|
1839
|
+
req.destroy()
|
|
1840
|
+
}
|
|
1841
|
+
signal?.addEventListener("abort", close, { once: true })
|
|
1842
|
+
if (signal?.aborted) {
|
|
1843
|
+
close()
|
|
1844
|
+
return Promise.resolve(cancelledOpen())
|
|
1845
|
+
}
|
|
1809
1846
|
;(async () => {
|
|
1810
1847
|
try {
|
|
1811
1848
|
const res = await fetch(API + "/agent.v1.AgentService/RunSSE", {
|
|
@@ -1814,25 +1851,29 @@ function openH1(headers, signal) {
|
|
|
1814
1851
|
body: frame(pb().str(1, id).done()),
|
|
1815
1852
|
signal: ac.signal,
|
|
1816
1853
|
})
|
|
1854
|
+
if (ended || ac.signal.aborted) { await res.body?.cancel().catch(() => {}); return }
|
|
1817
1855
|
if (!res.ok) return failed(res)
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
req.
|
|
1856
|
+
reader = res.body.getReader()
|
|
1857
|
+
try {
|
|
1858
|
+
while (!ended && !req.destroyed) {
|
|
1859
|
+
const { value, done } = await reader.read()
|
|
1860
|
+
if (done) break
|
|
1861
|
+
if (!ended && !req.destroyed) req.push(Buffer.from(value))
|
|
1862
|
+
}
|
|
1863
|
+
} finally {
|
|
1864
|
+
reader.releaseLock()
|
|
1865
|
+
reader = undefined
|
|
1821
1866
|
}
|
|
1822
1867
|
if (!ended && !req.destroyed) {
|
|
1823
1868
|
ended = true
|
|
1824
1869
|
req.push(null)
|
|
1870
|
+
cleanup()
|
|
1825
1871
|
}
|
|
1826
1872
|
} catch (e) {
|
|
1827
1873
|
if (!ac.signal.aborted) end(JSON.stringify({ error: { code: "unavailable", message: `RunSSE: ${e?.message ?? e}` } }))
|
|
1828
1874
|
}
|
|
1829
1875
|
})()
|
|
1830
|
-
|
|
1831
|
-
ended = true
|
|
1832
|
-
ac.abort()
|
|
1833
|
-
req.destroy()
|
|
1834
|
-
}
|
|
1835
|
-
return Promise.resolve({ session: { close, destroy: close }, req: Object.assign(req, { close }), status: 200, h1: true })
|
|
1876
|
+
return Promise.resolve(signal?.aborted ? cancelledOpen() : { session: { close, destroy: close }, req: Object.assign(req, { close }), status: 200, h1: true })
|
|
1836
1877
|
}
|
|
1837
1878
|
|
|
1838
1879
|
// runOnce is one Run of the chat on the agent API at base: an async
|
|
@@ -1865,14 +1906,15 @@ async function runOnce({ tok, base, id, tools, conv, convID, signal, maxMode, pa
|
|
|
1865
1906
|
if (o.error) return book.done(), o
|
|
1866
1907
|
const { session, req } = o
|
|
1867
1908
|
let closed = false
|
|
1909
|
+
let heartbeat
|
|
1868
1910
|
const send = (msg) => {
|
|
1869
1911
|
if (!closed && !req.destroyed && req.writable) req.write(frame(msg))
|
|
1870
1912
|
}
|
|
1871
|
-
const heartbeat = setInterval(() => send(pb().bytes(7, EMPTY).done()), 5000) // the client is still there, as the CLI says
|
|
1872
1913
|
const close = () => {
|
|
1873
1914
|
if (closed) return
|
|
1874
1915
|
closed = true
|
|
1875
1916
|
clearInterval(heartbeat)
|
|
1917
|
+
signal?.removeEventListener("abort", close)
|
|
1876
1918
|
try {
|
|
1877
1919
|
req.close(http2.constants.NGHTTP2_CANCEL)
|
|
1878
1920
|
} catch {}
|
|
@@ -1880,6 +1922,13 @@ async function runOnce({ tok, base, id, tools, conv, convID, signal, maxMode, pa
|
|
|
1880
1922
|
setTimeout(() => session.destroy(), 1000).unref?.()
|
|
1881
1923
|
}
|
|
1882
1924
|
signal?.addEventListener("abort", close, { once: true })
|
|
1925
|
+
// Abort can win after open's head check but before this Run takes ownership.
|
|
1926
|
+
if (signal?.aborted) {
|
|
1927
|
+
close()
|
|
1928
|
+
book.done()
|
|
1929
|
+
return cancelledOpen()
|
|
1930
|
+
}
|
|
1931
|
+
heartbeat = setInterval(() => send(pb().bytes(7, EMPTY).done()), 5000) // the client is still there, as the CLI says
|
|
1883
1932
|
send(first)
|
|
1884
1933
|
if (o.status < 200 || o.status > 299) {
|
|
1885
1934
|
const chunks = []
|
|
@@ -2349,8 +2398,12 @@ export async function CursorAuthPlugin() {
|
|
|
2349
2398
|
return { error: e.message, windows: [], signIn: "kept" }
|
|
2350
2399
|
}
|
|
2351
2400
|
const [u, plan, bot] = await Promise.all([usage(tok, Object.keys(provider?.models ?? {})), planOf(tok), botUsage(tok)])
|
|
2352
|
-
//
|
|
2353
|
-
|
|
2401
|
+
// Bot goes among magpie's three menu-bar rings: before Total, and
|
|
2402
|
+
// before an On-demand with no limit, which is only a dollar figure on
|
|
2403
|
+
// a ring that never fills (magpie #2213, Morganwan90). An On-demand
|
|
2404
|
+
// with a limit stays ahead of it: that is what can stop the account.
|
|
2405
|
+
const last = (w) => w.name === "Total" || (w.name === "On-demand" && w.aside)
|
|
2406
|
+
const windows = [...u.windows.filter((w) => !last(w)), ...bot, ...u.windows.filter(last)]
|
|
2354
2407
|
return { ...u, windows, ...(plan ? { plan } : {}), signIn: "kept" }
|
|
2355
2408
|
},
|
|
2356
2409
|
},
|
|
@@ -2393,4 +2446,4 @@ export async function CursorAuthPlugin() {
|
|
|
2393
2446
|
}
|
|
2394
2447
|
|
|
2395
2448
|
// for tests
|
|
2396
|
-
export const _internal = { onDemandOf,resetH1: () => (h1Until = 0), onH1: () => Date.now() < h1Until, H2, H1, h2Blocked, open, openH1, STEP_WAIT, stepUsage, ledger, owed, flights, misses, unreadable, catalog, usable, request, modelsOf, tokensOf, maxRequired, conversationID, usageOf, sessionOf, SESSION, errorResponse, kept, poolBase, conversation, buildRun, decode, exec, fields, pb, pbValue, pbAny, frame, frames, failure, toolsOf, expiry }
|
|
2449
|
+
export const _internal = { onDemandOf,resetH1: () => (h1Until = 0), onH1: () => Date.now() < h1Until, H2, H1, h2Blocked, open, openH1, openH2, STEP_WAIT, stepUsage, usageKey, ledger, owed, flights, misses, unreadable, catalog, usable, request, modelsOf, tokensOf, maxRequired, conversationID, usageOf, sessionOf, SESSION, errorResponse, kept, poolBase, conversation, buildRun, decode, exec, fields, pb, pbValue, pbAny, frame, frames, failure, toolsOf, expiry }
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@magpie-community/opencode-cursor-auth",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.13",
|
|
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",
|