@magpie-community/opencode-cursor-auth 0.2.7 → 0.2.8
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 +40 -4
- package/package.json +1 -1
package/index.mjs
CHANGED
|
@@ -1896,6 +1896,12 @@ async function* decode(stream, { send, blobs, tools, estimate, close, stepUsage,
|
|
|
1896
1896
|
let said = 0
|
|
1897
1897
|
// wrote: the reply's text alone; a turn of thinking only says nothing
|
|
1898
1898
|
let wrote = 0
|
|
1899
|
+
// what the Run sent, for an empty reply to name (#60): the thinking's
|
|
1900
|
+
// length, Cursor's own tools it asked for and was refused, and updates
|
|
1901
|
+
// and messages this doesn't read
|
|
1902
|
+
const seen = { thinking: 0, refused: new Map(), updates: new Map(), messages: new Map() }
|
|
1903
|
+
const count = (m, k) => m.set(k, (m.get(k) ?? 0) + 1)
|
|
1904
|
+
const empty = (how) => ({ error: { status: 502, message: "an empty reply" + emptyWhy(how, seen, ended ? usage : null) } })
|
|
1899
1905
|
let usage = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, reasoning: 0 }
|
|
1900
1906
|
// counted: the step's usage is the dashboard's events, its own counted
|
|
1901
1907
|
// with it or by a later step (ledger), never guessed
|
|
@@ -1941,7 +1947,7 @@ async function* decode(stream, { send, blobs, tools, estimate, close, stepUsage,
|
|
|
1941
1947
|
if (f.end) {
|
|
1942
1948
|
const e = failure(200, f.data)
|
|
1943
1949
|
if (e.status < 200 || e.status > 299) yield { error: e }
|
|
1944
|
-
else if (wrote === 0 && calls === 0) yield
|
|
1950
|
+
else if (wrote === 0 && calls === 0) yield empty(endFrame(f.data))
|
|
1945
1951
|
else yield await settled()
|
|
1946
1952
|
return
|
|
1947
1953
|
}
|
|
@@ -1966,6 +1972,7 @@ async function* decode(stream, { send, blobs, tools, estimate, close, stepUsage,
|
|
|
1966
1972
|
const t = pbStr(uf, 1)
|
|
1967
1973
|
if (t) {
|
|
1968
1974
|
said += t.length
|
|
1975
|
+
seen.thinking += t.length
|
|
1969
1976
|
yield { reasoning: t }
|
|
1970
1977
|
}
|
|
1971
1978
|
break
|
|
@@ -1976,7 +1983,7 @@ async function* decode(stream, { send, blobs, tools, estimate, close, stepUsage,
|
|
|
1976
1983
|
if (calls === 0) {
|
|
1977
1984
|
// nothing written and nothing called: an empty reply,
|
|
1978
1985
|
// which the client asks again, not a finished turn
|
|
1979
|
-
yield wrote === 0 ?
|
|
1986
|
+
yield wrote === 0 ? empty("Cursor ended the turn") : await settled()
|
|
1980
1987
|
return
|
|
1981
1988
|
}
|
|
1982
1989
|
break
|
|
@@ -1987,12 +1994,14 @@ async function* decode(stream, { send, blobs, tools, estimate, close, stepUsage,
|
|
|
1987
1994
|
return
|
|
1988
1995
|
}
|
|
1989
1996
|
break
|
|
1997
|
+
default:
|
|
1998
|
+
count(seen.updates, u.num)
|
|
1990
1999
|
}
|
|
1991
2000
|
}
|
|
1992
2001
|
break
|
|
1993
2002
|
case 2: {
|
|
1994
2003
|
// exec_server_message: the server asks the client to run something
|
|
1995
|
-
const call = exec(m.data, tools, send, closeExec)
|
|
2004
|
+
const call = exec(m.data, tools, send, closeExec, seen.refused)
|
|
1996
2005
|
if (call) {
|
|
1997
2006
|
said += call.args.length
|
|
1998
2007
|
yield { tool: { index: calls++, ...call } }
|
|
@@ -2021,6 +2030,8 @@ async function* decode(stream, { send, blobs, tools, estimate, close, stepUsage,
|
|
|
2021
2030
|
}
|
|
2022
2031
|
break
|
|
2023
2032
|
}
|
|
2033
|
+
default:
|
|
2034
|
+
count(seen.messages, m.num)
|
|
2024
2035
|
}
|
|
2025
2036
|
}
|
|
2026
2037
|
}
|
|
@@ -2038,10 +2049,33 @@ async function* decode(stream, { send, blobs, tools, estimate, close, stepUsage,
|
|
|
2038
2049
|
}
|
|
2039
2050
|
}
|
|
2040
2051
|
|
|
2052
|
+
// endFrame is how a Run's Connect end frame that said no error reads in
|
|
2053
|
+
// an empty reply's words: its JSON, cut short, or that it was empty.
|
|
2054
|
+
function endFrame(data) {
|
|
2055
|
+
const t = Buffer.from(data ?? []).toString("utf8").trim()
|
|
2056
|
+
if (!t || t === "{}") return "the Run's stream ended (an empty end frame)"
|
|
2057
|
+
return `the Run's stream ended (end frame: ${t.length > 300 ? t.slice(0, 300) + "…" : t})`
|
|
2058
|
+
}
|
|
2059
|
+
|
|
2060
|
+
// emptyWhy is what an empty reply says of what came before it (#60): how
|
|
2061
|
+
// it ended, the thinking, the turn's own count of output, Cursor's own
|
|
2062
|
+
// tools refused, and what Cursor sent that isn't read. Field numbers are
|
|
2063
|
+
// agent.v1's, so a report names the message that wasn't understood.
|
|
2064
|
+
function emptyWhy(how, seen, usage) {
|
|
2065
|
+
const list = (m) => [...m].map(([k, n]) => (n > 1 ? `#${k} ×${n}` : `#${k}`)).join(", ")
|
|
2066
|
+
const parts = [how]
|
|
2067
|
+
parts.push(seen.thinking ? `after ${seen.thinking} chars of thinking, no text and no tool call` : "with no thinking, no text and no tool call")
|
|
2068
|
+
if (usage) parts.push(`Cursor counted ${usage.output} output tokens`)
|
|
2069
|
+
if (seen.refused.size) parts.push(`Cursor's own tools asked for and refused: ${list(seen.refused)}`)
|
|
2070
|
+
if (seen.updates.size) parts.push(`updates not read: ${list(seen.updates)}`)
|
|
2071
|
+
if (seen.messages.size) parts.push(`messages not read: ${list(seen.messages)}`)
|
|
2072
|
+
return ` (${parts.join("; ")}; try again)`
|
|
2073
|
+
}
|
|
2074
|
+
|
|
2041
2075
|
// exec answers what the server asks the client to run: a call of the
|
|
2042
2076
|
// caller's tools is returned, the list of them is given, and anything else
|
|
2043
2077
|
// is refused.
|
|
2044
|
-
function exec(msg, tools, send, closeExec) {
|
|
2078
|
+
function exec(msg, tools, send, closeExec, refused) {
|
|
2045
2079
|
const es = fields(msg)
|
|
2046
2080
|
const id = pbNum(es, 1)
|
|
2047
2081
|
const execID = pbStr(es, 15)
|
|
@@ -2080,6 +2114,8 @@ function exec(msg, tools, send, closeExec) {
|
|
|
2080
2114
|
}
|
|
2081
2115
|
}
|
|
2082
2116
|
// a shell, a file read or an edit of Cursor's own: never run
|
|
2117
|
+
const kind = es.find((e) => e.num !== 1 && e.num !== 15)?.num ?? 0
|
|
2118
|
+
refused?.set(kind, (refused.get(kind) ?? 0) + 1)
|
|
2083
2119
|
send(pb().bytes(5, pb().bytes(2, pb().varint(1, id).str(2, "not available"))).done())
|
|
2084
2120
|
closeExec(id)
|
|
2085
2121
|
return null
|
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.8",
|
|
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",
|