@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 err = (payload.error_description || payload.error || text.slice(0, 200));
37
- throw new Error(`OAuth token request failed (${res.status}): ${err}`);
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bivy/bivy",
3
- "version": "0.10.1-staging.147",
3
+ "version": "0.10.1-staging.149",
4
4
  "type": "module",
5
5
  "license": "AGPL-3.0-only",
6
6
  "description": "Run coding agents on machines you own. Open-source, self-hostable agent workspace.",