@magpie-community/opencode-qoder-auth 0.2.13 → 0.2.14
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 +4 -2
- package/index.mjs +47 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -83,8 +83,10 @@ itself.
|
|
|
83
83
|
|
|
84
84
|
| What Qoder says | What the request returns |
|
|
85
85
|
|---|---|
|
|
86
|
-
| A refused sign-in | 401 |
|
|
87
|
-
| A quota | 429 |
|
|
86
|
+
| A refused sign-in (no code, or code 105) | 401 |
|
|
87
|
+
| A quota (codes 110, 112–119, 122) | 429 |
|
|
88
|
+
| Busy or queued for the model (code 10605) | 503, with `Retry-After` from Qoder's `retryAfterSeconds` (30s when it gives none); the sign-in is untouched |
|
|
89
|
+
| A refusal of the request itself (codes 406, 416, 430, 80411, 80412, 100400–100403) | 400, with Qoder's words |
|
|
88
90
|
| A failure before the answer starts | Qoder's status |
|
|
89
91
|
| A failure after the answer has started | The stream ends with an error |
|
|
90
92
|
|
package/index.mjs
CHANGED
|
@@ -720,19 +720,55 @@ function qoderBody(chat, m) {
|
|
|
720
720
|
return body
|
|
721
721
|
}
|
|
722
722
|
|
|
723
|
-
// failure is the status and message for a Qoder failure
|
|
724
|
-
//
|
|
723
|
+
// failure is the status and message for a Qoder failure. Qoder's own code
|
|
724
|
+
// says what it is, read as Qoder's client reads it (QoderErrorCode in the
|
|
725
|
+
// app's qoder-agent-sdk worker): only 105 (loginExpired) is a lapsed
|
|
726
|
+
// sign-in there, so a 401/403 that carries another code isn't one here
|
|
727
|
+
// either (#98: a queued 10605 came as a 403 and read as "sign in again").
|
|
728
|
+
// A refused chat with no code keeps the built-in's 401, and a quota is a
|
|
729
|
+
// 429.
|
|
730
|
+
const QUEUED = "10605"
|
|
731
|
+
// the codes Qoder's client counts as a plan's usage or credits used up
|
|
732
|
+
const QUOTA_CODES = new Set(["110", "112", "113", "114", "115", "116", "117", "118", "119", "122"])
|
|
733
|
+
// refusals of this request, not of the account: sensitive content, not
|
|
734
|
+
// supported, input too long, too many media, a custom model's service
|
|
735
|
+
const REQUEST_CODES = new Set(["406", "416", "430", "80411", "80412", "100400", "100401", "100403"])
|
|
736
|
+
const BUSY_WAIT = 30
|
|
737
|
+
|
|
725
738
|
function failure(status, text) {
|
|
726
739
|
if (status < 400 || status > 599) status = 502
|
|
727
740
|
let msg = String(text ?? "").trim()
|
|
741
|
+
let code = ""
|
|
742
|
+
let queue
|
|
728
743
|
try {
|
|
729
744
|
const j = JSON.parse(text)
|
|
730
|
-
|
|
745
|
+
code = j?.code == null ? "" : String(j.code)
|
|
746
|
+
if (j?.message) msg = String(j.message)
|
|
731
747
|
// details is a JSON string, or the object itself (gjson reads either)
|
|
732
748
|
const d = typeof j?.details === "string" ? JSON.parse(j.details) : j?.details
|
|
733
749
|
if (d?.error?.message) msg += ": " + d.error.message
|
|
750
|
+
// the queue's state: the message itself, as a JSON string, or a field
|
|
751
|
+
queue = j?.queue && typeof j.queue === "object" ? j.queue : undefined
|
|
752
|
+
if (!queue && typeof j?.message === "string" && j.message.trim().startsWith("{")) {
|
|
753
|
+
const q = JSON.parse(j.message)
|
|
754
|
+
if (q && typeof q === "object" && ("isQueued" in q || "serviceAvailable" in q || "retryAfterSeconds" in q)) queue = q
|
|
755
|
+
}
|
|
734
756
|
} catch {}
|
|
735
757
|
msg ||= STATUS_CODES[status] ?? `HTTP ${status}`
|
|
758
|
+
// Qoder's queue for the model: busy for now, with when to ask again. The
|
|
759
|
+
// sign-in is fine (the same token reads the models and the usage), so it
|
|
760
|
+
// is a 503 with Retry-After, which magpie asks again after, and never
|
|
761
|
+
// touches the account's sign-in.
|
|
762
|
+
if (code === QUEUED || queue?.isQueued === true || queue?.serviceAvailable === false) {
|
|
763
|
+
const n = Number(queue?.retryAfterSeconds)
|
|
764
|
+
const wait = Number.isFinite(n) && n > 0 ? Math.ceil(n) : BUSY_WAIT
|
|
765
|
+
const model = queue?.modelKey ? ` for ${queue.modelKey}` : ""
|
|
766
|
+
const tier = queue?.queueType ? ` (this plan's queue: ${queue.queueType})` : ""
|
|
767
|
+
const what = queue?.isQueued === true ? "queued the request" : "is busy"
|
|
768
|
+
return { status: 503, message: `Qoder ${what}${model}${tier}; try again in ${wait}s`, retryAfter: wait, signIn: "" }
|
|
769
|
+
}
|
|
770
|
+
if (QUOTA_CODES.has(code)) return { status: 429, message: "usage limit reached: " + msg, signIn: "" }
|
|
771
|
+
if (REQUEST_CODES.has(code)) return { status: 400, message: `Qoder refused the request (${code}): ${msg}`, signIn: "" }
|
|
736
772
|
// a refused chat is the built-in's 401, which never marked the account
|
|
737
773
|
// lapsed: only a refused refresh did (errorResponse says kept). Qoder's
|
|
738
774
|
// own words go with it: a 401 right after signing in isn't a lapsed
|
|
@@ -747,11 +783,16 @@ function failure(status, text) {
|
|
|
747
783
|
|
|
748
784
|
// errorResponse is a failure as OpenAI's API gives it. signIn is what it
|
|
749
785
|
// means for the account (magpie's X-Magpie-Sign-In): a 401 keeps it unless
|
|
750
|
-
// told expired, since the built-in marked only a refused refresh.
|
|
751
|
-
|
|
786
|
+
// told expired, since the built-in marked only a refused refresh. retryAfter
|
|
787
|
+
// (seconds) is sent as Retry-After.
|
|
788
|
+
const errorResponse = ({ status, message, signIn = status === 401 ? "kept" : undefined, retryAfter }) =>
|
|
752
789
|
new Response(JSON.stringify({ error: { message, type: "qoder_error", code: status } }), {
|
|
753
790
|
status,
|
|
754
|
-
headers: {
|
|
791
|
+
headers: {
|
|
792
|
+
"Content-Type": "application/json",
|
|
793
|
+
...(signIn ? { "X-Magpie-Sign-In": signIn } : {}),
|
|
794
|
+
...(retryAfter > 0 ? { "Retry-After": String(retryAfter) } : {}),
|
|
795
|
+
},
|
|
755
796
|
})
|
|
756
797
|
|
|
757
798
|
// ---- the reply ----------------------------------------------------------------
|
package/package.json
CHANGED