@magpie-community/opencode-cursor-auth 0.1.9 → 0.1.10
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/README.md +9 -1
- package/index.mjs +216 -27
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -58,7 +58,15 @@ plugin's `fetch` answers them on Cursor's agent API:
|
|
|
58
58
|
(Cursor tells it only once the tools' results come back in the same
|
|
59
59
|
Run), so once the Run is closed its usage is read from the dashboard's
|
|
60
60
|
usage events, by the Run's conversation id: it shows in about 2.5 s,
|
|
61
|
-
and is looked for up to 6 s
|
|
61
|
+
and is looked for up to 6 s. Far from Cursor it shows later than that
|
|
62
|
+
(yetone/magpie#1053), so the step says 0 used and the conversation owes
|
|
63
|
+
it: its next steps collect the event in the background and count it
|
|
64
|
+
with their own, and a step that ends the turn waits for what is still
|
|
65
|
+
owed, so the conversation adds up to what Cursor counted. An account
|
|
66
|
+
whose events miss the wait 3 steps in a row stops waiting for them.
|
|
67
|
+
With nothing naming the session (so no later step to collect it), or
|
|
68
|
+
an account that can't read its usage events, the step is estimated as
|
|
69
|
+
before.
|
|
62
70
|
Failures keep their statuses: 401 to sign in again, 429 at the
|
|
63
71
|
usage limit, 400 for a prompt too long, 403 for a region refusal.
|
|
64
72
|
|
package/index.mjs
CHANGED
|
@@ -1174,47 +1174,218 @@ function usageOf(uf) {
|
|
|
1174
1174
|
// was read from the cache and written to it, as TurnEndedUpdate does; one
|
|
1175
1175
|
// shows about 2.5 s after the Run is closed. STEP_WAIT is how long a step's
|
|
1176
1176
|
// is looked for: first after that long, then every so often until the
|
|
1177
|
-
// end
|
|
1178
|
-
|
|
1177
|
+
// end (each ask given `ask` to answer).
|
|
1178
|
+
//
|
|
1179
|
+
// Far from Cursor none shows in that time (yetone/magpie#1053: a round
|
|
1180
|
+
// trip of 4.2 s, the event 4–5 s after the Run closes), and waiting longer
|
|
1181
|
+
// would hold every tool step longer. So a tool step's Run is owed by its
|
|
1182
|
+
// conversation (owed): the step counts every event of the conversation's
|
|
1183
|
+
// owed Runs that has shown by the end of its wait, its own or earlier
|
|
1184
|
+
// ones, and what hasn't shown is collected by the conversation's next
|
|
1185
|
+
// steps, in the background from `owedAt` after the Run closed. A step
|
|
1186
|
+
// whose count is still owed says 0 used; the conversation's steps add up
|
|
1187
|
+
// to what Cursor counted, some of it a step or two late. A step that ends
|
|
1188
|
+
// the turn waits for what is still owed, as nothing may follow it soon.
|
|
1189
|
+
// After `skipAfter` steps in a row of an account's left something owed,
|
|
1190
|
+
// its steps stop waiting (but every `retryEvery`th), and leave it to the
|
|
1191
|
+
// next. A debt not collected in `owedFor` is let go. With no
|
|
1192
|
+
// conversation_id naming the session nothing later could collect a Run's
|
|
1193
|
+
// event: its step looks for it as before, and is guessed without it.
|
|
1194
|
+
const STEP_WAIT = { first: 1500, every: 500, until: 6000, ask: 5000, skipAfter: 3, retryEvery: 10, owedAt: 5000, owedFor: 600_000 }
|
|
1179
1195
|
|
|
1180
1196
|
// claimed are the usage events already counted, by conversation and time,
|
|
1181
1197
|
// so that two steps of one conversation never count the same one.
|
|
1182
1198
|
const claimed = new Map()
|
|
1183
1199
|
|
|
1184
|
-
//
|
|
1185
|
-
//
|
|
1186
|
-
|
|
1200
|
+
// owed are what each conversation still owes, by conversation_id: n Runs
|
|
1201
|
+
// whose events are to be counted, the earliest started at since, looked
|
|
1202
|
+
// for from ready on; and carry, a count collected that no step gave out.
|
|
1203
|
+
const owed = new Map()
|
|
1204
|
+
|
|
1205
|
+
// flights are each conversation's collections still going, which a step
|
|
1206
|
+
// that ends the turn waits for.
|
|
1207
|
+
const flights = new Map()
|
|
1208
|
+
|
|
1209
|
+
// unreadable are the accounts (by token) whose usage events Cursor won't
|
|
1210
|
+
// give (a 4xx), for owedFor: their steps are guessed, as before, and owe
|
|
1211
|
+
// nothing. misses are how many steps in a row of an account's left
|
|
1212
|
+
// something owed.
|
|
1213
|
+
const unreadable = new Map()
|
|
1214
|
+
const misses = new Map()
|
|
1215
|
+
const tokKey = (tok) => createHash("sha256").update(tok).digest("hex")
|
|
1216
|
+
function canRead(tok) {
|
|
1217
|
+
const at = unreadable.get(tokKey(tok))
|
|
1218
|
+
if (at === undefined) return true
|
|
1219
|
+
if (Date.now() - at < STEP_WAIT.owedFor) return false
|
|
1220
|
+
unreadable.delete(tokKey(tok))
|
|
1221
|
+
return true
|
|
1222
|
+
}
|
|
1223
|
+
|
|
1224
|
+
const ZERO = () => ({ input: 0, output: 0, cacheRead: 0, cacheWrite: 0, reasoning: 0 })
|
|
1225
|
+
function addUsage(a, b) {
|
|
1226
|
+
if (!b) return a
|
|
1227
|
+
if (!a) return { ...b }
|
|
1228
|
+
for (const k of Object.keys(a)) a[k] += b[k] ?? 0
|
|
1229
|
+
return a
|
|
1230
|
+
}
|
|
1231
|
+
|
|
1232
|
+
// owe adds to conversation conv's debt.
|
|
1233
|
+
function owe(conv, { since = Date.now(), n = 0, ready = Date.now(), carry = null }) {
|
|
1234
|
+
for (const [k, d] of owed) if (Date.now() - d.since > STEP_WAIT.owedFor) owed.delete(k)
|
|
1235
|
+
if (n <= 0 && !carry) return
|
|
1236
|
+
const d = owed.get(conv)
|
|
1237
|
+
if (!d) return void owed.set(conv, { since, n, ready, carry: carry && { ...carry } })
|
|
1238
|
+
d.since = Math.min(d.since, since)
|
|
1239
|
+
d.n += n
|
|
1240
|
+
d.ready = Math.min(d.ready, ready)
|
|
1241
|
+
d.carry = addUsage(d.carry, carry)
|
|
1242
|
+
}
|
|
1243
|
+
|
|
1244
|
+
// usageEvents are the dashboard's events of conversation conv from since
|
|
1245
|
+
// on, the `want` oldest not counted yet, summed: usage (null when none),
|
|
1246
|
+
// how many were found (got), and refused when the account can't read them.
|
|
1247
|
+
// Polling, they are looked for as STEP_WAIT says, from `first` on, until
|
|
1248
|
+
// all show; else asked for once.
|
|
1249
|
+
async function usageEvents(tok, conv, since, want, { poll = false, first = STEP_WAIT.first, signal } = {}) {
|
|
1187
1250
|
const end = Date.now() + STEP_WAIT.until
|
|
1188
1251
|
const wait = (ms) => new Promise((r) => {
|
|
1189
1252
|
const t = setTimeout(r, ms)
|
|
1190
1253
|
signal?.addEventListener("abort", () => (clearTimeout(t), r()), { once: true })
|
|
1191
1254
|
})
|
|
1192
|
-
for (const [k, at] of claimed) if (Date.now() - at >
|
|
1193
|
-
await wait(STEP_WAIT.first)
|
|
1255
|
+
for (const [k, at] of claimed) if (Date.now() - at > 2 * STEP_WAIT.owedFor) claimed.delete(k)
|
|
1194
1256
|
const num = (v) => (Number.isFinite(Number(v)) ? Number(v) : 0)
|
|
1257
|
+
let usage = null
|
|
1258
|
+
let got = 0
|
|
1259
|
+
if (poll) await wait(first)
|
|
1195
1260
|
while (!signal?.aborted) {
|
|
1196
1261
|
try {
|
|
1197
1262
|
const res = await fetch(API + "/aiserver.v1.DashboardService/GetFilteredUsageEvents", {
|
|
1198
1263
|
method: "POST",
|
|
1199
1264
|
headers: await headersFor(tok),
|
|
1200
1265
|
body: JSON.stringify({ teamId: 0, startDate: String(since - 60_000), endDate: String(Date.now() + 60_000), page: 1, pageSize: 50 }),
|
|
1201
|
-
signal: AbortSignal.timeout(
|
|
1266
|
+
signal: AbortSignal.timeout(STEP_WAIT.ask),
|
|
1202
1267
|
})
|
|
1203
|
-
if (res.status >= 400 && res.status < 500 && res.status !== 429)
|
|
1268
|
+
if (res.status >= 400 && res.status < 500 && res.status !== 429) {
|
|
1269
|
+
// not this account's to read
|
|
1270
|
+
unreadable.set(tokKey(tok), Date.now())
|
|
1271
|
+
return { usage, got, refused: true }
|
|
1272
|
+
}
|
|
1204
1273
|
const evs = res.ok ? ((await res.json())?.usageEventsDisplay ?? []) : []
|
|
1205
|
-
const
|
|
1274
|
+
const found = evs
|
|
1206
1275
|
.filter((e) => e?.conversationId === conv && e.tokenUsage && num(e.timestamp) >= since - 1000 && !claimed.has(conv + "\0" + e.timestamp))
|
|
1207
|
-
.sort((a, b) => num(a.timestamp) - num(b.timestamp))
|
|
1208
|
-
|
|
1276
|
+
.sort((a, b) => num(a.timestamp) - num(b.timestamp))
|
|
1277
|
+
.slice(0, want - got)
|
|
1278
|
+
for (const ev of found) {
|
|
1209
1279
|
claimed.set(conv + "\0" + ev.timestamp, Date.now())
|
|
1210
1280
|
const t = ev.tokenUsage
|
|
1211
|
-
|
|
1281
|
+
usage = addUsage(usage ?? ZERO(), { input: num(t.inputTokens), output: num(t.outputTokens), cacheRead: num(t.cacheReadTokens), cacheWrite: num(t.cacheWriteTokens) })
|
|
1282
|
+
got++
|
|
1212
1283
|
}
|
|
1284
|
+
if (got >= want) break
|
|
1213
1285
|
} catch {}
|
|
1214
|
-
if (Date.now() + STEP_WAIT.every > end)
|
|
1286
|
+
if (!poll || Date.now() + STEP_WAIT.every > end) break
|
|
1215
1287
|
await wait(STEP_WAIT.every)
|
|
1216
1288
|
}
|
|
1217
|
-
return
|
|
1289
|
+
return { usage, got, refused: false }
|
|
1290
|
+
}
|
|
1291
|
+
|
|
1292
|
+
// stepUsage is the usage of the Run of conversation conv started at since,
|
|
1293
|
+
// as the dashboard's usage events count it; null when none shows in time.
|
|
1294
|
+
async function stepUsage(tok, conv, since, signal) {
|
|
1295
|
+
return (await usageEvents(tok, conv, since, 1, { poll: true, signal })).usage
|
|
1296
|
+
}
|
|
1297
|
+
|
|
1298
|
+
// collect takes conversation conv's debt and asks for its events (polling
|
|
1299
|
+
// when poll): what was carried and what was found (usage), and whether
|
|
1300
|
+
// any is still owed (short), which is owed on. What comes back once the
|
|
1301
|
+
// Run that asked is over (over() true) is carried to the next instead.
|
|
1302
|
+
function collect(tok, conv, { poll = false, first, signal, over = () => false } = {}) {
|
|
1303
|
+
const d = owed.get(conv)
|
|
1304
|
+
if (!d) return Promise.resolve({ usage: null, short: false })
|
|
1305
|
+
owed.delete(conv)
|
|
1306
|
+
const p = (async () => {
|
|
1307
|
+
let r = { usage: null, got: 0 }
|
|
1308
|
+
if (d.n > 0 && canRead(tok)) r = await usageEvents(tok, conv, d.since, d.n, { poll, first, signal }).catch(() => r)
|
|
1309
|
+
const short = d.n > r.got && canRead(tok)
|
|
1310
|
+
if (short) owe(conv, { since: d.since, n: d.n - r.got, ready: d.ready })
|
|
1311
|
+
const usage = addUsage(d.carry, r.usage)
|
|
1312
|
+
if (!over()) return { usage, short }
|
|
1313
|
+
owe(conv, { carry: usage })
|
|
1314
|
+
return { usage: null, short }
|
|
1315
|
+
})()
|
|
1316
|
+
const set = flights.get(conv) ?? new Set()
|
|
1317
|
+
flights.set(conv, set.add(p))
|
|
1318
|
+
p.finally(() => {
|
|
1319
|
+
set.delete(p)
|
|
1320
|
+
if (!set.size && flights.get(conv) === set) flights.delete(conv)
|
|
1321
|
+
})
|
|
1322
|
+
return p
|
|
1323
|
+
}
|
|
1324
|
+
|
|
1325
|
+
// ledger is how a Run of conversation conv, started at since, has its
|
|
1326
|
+
// usage counted, for decode; kept when the conversation_id names the
|
|
1327
|
+
// session, so that a later Run of it can collect what this one owes. A
|
|
1328
|
+
// debt the conversation has is collected in the background. own() is a
|
|
1329
|
+
// step's count once it has called tools: its Run owed, what has shown of
|
|
1330
|
+
// the debt by the end of the wait (or at once, when the account's never
|
|
1331
|
+
// show in time); false when nothing has, null when the step is to be
|
|
1332
|
+
// guessed (not kept, and its event not found, or an account that can't
|
|
1333
|
+
// read its events). owed(final) is what the Run collected otherwise,
|
|
1334
|
+
// all that can be had when final. done() ends the Run: what was collected
|
|
1335
|
+
// and not given out goes back.
|
|
1336
|
+
function ledger(tok, conv, since, signal, kept) {
|
|
1337
|
+
const key = tokKey(tok)
|
|
1338
|
+
let pending = null // collected, not given out yet
|
|
1339
|
+
let over = false
|
|
1340
|
+
const gather = (opts) =>
|
|
1341
|
+
collect(tok, conv, { ...opts, over: () => over }).then((r) => {
|
|
1342
|
+
pending = addUsage(pending, r.usage)
|
|
1343
|
+
return r
|
|
1344
|
+
})
|
|
1345
|
+
let collecting = null
|
|
1346
|
+
const debt = kept ? owed.get(conv) : undefined
|
|
1347
|
+
const timer = debt ? setTimeout(() => (collecting = gather()), Math.max(0, debt.ready - Date.now())) : null
|
|
1348
|
+
timer?.unref?.()
|
|
1349
|
+
const take = () => {
|
|
1350
|
+
const u = pending
|
|
1351
|
+
pending = null
|
|
1352
|
+
return u
|
|
1353
|
+
}
|
|
1354
|
+
return {
|
|
1355
|
+
async own() {
|
|
1356
|
+
if (!canRead(tok)) return null
|
|
1357
|
+
const m = misses.get(key) ?? 0
|
|
1358
|
+
const waits = m < STEP_WAIT.skipAfter || m % STEP_WAIT.retryEvery === 0
|
|
1359
|
+
if (!kept) {
|
|
1360
|
+
const r = waits ? await usageEvents(tok, conv, since, 1, { poll: true, signal }).catch(() => ({})) : {}
|
|
1361
|
+
if (r.usage) misses.delete(key)
|
|
1362
|
+
else if (!r.refused) misses.set(key, m + 1)
|
|
1363
|
+
return r.usage ?? null
|
|
1364
|
+
}
|
|
1365
|
+
owe(conv, { since, n: 1, ready: Date.now() + STEP_WAIT.owedAt })
|
|
1366
|
+
if (waits) {
|
|
1367
|
+
const r = await gather({ poll: true, signal })
|
|
1368
|
+
if (!canRead(tok)) return null
|
|
1369
|
+
if (r.short) misses.set(key, m + 1)
|
|
1370
|
+
else misses.delete(key)
|
|
1371
|
+
} else misses.set(key, m + 1)
|
|
1372
|
+
return take() ?? false
|
|
1373
|
+
},
|
|
1374
|
+
async owed(final) {
|
|
1375
|
+
if (!kept) return null
|
|
1376
|
+
if (final) {
|
|
1377
|
+
await collecting
|
|
1378
|
+
await Promise.all([...(flights.get(conv) ?? [])])
|
|
1379
|
+
if (owed.has(conv)) await gather({ poll: owed.get(conv).n > 0, first: 0, signal })
|
|
1380
|
+
}
|
|
1381
|
+
return take()
|
|
1382
|
+
},
|
|
1383
|
+
done() {
|
|
1384
|
+
over = true
|
|
1385
|
+
clearTimeout(timer)
|
|
1386
|
+
if (pending) owe(conv, { carry: take() })
|
|
1387
|
+
},
|
|
1388
|
+
}
|
|
1218
1389
|
}
|
|
1219
1390
|
|
|
1220
1391
|
// buildRun is the Run's first message, an AgentClientMessage with its
|
|
@@ -1332,6 +1503,10 @@ async function runOnce({ tok, base, id, tools, conv, convID, signal, maxMode, pa
|
|
|
1332
1503
|
// its usage event is found by it
|
|
1333
1504
|
const cid = convID || randomUUID()
|
|
1334
1505
|
const since = Date.now()
|
|
1506
|
+
// how its usage is counted: a debt of the conversation's is collected
|
|
1507
|
+
// while it goes, which only a conversation_id that names the session
|
|
1508
|
+
// could have run up
|
|
1509
|
+
const book = ledger(tok, cid, since, signal, !!convID)
|
|
1335
1510
|
const { first, blobs } = buildRun(conv.msgs, conv.last, tools, id, cid, { maxMode, params })
|
|
1336
1511
|
const o = await open(
|
|
1337
1512
|
base,
|
|
@@ -1348,7 +1523,7 @@ async function runOnce({ tok, base, id, tools, conv, convID, signal, maxMode, pa
|
|
|
1348
1523
|
},
|
|
1349
1524
|
signal,
|
|
1350
1525
|
)
|
|
1351
|
-
if (o.error) return o
|
|
1526
|
+
if (o.error) return book.done(), o
|
|
1352
1527
|
const { session, req } = o
|
|
1353
1528
|
let closed = false
|
|
1354
1529
|
const send = (msg) => {
|
|
@@ -1373,6 +1548,7 @@ async function runOnce({ tok, base, id, tools, conv, convID, signal, maxMode, pa
|
|
|
1373
1548
|
for await (const c of req) chunks.push(c)
|
|
1374
1549
|
} catch {}
|
|
1375
1550
|
close()
|
|
1551
|
+
book.done()
|
|
1376
1552
|
return { error: failure(o.status, Buffer.concat(chunks).toString("utf8").slice(0, 1 << 20)) }
|
|
1377
1553
|
}
|
|
1378
1554
|
const it = decode(frames(req), {
|
|
@@ -1381,19 +1557,21 @@ async function runOnce({ tok, base, id, tools, conv, convID, signal, maxMode, pa
|
|
|
1381
1557
|
tools,
|
|
1382
1558
|
estimate: conv.estimate,
|
|
1383
1559
|
close,
|
|
1384
|
-
stepUsage:
|
|
1560
|
+
stepUsage: book.own,
|
|
1561
|
+
owedUsage: book.owed,
|
|
1385
1562
|
})
|
|
1386
1563
|
const wrapped = (async function* () {
|
|
1387
1564
|
try {
|
|
1388
1565
|
yield* it
|
|
1389
1566
|
} finally {
|
|
1390
1567
|
close()
|
|
1568
|
+
book.done()
|
|
1391
1569
|
}
|
|
1392
1570
|
})()
|
|
1393
1571
|
// an error comes before anything of the answer: out of quota, a model the
|
|
1394
1572
|
// plan doesn't have — answered with its own status
|
|
1395
1573
|
const head = await wrapped.next()
|
|
1396
|
-
if (head.done) return { error: { status: 502, message: "an empty reply" } }
|
|
1574
|
+
if (head.done) return book.done(), { error: { status: 502, message: "an empty reply" } }
|
|
1397
1575
|
if (head.value.error) {
|
|
1398
1576
|
await wrapped.return()
|
|
1399
1577
|
return { error: head.value.error }
|
|
@@ -1408,7 +1586,7 @@ async function runOnce({ tok, base, id, tools, conv, convID, signal, maxMode, pa
|
|
|
1408
1586
|
|
|
1409
1587
|
// decode follows the server's messages into the answer's pieces until the
|
|
1410
1588
|
// turn ends, or the model has made its tool calls.
|
|
1411
|
-
async function* decode(stream, { send, blobs, tools, estimate, close, stepUsage }) {
|
|
1589
|
+
async function* decode(stream, { send, blobs, tools, estimate, close, stepUsage, owedUsage }) {
|
|
1412
1590
|
let calls = 0
|
|
1413
1591
|
// ended: Cursor said what the turn used
|
|
1414
1592
|
let ended = false
|
|
@@ -1417,11 +1595,19 @@ async function* decode(stream, { send, blobs, tools, estimate, close, stepUsage
|
|
|
1417
1595
|
// wrote: the reply's text alone; a turn of thinking only says nothing
|
|
1418
1596
|
let wrote = 0
|
|
1419
1597
|
let usage = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, reasoning: 0 }
|
|
1420
|
-
|
|
1421
|
-
|
|
1598
|
+
// counted: the step's usage is the dashboard's events, its own counted
|
|
1599
|
+
// with it or by a later step (ledger), never guessed
|
|
1600
|
+
let counted = false
|
|
1601
|
+
// finish is the step's end, with what earlier steps owed (more), which
|
|
1602
|
+
// is no reason not to guess the step's own
|
|
1603
|
+
const finish = (more) => {
|
|
1604
|
+
if (!counted && !usage.output) usage.output = Math.floor((said + 3) / 4)
|
|
1422
1605
|
// a guess only when Cursor counted nothing: a prompt read whole from
|
|
1423
|
-
// the cache leaves no uncached rest, and is no reason to guess
|
|
1424
|
-
|
|
1606
|
+
// the cache leaves no uncached rest, and is no reason to guess; nor is
|
|
1607
|
+
// a prompt counted from the events
|
|
1608
|
+
if (!counted && !usage.input && !usage.cacheRead && !usage.cacheWrite) usage.input = estimate
|
|
1609
|
+
// the events' output is their steps', counted here as their prompt is
|
|
1610
|
+
if (more) for (const k of ["input", "output", "cacheRead", "cacheWrite"]) usage[k] += more[k]
|
|
1425
1611
|
const prompt = usage.input + usage.cacheRead + usage.cacheWrite
|
|
1426
1612
|
return {
|
|
1427
1613
|
stop: calls > 0 ? "tool_calls" : "stop",
|
|
@@ -1435,14 +1621,17 @@ async function* decode(stream, { send, blobs, tools, estimate, close, stepUsage
|
|
|
1435
1621
|
}
|
|
1436
1622
|
}
|
|
1437
1623
|
// settled is finish once a step that called tools has its usage: the
|
|
1438
|
-
// dashboard's count, the Run closed first, when the turn didn't end
|
|
1624
|
+
// dashboard's count, the Run closed first, when the turn didn't end (or
|
|
1625
|
+
// owed); and with what the conversation's earlier steps owed, which a
|
|
1626
|
+
// step that ends the turn waits for
|
|
1439
1627
|
const settled = async () => {
|
|
1440
1628
|
if (calls > 0 && !ended && stepUsage) {
|
|
1441
1629
|
close?.()
|
|
1442
1630
|
const u = await stepUsage().catch(() => null)
|
|
1443
1631
|
if (u) usage = u
|
|
1632
|
+
counted = u === false || !!u
|
|
1444
1633
|
}
|
|
1445
|
-
return finish()
|
|
1634
|
+
return finish(owedUsage ? await owedUsage(calls === 0).catch(() => null) : null)
|
|
1446
1635
|
}
|
|
1447
1636
|
const closeExec = (id) => send(pb().bytes(5, pb().bytes(1, pb().varint(1, id))).done())
|
|
1448
1637
|
try {
|
|
@@ -1485,7 +1674,7 @@ async function* decode(stream, { send, blobs, tools, estimate, close, stepUsage
|
|
|
1485
1674
|
if (calls === 0) {
|
|
1486
1675
|
// nothing written and nothing called: an empty reply,
|
|
1487
1676
|
// which the client asks again, not a finished turn
|
|
1488
|
-
yield wrote === 0 ? { error: { status: 502, message: "an empty reply" } } :
|
|
1677
|
+
yield wrote === 0 ? { error: { status: 502, message: "an empty reply" } } : await settled()
|
|
1489
1678
|
return
|
|
1490
1679
|
}
|
|
1491
1680
|
break
|
|
@@ -1810,4 +1999,4 @@ export async function CursorAuthPlugin() {
|
|
|
1810
1999
|
}
|
|
1811
2000
|
|
|
1812
2001
|
// for tests
|
|
1813
|
-
export const _internal = { STEP_WAIT, stepUsage, catalog, usable, maxRequired, conversationID, usageOf, sessionOf, SESSION, errorResponse, kept, poolBase, splitID, families, byEffort, offered, modelID, conversation, buildRun, decode, exec, fields, pb, pbValue, pbAny, frame, frames, failure, toolsOf, expiry }
|
|
2002
|
+
export const _internal = { STEP_WAIT, stepUsage, ledger, owed, flights, misses, unreadable, catalog, usable, maxRequired, conversationID, usageOf, sessionOf, SESSION, errorResponse, kept, poolBase, splitID, families, byEffort, offered, modelID, 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.1.
|
|
3
|
+
"version": "0.1.10",
|
|
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",
|