@bivy/bivy 0.10.1-staging.147 → 0.10.1-staging.149
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.
|
@@ -16,6 +16,22 @@ import { createCredentialVault } from "../credential-store.js";
|
|
|
16
16
|
import { getModelOAuthProvider } from "./model-oauth-providers.js";
|
|
17
17
|
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
18
18
|
// --- HTTP helpers ------------------------------------------------------------
|
|
19
|
+
/** A failed token/device response that keeps the machine-readable OAuth `error`
|
|
20
|
+
* code separate from the human `error_description`. The device poll matches on
|
|
21
|
+
* the code (e.g. `authorization_pending`) — providers like xAI return a friendly
|
|
22
|
+
* description ("User has not yet authorized") that would otherwise mask it. */
|
|
23
|
+
class OAuthTokenError extends Error {
|
|
24
|
+
status;
|
|
25
|
+
code;
|
|
26
|
+
description;
|
|
27
|
+
constructor(status, code, description) {
|
|
28
|
+
super(`OAuth token request failed (${status}): ${description || code || "unknown error"}`);
|
|
29
|
+
this.status = status;
|
|
30
|
+
this.code = code;
|
|
31
|
+
this.description = description;
|
|
32
|
+
this.name = "OAuthTokenError";
|
|
33
|
+
}
|
|
34
|
+
}
|
|
19
35
|
async function postToken(url, encoding, body) {
|
|
20
36
|
const res = await fetch(url, {
|
|
21
37
|
method: "POST",
|
|
@@ -33,8 +49,9 @@ async function postToken(url, encoding, body) {
|
|
|
33
49
|
throw new Error(`Token endpoint returned non-JSON (${res.status}): ${text.slice(0, 200)}`);
|
|
34
50
|
}
|
|
35
51
|
if (!res.ok) {
|
|
36
|
-
const
|
|
37
|
-
|
|
52
|
+
const code = typeof payload.error === "string" ? payload.error : "";
|
|
53
|
+
const description = (typeof payload.error_description === "string" ? payload.error_description : "") || text.slice(0, 200);
|
|
54
|
+
throw new OAuthTokenError(res.status, code, description);
|
|
38
55
|
}
|
|
39
56
|
return payload;
|
|
40
57
|
}
|
|
@@ -268,12 +285,16 @@ async function loginDeviceCode(provider, interaction) {
|
|
|
268
285
|
});
|
|
269
286
|
}
|
|
270
287
|
catch (error) {
|
|
288
|
+
// Prefer the machine-readable OAuth `error` code; fall back to the message
|
|
289
|
+
// for providers (xAI) that return a friendly description like "User has not
|
|
290
|
+
// yet authorized" instead of the RFC-8628 `authorization_pending` code.
|
|
291
|
+
const code = error instanceof OAuthTokenError ? error.code : "";
|
|
271
292
|
const message = error instanceof Error ? error.message : String(error);
|
|
272
|
-
if (/authorization_pending/i.test(message)) {
|
|
293
|
+
if (code === "authorization_pending" || /authorization_pending|not yet authorized/i.test(message)) {
|
|
273
294
|
await sleep(interval);
|
|
274
295
|
continue;
|
|
275
296
|
}
|
|
276
|
-
if (/slow_down/i.test(message)) {
|
|
297
|
+
if (code === "slow_down" || /slow_down/i.test(message)) {
|
|
277
298
|
interval += 5000;
|
|
278
299
|
await sleep(interval);
|
|
279
300
|
continue;
|
package/package.json
CHANGED