@magpie-community/opencode-qoder-auth 0.2.18 → 0.2.20
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 +33 -0
- package/index.mjs +25 -9
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -247,6 +247,39 @@ International campaign discovery was checked with a real account on
|
|
|
247
247
|
omitting either header hid them. This verification only queried the
|
|
248
248
|
activity; a live claim was not performed.
|
|
249
249
|
|
|
250
|
+
## Credits available, but a request is refused
|
|
251
|
+
|
|
252
|
+
A positive credit balance does not guarantee a queue slot or access to
|
|
253
|
+
every model. Use the model ids listed for that particular account and
|
|
254
|
+
region. Do not infer another account's permission from its balance.
|
|
255
|
+
|
|
256
|
+
Qoder code **10605**, including `RESOURCE_LIMIT`, `serviceAvailable` or
|
|
257
|
+
`isQueued` details, is a resource/queue answer. Keep its suggested retry
|
|
258
|
+
delay; repeatedly signing in does not free that queue. Since **0.2.18**
|
|
259
|
+
([#185](https://github.com/magpie-community/plugins/pull/185)), a 10605 led
|
|
260
|
+
by a BOM or wrapped in an outer message is read as busy too; see
|
|
261
|
+
[#167](https://github.com/magpie-community/plugins/issues/167) for the broader report.
|
|
262
|
+
That parser fix does not remove the provider's limit or prove that every
|
|
263
|
+
live 401 had the same cause. A timeout likewise does not establish an
|
|
264
|
+
empty wallet or an expired login.
|
|
265
|
+
|
|
266
|
+
For a bounded offline reproduction, run `packages/qoder/busy.test.mjs`
|
|
267
|
+
from #185 in an isolated temporary HOME. It compares plain queue JSON,
|
|
268
|
+
BOM-prefixed JSON and known message wrappers, keeping explicit login and
|
|
269
|
+
credit failures distinct. Extracting a JSON body from a translated log
|
|
270
|
+
cannot recover the original wire bytes; synthetic wrappers demonstrate
|
|
271
|
+
parser behavior, not which wrapper a historical request actually used.
|
|
272
|
+
After selecting a local fix with magpie's `plugin use`, confirm which spec
|
|
273
|
+
serves `qoder` in `plugin list`; a patched checkout alone does not change
|
|
274
|
+
the running provider.
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
For native check-in, an existing `CLAIMED` result is not a new credit grant.
|
|
278
|
+
The host's recheck/cache behavior is tracked in
|
|
279
|
+
[magpie#2696](https://github.com/yetone/magpie/issues/2696). Verify a new
|
|
280
|
+
claim against the vendor record; a successful activity query alone is not
|
|
281
|
+
proof that credits arrived.
|
|
282
|
+
|
|
250
283
|
## Not here
|
|
251
284
|
|
|
252
285
|
- Qoder's usage and quota display.
|
package/index.mjs
CHANGED
|
@@ -1015,7 +1015,7 @@ async function* sseLines(body) {
|
|
|
1015
1015
|
async function* events(body) {
|
|
1016
1016
|
const a = new Splitter()
|
|
1017
1017
|
let index = -1 // the tool call being given
|
|
1018
|
-
|
|
1018
|
+
const native = new Map() // upstream index -> call and its output index
|
|
1019
1019
|
// one piece of the split text as an event: a call, text, or a call that
|
|
1020
1020
|
// can't be read, which ends the turn as a 502
|
|
1021
1021
|
const piece = (f) =>
|
|
@@ -1055,16 +1055,29 @@ async function* events(body) {
|
|
|
1055
1055
|
// tool calls served the OpenAI way keep Qoder's id: a result answers it
|
|
1056
1056
|
for (const tc of delta.tool_calls ?? []) {
|
|
1057
1057
|
const i = Number(tc.index ?? 0)
|
|
1058
|
-
|
|
1059
|
-
|
|
1058
|
+
const name = typeof tc.function?.name === "string" ? tc.function.name.trim() : ""
|
|
1059
|
+
const args = tc.function?.arguments ?? ""
|
|
1060
|
+
if (!tc.id && !name && !args) continue
|
|
1061
|
+
let call = native.get(i)
|
|
1062
|
+
if (!call) {
|
|
1063
|
+
call = { id: "", args: "" }
|
|
1064
|
+
native.set(i, call)
|
|
1065
|
+
}
|
|
1066
|
+
if (tc.id) call.id = tc.id
|
|
1067
|
+
if (call.index === undefined) {
|
|
1068
|
+
// An id or arguments can arrive before the name. Never emit an
|
|
1069
|
+
// unnamed tool: clients persist it and other providers reject it.
|
|
1070
|
+
call.args += args
|
|
1071
|
+
if (!name) continue
|
|
1060
1072
|
for (const f of a.flush()) {
|
|
1061
1073
|
const e = piece(f)
|
|
1062
1074
|
yield e
|
|
1063
1075
|
if (e.error) return
|
|
1064
1076
|
}
|
|
1065
1077
|
a.sawTool = true
|
|
1066
|
-
|
|
1067
|
-
|
|
1078
|
+
call.index = ++index
|
|
1079
|
+
yield { tool: { index: call.index, id: call.id || "call_" + hexID(), name, args: call.args } }
|
|
1080
|
+
} else if (args) yield { args: { index: call.index, text: args } }
|
|
1068
1081
|
}
|
|
1069
1082
|
fr = chunk?.choices?.[0]?.finish_reason || fr
|
|
1070
1083
|
// the usage comes in a chunk of its own after the finish, with no
|
|
@@ -1085,6 +1098,10 @@ async function* events(body) {
|
|
|
1085
1098
|
yield e
|
|
1086
1099
|
if (e.error) return
|
|
1087
1100
|
}
|
|
1101
|
+
if ([...native.values()].some((call) => call.index === undefined)) {
|
|
1102
|
+
yield { error: { status: 502, message: "the model's native tool call has no name; it is not sent on as a tool" } }
|
|
1103
|
+
return
|
|
1104
|
+
}
|
|
1088
1105
|
yield { stop: a.sawTool ? "tool_calls" : fr === "length" ? "length" : "stop", usage }
|
|
1089
1106
|
}
|
|
1090
1107
|
|
|
@@ -1111,7 +1128,7 @@ async function answer(res, chat) {
|
|
|
1111
1128
|
if (e.text) msg.content += e.text
|
|
1112
1129
|
if (e.reasoning) reasoning += e.reasoning
|
|
1113
1130
|
if (e.tool) calls.push({ id: e.tool.id, type: "function", function: { name: e.tool.name, arguments: e.tool.args } })
|
|
1114
|
-
if (e.args) calls[
|
|
1131
|
+
if (e.args) calls[e.args.index].function.arguments += e.args.text
|
|
1115
1132
|
if (e.stop) [stop, usage] = [e.stop, e.usage]
|
|
1116
1133
|
}
|
|
1117
1134
|
if (reasoning) msg.reasoning_content = reasoning
|
|
@@ -1708,9 +1725,8 @@ const makePlugin = (site) => async ({ client }) => {
|
|
|
1708
1725
|
try {
|
|
1709
1726
|
m = (await models(cred)).find((x) => x.key === chat.model) ?? (await models(cred, true)).find((x) => x.key === chat.model)
|
|
1710
1727
|
} catch (e) {
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
return errorResponse({ status: 400, message: e.message })
|
|
1728
|
+
if (e instanceof SignInGone || e?.expired) return signedInError(e)
|
|
1729
|
+
return errorResponse({ status: 502, message: e?.message ?? String(e) })
|
|
1714
1730
|
}
|
|
1715
1731
|
if (!m) return errorResponse({ status: 400, message: `unknown or disabled model "${chat.model}"` })
|
|
1716
1732
|
const CHAT_URL = siteOf(site, cred).api + CHAT_PATH
|
package/package.json
CHANGED