nolo-cli 0.27.0 → 0.28.0

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.
Files changed (68) hide show
  1. package/{_executeModel-GBJY45QW.js → _executeModel-SUMILI7E.js} +13 -13
  2. package/{agentDeleteCommand-VFHDZJG3.js → agentDeleteCommand-GEHAXWM6.js} +7 -7
  3. package/{agentEmailCommands-NV64EI7G.js → agentEmailCommands-PQXAKGK2.js} +17 -17
  4. package/{agentListCommands-BDDUYHLP.js → agentListCommands-V2IIWNTX.js} +8 -8
  5. package/{agentMachineCommands-2KYBYNLE.js → agentMachineCommands-Y47CABE2.js} +7 -7
  6. package/{agentRecordCommands-3OX576G3.js → agentRecordCommands-UYUJUT4K.js} +16 -16
  7. package/{agentRunCommand-FZOGN67Y.js → agentRunCommand-3P6CCJQK.js} +17 -17
  8. package/{agentRuntimeLocal-552R4CZA.js → agentRuntimeLocal-ZALQDCZ3.js} +4 -4
  9. package/{agentSlice-7AEBCNVZ.js → agentSlice-LH2YKWE7.js} +1 -1
  10. package/{appDeleteCommands-IPJT6IYW.js → appDeleteCommands-XELAKISE.js} +8 -8
  11. package/{appDeployCommands-24P4CADQ.js → appDeployCommands-PFHVHXJ3.js} +8 -8
  12. package/{appDeployStatusCommands-3DRZOUAG.js → appDeployStatusCommands-RULB3DGE.js} +8 -8
  13. package/{appGetCommands-JEOSBLUL.js → appGetCommands-A3NLQ2U5.js} +8 -8
  14. package/{appListCommands-EIBM54WR.js → appListCommands-NQLJ7RHY.js} +8 -8
  15. package/{authCommand-MKMYHD52.js → authCommand-XMQHBK5L.js} +470 -40
  16. package/chunk-2FX23RGA.js +162 -0
  17. package/{chunk-6MBOZ4UP.js → chunk-2TYLTEAH.js} +1 -1
  18. package/{chunk-W2IOPRHX.js → chunk-4O2L6YR5.js} +3 -3
  19. package/{chunk-X43U4JUJ.js → chunk-4UYKPT74.js} +1 -1
  20. package/{chunk-TTPVLL5F.js → chunk-7IX2Z2IF.js} +8 -8
  21. package/{chunk-3X4IYB22.js → chunk-7OYY7W4W.js} +2 -2
  22. package/{chunk-ZNFZGHKL.js → chunk-7ZKK4F22.js} +1 -1
  23. package/{chunk-YZV4676I.js → chunk-A6WDXLAG.js} +2 -2
  24. package/{chunk-KXEWHQAW.js → chunk-ATGTWONB.js} +1 -1
  25. package/{chunk-Z3ORPMOA.js → chunk-BTA2CW6H.js} +6 -6
  26. package/{chunk-J7PB5GXH.js → chunk-D36OKPFG.js} +1 -1
  27. package/{chunk-56CPK6JE.js → chunk-D5D3XTWF.js} +30 -35
  28. package/{chunk-V7BUGVT2.js → chunk-E4XWECLB.js} +2 -2
  29. package/{chunk-UADEEVDX.js → chunk-HTLBU4ZY.js} +5 -5
  30. package/{chunk-N32A423D.js → chunk-IVMPWUAR.js} +2 -2
  31. package/{chunk-O5VFD7V6.js → chunk-MSXDPLDQ.js} +1 -1
  32. package/{chunk-NCRWA6ZB.js → chunk-MY54LNPC.js} +2 -2
  33. package/{chunk-4FRIAKSZ.js → chunk-OMN2LILO.js} +1 -1
  34. package/{chunk-7OYLPHDL.js → chunk-PASYOZYI.js} +22 -65
  35. package/{chunk-AL2V7U3E.js → chunk-PJY5AH5A.js} +25 -8
  36. package/chunk-PSK2RUHV.js +529 -0
  37. package/{chunk-Q4TAIQTA.js → chunk-QUXMWSCQ.js} +21 -47
  38. package/{chunk-PVWFM7JP.js → chunk-RRWRVIQU.js} +1 -1
  39. package/{chunk-QCUS52YR.js → chunk-SFFG3HJH.js} +3 -3
  40. package/{chunk-7WMLPRXP.js → chunk-UP7UFQOH.js} +1 -1
  41. package/{chunk-VV4TYWNV.js → chunk-WX3ZOSTL.js} +376 -656
  42. package/{chunk-HQFXBRI2.js → chunk-XMAELUQW.js} +11 -11
  43. package/{chunk-7OBMZCRD.js → chunk-ZVZMT3EA.js} +7 -5
  44. package/{createAgentAutomationAction-YB65NAU5.js → createAgentAutomationAction-FAYQK5ME.js} +2 -2
  45. package/{createDialogAction-6USRBKKL.js → createDialogAction-NDBK6IQG.js} +3 -3
  46. package/{createPageAction-ZGE3SG6J.js → createPageAction-CQTLV7FP.js} +2 -2
  47. package/{dialogCommands-O4CJJRTQ.js → dialogCommands-ZR42K2M5.js} +8 -8
  48. package/{dialogSlice-HMRBZCSE.js → dialogSlice-ZLGEYKLO.js} +2 -2
  49. package/{docCreateCommands-2U5AIF3O.js → docCreateCommands-2WXA3BCQ.js} +7 -7
  50. package/{docDeleteCommands-EDCAUQEF.js → docDeleteCommands-HSL7CD32.js} +8 -8
  51. package/{docReadCommands-KFMBFGPY.js → docReadCommands-YSPUU2DP.js} +7 -7
  52. package/{docStore-ZGGDZFCC.js → docStore-LJQIY2ZU.js} +3 -3
  53. package/{docUpdateCommands-57M4XOT7.js → docUpdateCommands-EFYOIVM7.js} +7 -7
  54. package/{handleSendMessageAction-ANCZXLQY.js → handleSendMessageAction-JL6GGVNW.js} +2 -2
  55. package/index.js +46 -46
  56. package/{machineCommands-6EG5U6TU.js → machineCommands-VAANUFNC.js} +15 -15
  57. package/{machineWsRunDispatch-SFIKRI4G.js → machineWsRunDispatch-ABWV2WZO.js} +15 -15
  58. package/package.json +1 -1
  59. package/{readlineWorkspace-TVIHBRN2.js → readlineWorkspace-GQI3XP5E.js} +41 -44
  60. package/{runAgentClientLoop-SJ6QQ3ZS.js → runAgentClientLoop-U632N2KO.js} +9 -9
  61. package/{skillDiscovery-KJWT7JBU.js → skillDiscovery-ITA7BI7A.js} +4 -2
  62. package/{spaceCommands-XK46FRYG.js → spaceCommands-DE6KNJIV.js} +7 -7
  63. package/{spaceSlice-FNFNVXPQ.js → spaceSlice-QTMWWQHQ.js} +2 -2
  64. package/{streamAgentChatTurn-HHIWP44U.js → streamAgentChatTurn-VU7BM3K3.js} +12 -12
  65. package/{tools-CT7AFBI3.js → tools-LSIS6NY6.js} +5 -5
  66. package/{updateDialogTitleAction-7RFN5GA4.js → updateDialogTitleAction-T77A54DE.js} +2 -2
  67. package/chunk-UTYJ47H2.js +0 -51
  68. package/chunk-ZJ7WLPDP.js +0 -553
@@ -1,6 +1,17 @@
1
1
  import {
2
- getAntigravityUserAgent
3
- } from "./chunk-UTYJ47H2.js";
2
+ ANTIGRAVITY_AUTH_URL,
3
+ ANTIGRAVITY_CALLBACK_PATH,
4
+ ANTIGRAVITY_CALLBACK_PORT,
5
+ ANTIGRAVITY_CLIENT_ID,
6
+ ANTIGRAVITY_CLIENT_SECRET,
7
+ ANTIGRAVITY_CLOUD_CODE_BASE_URL,
8
+ ANTIGRAVITY_SCOPES,
9
+ ANTIGRAVITY_TOKEN_URL,
10
+ ANTIGRAVITY_USERINFO_URL,
11
+ getAntigravityUserAgent,
12
+ normalizeAntigravityTokenPayload,
13
+ refreshAntigravityToken
14
+ } from "./chunk-2FX23RGA.js";
4
15
  import {
5
16
  writeOAuthCredential
6
17
  } from "./chunk-JZPBVBIY.js";
@@ -153,28 +164,9 @@ function generatePkcePair(length = PKCE_VERIFIER_LENGTH) {
153
164
  }
154
165
 
155
166
  // packages/cli/oauth/flows/antigravity.ts
156
- var decode = (s) => Buffer.from(s, "base64").toString("utf8");
157
- var CLIENT_ID = decode(
158
- "MTA3MTAwNjA2MDU5MS10bWhzc2luMmgyMWxjcmUyMzV2dG9sb2poNGc0MDNlcC5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbQ=="
159
- );
160
- var CLIENT_SECRET = decode("R09DU1BYLUs1OEZXUjQ4NkxkTEoxbUxCOHNYQzR6NnFEQWY=");
161
- var CALLBACK_PORT = 51121;
162
- var CALLBACK_PATH = "/oauth-callback";
163
- var SCOPES = [
164
- "https://www.googleapis.com/auth/cloud-platform",
165
- "https://www.googleapis.com/auth/userinfo.email",
166
- "https://www.googleapis.com/auth/userinfo.profile",
167
- "https://www.googleapis.com/auth/cclog",
168
- "https://www.googleapis.com/auth/experimentsandconfigs"
169
- ];
170
- var AUTH_URL = "https://accounts.google.com/o/oauth2/v2/auth";
171
- var TOKEN_URL = "https://oauth2.googleapis.com/token";
172
- var USERINFO_URL = "https://www.googleapis.com/oauth2/v1/userinfo?alt=json";
173
- var CLOUD_CODE_ENDPOINT = "https://daily-cloudcode-pa.googleapis.com";
174
167
  var TIER_LEGACY = "legacy-tier";
175
168
  var PROJECT_ONBOARD_MAX_ATTEMPTS = 5;
176
169
  var PROJECT_ONBOARD_INTERVAL_MS = 2e3;
177
- var ACCESS_TOKEN_CLIENT_SKEW_MS = 5 * 60 * 1e3;
178
170
  var ANTIGRAVITY_LOAD_CODE_ASSIST_METADATA = Object.freeze({
179
171
  ideType: "ANTIGRAVITY",
180
172
  platform: "PLATFORM_UNSPECIFIED",
@@ -251,7 +243,7 @@ async function discoverProject(fetchImpl, accessToken, onProgress) {
251
243
  "User-Agent": getAntigravityUserAgent()
252
244
  };
253
245
  onProgress?.("Checking for existing project...");
254
- const endpoint = CLOUD_CODE_ENDPOINT;
246
+ const endpoint = ANTIGRAVITY_CLOUD_CODE_BASE_URL;
255
247
  const loadResponse = await fetchImpl(`${endpoint}/v1internal:loadCodeAssist`, {
256
248
  method: "POST",
257
249
  headers,
@@ -286,7 +278,7 @@ async function discoverProject(fetchImpl, accessToken, onProgress) {
286
278
  }
287
279
  async function getUserEmail(fetchImpl, accessToken) {
288
280
  try {
289
- const response = await fetchImpl(USERINFO_URL, {
281
+ const response = await fetchImpl(ANTIGRAVITY_USERINFO_URL, {
290
282
  headers: { Authorization: `Bearer ${accessToken}` }
291
283
  });
292
284
  if (!response.ok) return void 0;
@@ -305,32 +297,32 @@ async function runAntigravityOAuthLogin(deps = {}) {
305
297
  const fetchImpl = deps.fetchImpl ?? fetch;
306
298
  const output = deps.output ?? console;
307
299
  const error = deps.error ?? console;
308
- const redirectUri = `http://127.0.0.1:${CALLBACK_PORT}${CALLBACK_PATH}`;
300
+ const redirectUri = `http://127.0.0.1:${ANTIGRAVITY_CALLBACK_PORT}${ANTIGRAVITY_CALLBACK_PATH}`;
309
301
  let handle;
310
302
  try {
311
303
  handle = await startCallbackServer({
312
- port: CALLBACK_PORT,
304
+ port: ANTIGRAVITY_CALLBACK_PORT,
313
305
  hostname: "127.0.0.1",
314
306
  timeoutMs: 5 * 6e4
315
307
  });
316
308
  } catch (err) {
317
309
  throw new Error(
318
- `Failed to start Antigravity OAuth callback server on ${CALLBACK_PORT}: ${toErrorMessage(err)}`
310
+ `Failed to start Antigravity OAuth callback server on ${ANTIGRAVITY_CALLBACK_PORT}: ${toErrorMessage(err)}`
319
311
  );
320
312
  }
321
313
  try {
322
314
  const state = generateState();
323
315
  const pkce = await generatePkcePair();
324
316
  const authParams = new URLSearchParams({
325
- client_id: CLIENT_ID,
317
+ client_id: ANTIGRAVITY_CLIENT_ID,
326
318
  response_type: "code",
327
319
  redirect_uri: redirectUri,
328
- scope: SCOPES.join(" "),
320
+ scope: ANTIGRAVITY_SCOPES.join(" "),
329
321
  state,
330
322
  access_type: "offline",
331
323
  prompt: "consent"
332
324
  });
333
- const authUrl = `${AUTH_URL}?${authParams.toString()}`;
325
+ const authUrl = `${ANTIGRAVITY_AUTH_URL}?${authParams.toString()}`;
334
326
  output.log(
335
327
  `Open the following URL in your browser to log in to Antigravity:
336
328
  ${authUrl}`
@@ -345,15 +337,16 @@ async function runAntigravityOAuthLogin(deps = {}) {
345
337
  }
346
338
  }
347
339
  const callback = await handle.waitForCode();
348
- const tokenResponse = await fetchImpl(TOKEN_URL, {
340
+ const tokenResponse = await fetchImpl(ANTIGRAVITY_TOKEN_URL, {
349
341
  method: "POST",
350
342
  headers: { "Content-Type": "application/x-www-form-urlencoded" },
351
343
  body: new URLSearchParams({
352
- client_id: CLIENT_ID,
353
- client_secret: CLIENT_SECRET,
344
+ client_id: ANTIGRAVITY_CLIENT_ID,
345
+ client_secret: ANTIGRAVITY_CLIENT_SECRET,
354
346
  code: callback.code,
355
347
  grant_type: "authorization_code",
356
- redirect_uri: redirectUri
348
+ redirect_uri: redirectUri,
349
+ code_verifier: pkce.verifier
357
350
  })
358
351
  });
359
352
  if (!tokenResponse.ok) {
@@ -361,66 +354,43 @@ async function runAntigravityOAuthLogin(deps = {}) {
361
354
  throw new Error(`Antigravity token exchange failed: ${body}`);
362
355
  }
363
356
  const tokenData = await tokenResponse.json();
364
- if (!tokenData.refresh_token) {
357
+ if (typeof tokenData.refresh_token !== "string" || !tokenData.refresh_token.trim()) {
365
358
  throw new Error("No refresh token received. Please try again.");
366
359
  }
367
- const email = await getUserEmail(fetchImpl, tokenData.access_token);
360
+ if (typeof tokenData.access_token !== "string" || !tokenData.access_token.trim()) {
361
+ throw new Error("No access token received. Please try again.");
362
+ }
363
+ const email = await getUserEmail(fetchImpl, tokenData.access_token.trim());
368
364
  const projectId = await discoverProject(
369
365
  fetchImpl,
370
- tokenData.access_token,
366
+ tokenData.access_token.trim(),
371
367
  (message) => output.log(message)
372
368
  );
373
369
  const now = (deps.now ?? Date.now)();
374
- return {
375
- provider: "antigravity",
376
- accessToken: tokenData.access_token,
377
- refreshToken: tokenData.refresh_token,
378
- expiresAt: now + tokenData.expires_in * 1e3 - ACCESS_TOKEN_CLIENT_SKEW_MS,
379
- scope: tokenData.scope,
380
- obtainedAt: now,
381
- metadata: {
382
- projectId,
383
- email
384
- }
385
- };
370
+ return normalizeAntigravityTokenPayload({
371
+ payload: tokenData,
372
+ baseCredential: {
373
+ provider: "antigravity",
374
+ accountId: email,
375
+ metadata: {
376
+ projectId,
377
+ email
378
+ }
379
+ },
380
+ now
381
+ });
386
382
  } finally {
387
383
  await handle.close();
388
384
  }
389
385
  }
390
- async function refreshAntigravityOAuthToken(credential) {
391
- if (!credential.refreshToken) {
392
- throw new Error("Antigravity credential has no refresh_token");
393
- }
394
- const fetchImpl = fetch;
395
- const projectId = credential.metadata?.projectId ?? void 0;
396
- const response = await fetchImpl(TOKEN_URL, {
397
- method: "POST",
398
- headers: { "Content-Type": "application/x-www-form-urlencoded" },
399
- body: new URLSearchParams({
400
- client_id: CLIENT_ID,
401
- client_secret: CLIENT_SECRET,
402
- refresh_token: credential.refreshToken,
403
- grant_type: "refresh_token"
404
- })
405
- });
406
- if (!response.ok) {
407
- const body = await response.text();
408
- throw new Error(`Antigravity token refresh failed: ${body}`);
409
- }
410
- const data = await response.json();
411
- const now = Date.now();
412
- return {
413
- ...credential,
414
- accessToken: data.access_token,
415
- refreshToken: data.refresh_token || credential.refreshToken,
416
- expiresAt: now + data.expires_in * 1e3 - ACCESS_TOKEN_CLIENT_SKEW_MS,
417
- scope: data.scope ?? credential.scope,
418
- obtainedAt: now
419
- };
386
+ async function refreshAntigravityOAuthToken(credential, deps = {}) {
387
+ return refreshAntigravityToken(credential, deps);
420
388
  }
421
389
 
422
390
  // packages/cli/oauth/flows/openai-codex.ts
423
391
  import { createHash as createHash2 } from "node:crypto";
392
+
393
+ // packages/agent-runtime/openaiCodexOAuth.ts
424
394
  var OPENAI_CODEX_CLIENT_ID = "app_EMoamEEZ73f0CkXaXp7hrann";
425
395
  var OPENAI_CODEX_SCOPES = [
426
396
  "openid",
@@ -440,8 +410,104 @@ var OPENAI_CODEX_ORIGINATOR = "codex_cli_rs";
440
410
  var OPENAI_CODEX_CALLBACK_PORT = 1455;
441
411
  var OPENAI_CODEX_CALLBACK_PATH = "/auth/callback";
442
412
  var OPENAI_CODEX_CALLBACK_URL = `http://localhost:${OPENAI_CODEX_CALLBACK_PORT}${OPENAI_CODEX_CALLBACK_PATH}`;
413
+ var OPENAI_CODEX_ACCESS_TOKEN_CLIENT_SKEW_MS = 5 * 60 * 1e3;
414
+ var OPENAI_CODEX_TOKEN_REQUEST_TIMEOUT_MS = 3e4;
415
+ function decodeOpenAiIdToken(idToken) {
416
+ if (!idToken || typeof idToken !== "string") return {};
417
+ const parts = idToken.split(".");
418
+ if (parts.length < 2) return {};
419
+ try {
420
+ const payload = JSON.parse(
421
+ Buffer.from(parts[1], "base64url").toString("utf-8")
422
+ );
423
+ const authClaim = payload["https://api.openai.com/auth"];
424
+ const nestedAccountId = authClaim && typeof authClaim === "object" ? authClaim.chatgpt_account_id : void 0;
425
+ const accountId = nestedAccountId ?? payload["chatgpt_account_id"] ?? payload["account_id"];
426
+ const email = payload["email"];
427
+ return {
428
+ ...typeof accountId === "string" && accountId.trim() ? { accountId: accountId.trim() } : {},
429
+ ...typeof email === "string" && email.trim() ? { email: email.trim() } : {}
430
+ };
431
+ } catch {
432
+ return {};
433
+ }
434
+ }
435
+ function normalizeOpenAiCodexTokenPayload(args) {
436
+ const { payload, baseCredential, now = Date.now() } = args;
437
+ if (typeof payload.access_token !== "string" || !payload.access_token.trim()) {
438
+ throw new Error("OpenAI Codex token response missing access_token");
439
+ }
440
+ const accessToken = payload.access_token.trim();
441
+ const expiresIn = asOptionalFiniteNumber(payload.expires_in);
442
+ const clientSkewMs = args.clientSkewMs ?? OPENAI_CODEX_ACCESS_TOKEN_CLIENT_SKEW_MS;
443
+ const expiresAt = expiresIn !== void 0 ? now + expiresIn * 1e3 - clientSkewMs : baseCredential?.expiresAt;
444
+ const idTokenStr = typeof payload.id_token === "string" && payload.id_token.trim() ? payload.id_token.trim() : void 0;
445
+ const fromAccess = decodeOpenAiIdToken(accessToken);
446
+ const fromId = idTokenStr ? decodeOpenAiIdToken(idTokenStr) : {};
447
+ const accountId = fromAccess.accountId ?? fromId.accountId ?? baseCredential?.accountId;
448
+ const email = fromAccess.email ?? fromId.email ?? baseCredential?.metadata?.email;
449
+ const refreshToken = typeof payload.refresh_token === "string" && payload.refresh_token.trim() ? payload.refresh_token.trim() : baseCredential?.refreshToken;
450
+ const scope = typeof payload.scope === "string" && payload.scope.trim() ? payload.scope.trim() : baseCredential?.scope;
451
+ const metadata = {
452
+ ...baseCredential?.metadata ?? {},
453
+ ...email ? { email } : {}
454
+ };
455
+ return {
456
+ ...baseCredential ?? {},
457
+ provider: "chatgpt",
458
+ accessToken,
459
+ ...refreshToken ? { refreshToken } : {},
460
+ ...expiresAt !== void 0 ? { expiresAt } : {},
461
+ obtainedAt: now,
462
+ ...scope ? { scope } : {},
463
+ ...accountId ? { accountId } : {},
464
+ ...Object.keys(metadata).length > 0 ? { metadata } : {}
465
+ };
466
+ }
467
+ async function refreshOpenAiCodexToken(credential, deps = {}) {
468
+ if (!credential.refreshToken) {
469
+ throw new Error("Cannot refresh OpenAI Codex token without a refresh token.");
470
+ }
471
+ const fetchImpl = deps.fetchImpl ?? fetch;
472
+ const body = new URLSearchParams({
473
+ client_id: OPENAI_CODEX_CLIENT_ID,
474
+ grant_type: "refresh_token",
475
+ refresh_token: credential.refreshToken
476
+ });
477
+ let response;
478
+ try {
479
+ response = await fetchImpl(OPENAI_CODEX_TOKEN_URL, {
480
+ method: "POST",
481
+ headers: {
482
+ "Content-Type": "application/x-www-form-urlencoded",
483
+ Accept: "application/json"
484
+ },
485
+ body: body.toString(),
486
+ signal: AbortSignal.timeout(OPENAI_CODEX_TOKEN_REQUEST_TIMEOUT_MS)
487
+ });
488
+ } catch (error) {
489
+ throw new Error(
490
+ `OpenAI Codex token refresh failed: ${toErrorMessage(error)}`
491
+ );
492
+ }
493
+ const payload = await response.json().catch(() => ({}));
494
+ if (!response.ok) {
495
+ const detail = typeof payload.error_description === "string" && payload.error_description ? payload.error_description : typeof payload.error === "string" && payload.error ? payload.error : `HTTP ${response.status}`;
496
+ throw new Error(`OpenAI Codex token refresh failed: ${detail}`);
497
+ }
498
+ if (typeof payload.access_token !== "string" || !payload.access_token.trim()) {
499
+ throw new Error("OpenAI Codex token refresh response missing access_token");
500
+ }
501
+ const now = deps.now?.() ?? Date.now();
502
+ return normalizeOpenAiCodexTokenPayload({
503
+ payload,
504
+ baseCredential: credential,
505
+ now
506
+ });
507
+ }
508
+
509
+ // packages/cli/oauth/flows/openai-codex.ts
443
510
  var AUTHORIZATION_CODE_GRANT_TYPE = "authorization_code";
444
- var REFRESH_TOKEN_GRANT_TYPE = "refresh_token";
445
511
  var DEVICE_CODE_DEFAULT_INTERVAL_MS = 5e3;
446
512
  var DEVICE_POLL_SAFETY_MARGIN_MS = 3e3;
447
513
  var DEVICE_MAX_POLLS = 120;
@@ -470,76 +536,14 @@ async function postForm(fetchImpl, url, body, deps) {
470
536
  return response;
471
537
  }
472
538
  async function parseJsonResponse(response) {
473
- const text = await response.text().catch(() => "");
474
- if (!text) return {};
475
539
  try {
476
- return JSON.parse(text);
540
+ return await response.json();
477
541
  } catch {
478
542
  return {};
479
543
  }
480
544
  }
481
- function scopeString(scopes = OPENAI_CODEX_SCOPES) {
482
- return scopes.join(" ");
483
- }
484
- function base64UrlDecode(value) {
485
- const normalized = value.replace(/-/g, "+").replace(/_/g, "/");
486
- const padded = normalized.padEnd(normalized.length + (4 - normalized.length % 4) % 4, "=");
487
- return Buffer.from(padded, "base64").toString("utf8");
488
- }
489
- var OPENAI_AUTH_CLAIM = "https://api.openai.com/auth";
490
- var OPENAI_PROFILE_CLAIM = "https://api.openai.com/profile";
491
- function readClaimString(claim, key) {
492
- if (!claim || typeof claim !== "object") return void 0;
493
- const value = claim[key];
494
- return typeof value === "string" && value ? value : void 0;
495
- }
496
- function decodeOpenAiIdToken(idToken) {
497
- if (!idToken) return {};
498
- const parts = idToken.split(".");
499
- if (parts.length < 2) return {};
500
- try {
501
- const payload = JSON.parse(base64UrlDecode(parts[1]));
502
- const authClaim = payload[OPENAI_AUTH_CLAIM];
503
- const profileClaim = payload[OPENAI_PROFILE_CLAIM];
504
- return {
505
- chatgptAccountId: readClaimString(authClaim, "chatgpt_account_id") ?? (typeof payload["chatgpt_account_id"] === "string" ? payload["chatgpt_account_id"] : void 0),
506
- email: readClaimString(profileClaim, "email") ?? (typeof payload["email"] === "string" ? payload["email"] : void 0),
507
- payload
508
- };
509
- } catch {
510
- return {};
511
- }
512
- }
513
- function tokenResponseToCredential(token, now) {
514
- const fromAccess = decodeOpenAiIdToken(token.accessToken);
515
- const fromId = decodeOpenAiIdToken(token.idToken);
516
- const decoded = {
517
- chatgptAccountId: fromAccess.chatgptAccountId ?? fromId.chatgptAccountId,
518
- email: fromAccess.email ?? fromId.email
519
- };
520
- const expiresAt = typeof token.expiresIn === "number" && token.expiresIn > 0 ? now + token.expiresIn * 1e3 : void 0;
521
- return {
522
- provider: "chatgpt",
523
- accessToken: token.accessToken,
524
- ...token.refreshToken ? { refreshToken: token.refreshToken } : {},
525
- ...expiresAt ? { expiresAt } : {},
526
- ...token.scope ? { scope: token.scope } : {},
527
- ...token.idToken ? { idToken: token.idToken } : {},
528
- ...decoded.chatgptAccountId ? { accountId: decoded.chatgptAccountId } : {},
529
- obtainedAt: now
530
- };
531
- }
532
- function extractTokenResponse(data) {
533
- const accessToken = data["access_token"];
534
- if (typeof accessToken !== "string" || !accessToken) return null;
535
- const expiresInRaw = data["expires_in"];
536
- return {
537
- accessToken,
538
- ...typeof data["refresh_token"] === "string" ? { refreshToken: data["refresh_token"] } : {},
539
- ...typeof expiresInRaw === "number" ? { expiresIn: expiresInRaw } : {},
540
- ...typeof data["scope"] === "string" ? { scope: data["scope"] } : {},
541
- ...typeof data["id_token"] === "string" ? { idToken: data["id_token"] } : {}
542
- };
545
+ function scopeString() {
546
+ return OPENAI_CODEX_SCOPES.join(" ");
543
547
  }
544
548
  async function startDeviceCodeFlow(deps) {
545
549
  const fetchImpl = deps.fetchImpl ?? fetch;
@@ -574,11 +578,11 @@ async function startDeviceCodeFlow(deps) {
574
578
  }
575
579
  async function pollDeviceCodeToken(args) {
576
580
  const fetchImpl = args.deps?.fetchImpl ?? fetch;
577
- const sleep3 = args.sleep ?? args.deps?.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
581
+ const sleep2 = args.sleep ?? args.deps?.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
578
582
  const intervalMs = args.intervalMs ?? DEVICE_CODE_DEFAULT_INTERVAL_MS;
579
583
  const maxPolls = args.maxPolls ?? DEVICE_MAX_POLLS;
580
584
  for (let poll = 0; poll < maxPolls; poll++) {
581
- await sleep3(poll === 0 ? Math.min(intervalMs, DEVICE_CODE_DEFAULT_INTERVAL_MS) : intervalMs);
585
+ await sleep2(poll === 0 ? Math.min(intervalMs, DEVICE_CODE_DEFAULT_INTERVAL_MS) : intervalMs);
582
586
  const response = await postJson(
583
587
  fetchImpl,
584
588
  OPENAI_CODEX_DEVICE_TOKEN_URL,
@@ -644,7 +648,7 @@ async function runOpenAiCodexDeviceCode(deps = {}) {
644
648
  }
645
649
  async function exchangeCodexAuthorizationCode(args) {
646
650
  const fetchImpl = args.deps?.fetchImpl ?? fetch;
647
- const now = args.now ?? Date.now;
651
+ const now = (args.now ?? Date.now)();
648
652
  const response = await postForm(
649
653
  fetchImpl,
650
654
  OPENAI_CODEX_TOKEN_URL,
@@ -663,11 +667,10 @@ async function exchangeCodexAuthorizationCode(args) {
663
667
  `OpenAI authorization-code exchange failed (HTTP ${response.status}): ${JSON.stringify(data)}`
664
668
  );
665
669
  }
666
- const token = extractTokenResponse(data);
667
- if (!token) {
668
- throw new Error(`OpenAI authorization-code exchange returned no token: ${JSON.stringify(data)}`);
669
- }
670
- return tokenResponseToCredential(token, now());
670
+ return normalizeOpenAiCodexTokenPayload({
671
+ payload: data,
672
+ now
673
+ });
671
674
  }
672
675
  async function exchangeAuthorizationCode(args) {
673
676
  return exchangeCodexAuthorizationCode({
@@ -726,42 +729,14 @@ async function runOpenAiCodexBrowserPkce(deps = {}) {
726
729
  });
727
730
  }
728
731
  }
729
- var refreshOpenAiCodexToken = async (credential, deps = {}) => {
730
- if (!credential.refreshToken) {
731
- throw new Error("Cannot refresh ChatGPT OAuth token without a refresh_token.");
732
- }
733
- const fetchImpl = deps.fetchImpl ?? fetch;
734
- const now = deps.now ?? Date.now;
735
- const response = await postForm(
736
- fetchImpl,
737
- OPENAI_CODEX_TOKEN_URL,
738
- {
739
- grant_type: REFRESH_TOKEN_GRANT_TYPE,
740
- refresh_token: credential.refreshToken,
741
- client_id: OPENAI_CODEX_CLIENT_ID,
742
- scope: scopeString()
743
- },
744
- deps
745
- );
746
- const data = await parseJsonResponse(response);
747
- if (!response.ok) {
748
- throw new Error(
749
- `OpenAI token refresh failed (HTTP ${response.status}): ${JSON.stringify(data)}`
750
- );
751
- }
752
- const token = extractTokenResponse(data);
753
- if (!token) {
754
- throw new Error(`OpenAI token refresh returned no token: ${JSON.stringify(data)}`);
755
- }
756
- const refreshed = tokenResponseToCredential(token, now());
757
- return {
758
- ...refreshed,
759
- refreshToken: refreshed.refreshToken ?? credential.refreshToken,
760
- accountId: refreshed.accountId ?? credential.accountId
761
- };
732
+ var refreshOpenAiCodexToken2 = async (credential, deps = {}) => {
733
+ return refreshOpenAiCodexToken(credential, {
734
+ fetchImpl: deps.fetchImpl,
735
+ now: deps.now
736
+ });
762
737
  };
763
738
 
764
- // packages/cli/oauth/flows/xai.ts
739
+ // packages/agent-runtime/xaiOAuth.ts
765
740
  var XAI_OAUTH_ISSUER = "https://auth.x.ai";
766
741
  var XAI_OAUTH_DISCOVERY_URL = `${XAI_OAUTH_ISSUER}/.well-known/openid-configuration`;
767
742
  var XAI_OAUTH_CLIENT_ID = "b1a00492-073a-47ea-816f-4c329264a828";
@@ -769,15 +744,16 @@ var XAI_OAUTH_SCOPE = "openid profile email offline_access grok-cli:access api:a
769
744
  var XAI_OAUTH_REDIRECT_HOST = "127.0.0.1";
770
745
  var XAI_OAUTH_REDIRECT_PORT = 56121;
771
746
  var XAI_OAUTH_REDIRECT_PATH = "/callback";
747
+ var XAI_OAUTH_REDIRECT_URI = `http://${XAI_OAUTH_REDIRECT_HOST}:${XAI_OAUTH_REDIRECT_PORT}${XAI_OAUTH_REDIRECT_PATH}`;
772
748
  var XAI_OAUTH_DOCS_URL = "https://hermes-agent.nousresearch.com/docs/guides/xai-grok-oauth";
773
749
  var XAI_DEVICE_CODE_GRANT_TYPE = "urn:ietf:params:oauth:grant-type:device_code";
774
750
  var XAI_DEVICE_CODE_DEFAULT_INTERVAL_MS = 5e3;
775
751
  var XAI_DEVICE_CODE_MIN_INTERVAL_MS = 1e3;
776
752
  var XAI_DEVICE_CODE_SLOW_DOWN_INCREMENT_MS = 5e3;
777
753
  var XAI_DEVICE_CODE_DEFAULT_EXPIRES_MS = 5 * 6e4;
778
- var ACCESS_TOKEN_CLIENT_SKEW_MS2 = 5 * 60 * 1e3;
779
- var DISCOVERY_TIMEOUT_MS = 15e3;
780
- var TOKEN_REQUEST_TIMEOUT_MS = 2e4;
754
+ var XAI_ACCESS_TOKEN_CLIENT_SKEW_MS = 5 * 60 * 1e3;
755
+ var XAI_DISCOVERY_TIMEOUT_MS = 15e3;
756
+ var XAI_TOKEN_REQUEST_TIMEOUT_MS = 2e4;
781
757
  function validateXAIEndpoint(url, field) {
782
758
  let parsed;
783
759
  try {
@@ -835,8 +811,8 @@ async function readJsonBody(response, context) {
835
811
  );
836
812
  }
837
813
  }
838
- async function xaiOAuthDiscovery(fetchImpl, options = {}) {
839
- const timeoutMs = options.timeoutMs ?? DISCOVERY_TIMEOUT_MS;
814
+ async function xaiOAuthDiscovery(fetchImpl = fetch, options = {}) {
815
+ const timeoutMs = options.timeoutMs ?? XAI_DISCOVERY_TIMEOUT_MS;
840
816
  let response;
841
817
  try {
842
818
  response = await fetchImpl(XAI_OAUTH_DISCOVERY_URL, {
@@ -850,6 +826,14 @@ async function xaiOAuthDiscovery(fetchImpl, options = {}) {
850
826
  );
851
827
  }
852
828
  if (response.status !== 200) {
829
+ if (isLikelyHtmlOrCloudflareChallenge(
830
+ response,
831
+ await response.clone().text().catch(() => "")
832
+ )) {
833
+ throw new Error(
834
+ `xAI OIDC discovery failed (${response.status}): xAI returned an HTML/Cloudflare challenge instead of OAuth JSON`
835
+ );
836
+ }
853
837
  throw new Error(`xAI OIDC discovery returned status ${response.status}.`);
854
838
  }
855
839
  const obj = await readJsonBody(response, "xAI OIDC discovery");
@@ -879,72 +863,53 @@ async function xaiOAuthDiscovery(fetchImpl, options = {}) {
879
863
  ...deviceAuthorizationEndpoint ? { device_authorization_endpoint: deviceAuthorizationEndpoint } : {}
880
864
  };
881
865
  }
882
- function buildXAIAuthorizeUrl(opts) {
883
- const params = new URLSearchParams({
884
- response_type: "code",
885
- client_id: XAI_OAUTH_CLIENT_ID,
886
- redirect_uri: opts.redirectUri,
887
- scope: XAI_OAUTH_SCOPE,
888
- code_challenge: opts.codeChallenge,
889
- code_challenge_method: "S256",
890
- state: opts.state,
891
- nonce: opts.nonce,
892
- plan: "generic",
893
- referrer: "nolo-cli"
894
- });
895
- return `${opts.authorizationEndpoint}?${params.toString()}`;
896
- }
897
- function generateState2() {
898
- const bytes = new Uint8Array(16);
899
- crypto.getRandomValues(bytes);
900
- return Array.from(bytes).map((value) => value.toString(16).padStart(2, "0")).join("");
901
- }
902
- function parsePositiveSecondsToMs(value, fallbackMs) {
903
- const sec = typeof value === "number" ? value : typeof value === "string" ? Number.parseInt(value, 10) : NaN;
904
- if (!Number.isFinite(sec) || sec <= 0) return fallbackMs;
905
- return Math.max(1, Math.floor(sec * 1e3));
906
- }
907
- function parseOAuthTokenPayload(data, context, options = {}) {
908
- if (typeof data.access_token !== "string" || !data.access_token) {
866
+ function normalizeXaiTokenPayload(args) {
867
+ const {
868
+ payload,
869
+ baseCredential,
870
+ now = Date.now(),
871
+ requireRefreshToken = false,
872
+ context = "xAI OAuth token response"
873
+ } = args;
874
+ const accessToken = typeof payload.access_token === "string" ? payload.access_token.trim() : "";
875
+ if (!accessToken) {
909
876
  throw new Error(`${context} missing access_token`);
910
877
  }
911
- const refreshToken = typeof data.refresh_token === "string" && data.refresh_token ? data.refresh_token : void 0;
912
- if (options.requireRefreshToken && !refreshToken) {
878
+ const rawRefreshToken = typeof payload.refresh_token === "string" && payload.refresh_token.trim() ? payload.refresh_token.trim() : void 0;
879
+ if (requireRefreshToken && !rawRefreshToken) {
913
880
  throw new Error(`${context} missing refresh_token`);
914
881
  }
915
- const expiresIn = asOptionalFiniteNumber(data.expires_in);
882
+ const expiresIn = asOptionalFiniteNumber(payload.expires_in);
916
883
  if (expiresIn === void 0) {
917
884
  throw new Error(`${context} missing expires_in`);
918
885
  }
886
+ const refreshToken = rawRefreshToken ?? baseCredential?.refreshToken;
887
+ const scope = typeof payload.scope === "string" && payload.scope.trim() ? payload.scope.trim() : baseCredential?.scope;
888
+ const idToken = typeof payload.id_token === "string" && payload.id_token.trim() ? payload.id_token.trim() : baseCredential?.idToken;
889
+ const accountId = typeof payload.account_id === "string" && payload.account_id ? payload.account_id : baseCredential?.accountId;
919
890
  return {
920
- accessToken: data.access_token,
921
- ...refreshToken ? { refreshToken } : {},
922
- expiresIn,
923
- scope: typeof data.scope === "string" ? data.scope : void 0,
924
- idToken: typeof data.id_token === "string" ? data.id_token : void 0
925
- };
926
- }
927
- function tokenToCredential(token, now) {
928
- const expiresIn = token.expiresIn;
929
- return {
891
+ ...baseCredential,
930
892
  provider: "xai",
931
- accessToken: token.accessToken,
932
- refreshToken: token.refreshToken,
933
- expiresAt: now + expiresIn * 1e3 - ACCESS_TOKEN_CLIENT_SKEW_MS2,
934
- scope: token.scope,
935
- idToken: token.idToken,
893
+ accessToken,
894
+ ...refreshToken ? { refreshToken } : {},
895
+ expiresAt: now + expiresIn * 1e3 - XAI_ACCESS_TOKEN_CLIENT_SKEW_MS,
896
+ ...scope ? { scope } : {},
897
+ ...idToken ? { idToken } : {},
898
+ ...accountId ? { accountId } : {},
936
899
  obtainedAt: now
937
900
  };
938
901
  }
939
- async function exchangeXAIToken(fetchImpl, code, redirectUri, verifier) {
902
+ async function refreshXaiToken(credential, deps = {}) {
903
+ if (!credential.refreshToken) {
904
+ throw new Error("xAI credential has no refresh_token");
905
+ }
906
+ const fetchImpl = deps.fetchImpl ?? fetch;
940
907
  const discovery = await xaiOAuthDiscovery(fetchImpl);
941
908
  const tokenEndpoint = validateXAIEndpoint(discovery.token_endpoint, "token_endpoint");
942
909
  const body = new URLSearchParams({
943
- grant_type: "authorization_code",
910
+ grant_type: "refresh_token",
944
911
  client_id: XAI_OAUTH_CLIENT_ID,
945
- code,
946
- redirect_uri: redirectUri,
947
- code_verifier: verifier
912
+ refresh_token: credential.refreshToken
948
913
  });
949
914
  let response;
950
915
  try {
@@ -955,448 +920,175 @@ async function exchangeXAIToken(fetchImpl, code, redirectUri, verifier) {
955
920
  Accept: "application/json"
956
921
  },
957
922
  body,
958
- signal: AbortSignal.timeout(TOKEN_REQUEST_TIMEOUT_MS)
923
+ signal: AbortSignal.timeout(XAI_TOKEN_REQUEST_TIMEOUT_MS)
959
924
  });
960
925
  } catch (error) {
961
926
  throw new Error(
962
- `xAI token exchange failed: ${toErrorMessage(error)}`
927
+ `xAI token refresh failed: ${toErrorMessage(error)}`
963
928
  );
964
929
  }
965
- const data = await readJsonBody(response, "xAI token exchange");
930
+ const data = await readJsonBody(response, "xAI token refresh");
966
931
  if (!response.ok) {
967
932
  const detail = typeof data.error_description === "string" && data.error_description || typeof data.error === "string" && data.error || "";
968
933
  throw new Error(
969
- `xAI token exchange failed: ${response.status}${detail ? ` ${detail}` : ""}`
934
+ `xAI token refresh failed: ${response.status}${detail ? ` ${detail}` : ""}`
970
935
  );
971
936
  }
972
- return parseOAuthTokenPayload(data, "xAI token exchange response", {
973
- requireRefreshToken: true
937
+ const now = deps.now?.() ?? Date.now();
938
+ return normalizeXaiTokenPayload({
939
+ payload: data,
940
+ baseCredential: credential,
941
+ now,
942
+ context: "xAI token refresh response"
974
943
  });
975
944
  }
976
- async function requestXaiDeviceCode(fetchImpl, deviceAuthorizationEndpoint) {
977
- const endpoint = validateXAIEndpoint(
978
- deviceAuthorizationEndpoint,
979
- "device_authorization_endpoint"
980
- );
981
- let response;
982
- try {
983
- response = await fetchImpl(endpoint, {
984
- method: "POST",
985
- headers: {
986
- "Content-Type": "application/x-www-form-urlencoded",
987
- Accept: "application/json"
988
- },
989
- body: new URLSearchParams({
990
- client_id: XAI_OAUTH_CLIENT_ID,
991
- scope: XAI_OAUTH_SCOPE
992
- }),
993
- signal: AbortSignal.timeout(TOKEN_REQUEST_TIMEOUT_MS)
994
- });
995
- } catch (error) {
996
- throw new Error(
997
- `xAI device code request failed: ${toErrorMessage(error)}`
998
- );
999
- }
1000
- const data = await readJsonBody(response, "xAI device code request");
1001
- if (!response.ok) {
1002
- const detail = typeof data.error_description === "string" && data.error_description || typeof data.error === "string" && data.error || "";
1003
- throw new Error(
1004
- `xAI device code request failed (${response.status})${detail ? `: ${detail}` : ""}`
1005
- );
1006
- }
1007
- const deviceCode = asTrimmedString(data.device_code);
1008
- const userCode = asTrimmedString(data.user_code);
1009
- const verificationUri = asTrimmedString(data.verification_uri);
1010
- const verificationUriComplete = asTrimmedString(
1011
- data.verification_uri_complete
1012
- );
1013
- if (!deviceCode || !userCode || !verificationUri) {
1014
- throw new Error(
1015
- "xAI device code response is missing device_code, user_code, or verification_uri"
1016
- );
1017
- }
1018
- validateXAIEndpoint(verificationUri, "verification_uri");
1019
- if (verificationUriComplete) {
1020
- validateXAIEndpoint(verificationUriComplete, "verification_uri_complete");
1021
- }
945
+ var xaiRefresh = refreshXaiToken;
946
+
947
+ // packages/agent-runtime/anthropicOAuth.ts
948
+ var ANTHROPIC_OAUTH_CLIENT_ID = "9d1c250a-e61b-44d9-88ed-5944d1962f5e";
949
+ var ANTHROPIC_OAUTH_AUTHORIZE_URL = "https://claude.ai/oauth/authorize";
950
+ var ANTHROPIC_OAUTH_TOKEN_URL = "https://api.anthropic.com/v1/oauth/token";
951
+ var ANTHROPIC_OAUTH_CALLBACK_PORT = 54545;
952
+ var ANTHROPIC_OAUTH_REDIRECT_URI = `http://localhost:${ANTHROPIC_OAUTH_CALLBACK_PORT}/callback`;
953
+ var ANTHROPIC_OAUTH_SCOPES = [
954
+ "org:create_api_key",
955
+ "user:profile",
956
+ "user:inference",
957
+ "user:sessions:claude_code",
958
+ "user:mcp_servers",
959
+ "user:file_upload"
960
+ ];
961
+ var ANTHROPIC_ACCESS_TOKEN_CLIENT_SKEW_MS = 5 * 60 * 1e3;
962
+ var ANTHROPIC_OAUTH_BETA = "oauth-2025-04-20";
963
+ function normalizeAnthropicTokenPayload(args) {
964
+ const { payload, baseCredential, now = Date.now() } = args;
965
+ if (typeof payload.access_token !== "string" || !payload.access_token.trim()) {
966
+ throw new Error("Claude OAuth token response missing access_token");
967
+ }
968
+ const expiresIn = asOptionalFiniteNumber(payload.expires_in);
969
+ const accountId = typeof payload.account?.uuid === "string" && payload.account.uuid ? payload.account.uuid : baseCredential?.accountId;
970
+ const email = typeof payload.account?.email_address === "string" && payload.account.email_address ? payload.account.email_address : baseCredential?.metadata?.email;
971
+ const organizationId = typeof payload.organization?.uuid === "string" && payload.organization.uuid ? payload.organization.uuid : baseCredential?.metadata?.organizationId;
972
+ const organizationName = typeof payload.organization?.name === "string" && payload.organization.name ? payload.organization.name : baseCredential?.metadata?.organizationName;
973
+ const refreshToken = typeof payload.refresh_token === "string" && payload.refresh_token.trim() ? payload.refresh_token.trim() : baseCredential?.refreshToken;
974
+ const scope = typeof payload.scope === "string" && payload.scope ? payload.scope : baseCredential?.scope;
975
+ const metadata = {
976
+ ...baseCredential?.metadata ?? {},
977
+ ...email ? { email } : {},
978
+ ...organizationId ? { organizationId } : {},
979
+ ...organizationName ? { organizationName } : {}
980
+ };
1022
981
  return {
1023
- deviceCode,
1024
- userCode,
1025
- verificationUri,
1026
- ...verificationUriComplete ? { verificationUriComplete } : {},
1027
- expiresInMs: parsePositiveSecondsToMs(
1028
- data.expires_in,
1029
- XAI_DEVICE_CODE_DEFAULT_EXPIRES_MS
1030
- ),
1031
- intervalMs: Math.max(
1032
- parsePositiveSecondsToMs(data.interval, XAI_DEVICE_CODE_DEFAULT_INTERVAL_MS),
1033
- XAI_DEVICE_CODE_MIN_INTERVAL_MS
1034
- )
982
+ ...baseCredential,
983
+ provider: "claude",
984
+ accessToken: payload.access_token.trim(),
985
+ ...refreshToken ? { refreshToken } : {},
986
+ ...expiresIn !== void 0 ? { expiresAt: now + expiresIn * 1e3 - ANTHROPIC_ACCESS_TOKEN_CLIENT_SKEW_MS } : baseCredential?.expiresAt !== void 0 ? { expiresAt: baseCredential.expiresAt } : {},
987
+ ...scope ? { scope } : {},
988
+ ...accountId ? { accountId } : {},
989
+ ...Object.keys(metadata).length > 0 ? { metadata } : {},
990
+ obtainedAt: now
1035
991
  };
1036
992
  }
1037
- async function pollXaiDeviceCodeToken(args) {
1038
- const tokenEndpoint = validateXAIEndpoint(args.tokenEndpoint, "token_endpoint");
1039
- const deadlineMs = args.now() + args.expiresInMs;
1040
- let intervalMs = args.intervalMs;
1041
- while (args.now() < deadlineMs) {
1042
- const remainingMs = Math.max(0, deadlineMs - args.now());
1043
- const delayMs = Math.min(Math.max(intervalMs, XAI_DEVICE_CODE_MIN_INTERVAL_MS), remainingMs);
1044
- if (delayMs > 0) {
1045
- await args.sleep(delayMs);
1046
- }
1047
- if (args.now() >= deadlineMs) break;
1048
- let response;
1049
- try {
1050
- response = await args.fetchImpl(tokenEndpoint, {
1051
- method: "POST",
1052
- headers: {
1053
- "Content-Type": "application/x-www-form-urlencoded",
1054
- Accept: "application/json"
1055
- },
1056
- body: new URLSearchParams({
1057
- grant_type: XAI_DEVICE_CODE_GRANT_TYPE,
1058
- client_id: XAI_OAUTH_CLIENT_ID,
1059
- device_code: args.deviceCode
1060
- }),
1061
- signal: AbortSignal.timeout(TOKEN_REQUEST_TIMEOUT_MS)
1062
- });
1063
- } catch (error) {
1064
- const message = toErrorMessage(error);
1065
- if (/abort|timeout/i.test(message)) {
1066
- throw new Error(`xAI device token poll aborted or timed out: ${message}`);
1067
- }
1068
- throw new Error(`xAI device token poll failed: ${message}`);
1069
- }
1070
- let data;
1071
- try {
1072
- data = await readJsonBody(response, "xAI device token exchange");
1073
- } catch (error) {
1074
- throw error;
1075
- }
1076
- if (response.ok) {
1077
- return parseOAuthTokenPayload(data, "xAI device token exchange response", {
1078
- requireRefreshToken: true
1079
- });
1080
- }
1081
- const oauthError = typeof data.error === "string" ? data.error : "";
1082
- if (oauthError === "authorization_pending") {
1083
- continue;
1084
- }
1085
- if (oauthError === "slow_down") {
1086
- intervalMs += XAI_DEVICE_CODE_SLOW_DOWN_INCREMENT_MS;
1087
- continue;
1088
- }
1089
- if (oauthError === "access_denied" || oauthError === "authorization_denied") {
1090
- throw new Error("xAI device authorization was denied");
1091
- }
1092
- if (oauthError === "expired_token") {
1093
- throw new Error("xAI device code expired. Re-run the login.");
1094
- }
1095
- const detail = typeof data.error_description === "string" && data.error_description || oauthError || "";
1096
- throw new Error(
1097
- `xAI device token exchange failed (${response.status})${detail ? `: ${detail}` : ""}`
1098
- );
1099
- }
1100
- throw new Error("xAI device authorization timed out");
1101
- }
1102
- async function runXaiOAuthLogin(deps = {}) {
1103
- const fetchImpl = deps.fetchImpl ?? fetch;
1104
- const output = deps.output ?? console;
1105
- const error = deps.error ?? console;
1106
- const redirectUri = `http://${XAI_OAUTH_REDIRECT_HOST}:${XAI_OAUTH_REDIRECT_PORT}${XAI_OAUTH_REDIRECT_PATH}`;
1107
- let handle;
1108
- try {
1109
- handle = await startCallbackServer({
1110
- port: XAI_OAUTH_REDIRECT_PORT,
1111
- hostname: XAI_OAUTH_REDIRECT_HOST,
1112
- timeoutMs: 5 * 6e4
1113
- });
1114
- } catch (err) {
1115
- throw new Error(
1116
- `Failed to start xAI OAuth callback server on ${XAI_OAUTH_REDIRECT_PORT}: ${toErrorMessage(err)}`
1117
- );
1118
- }
1119
- try {
1120
- const state = generateState2();
1121
- const pkce = await generatePkcePair();
1122
- const nonce = crypto.randomUUID().replace(/-/g, "");
1123
- const discovery = await xaiOAuthDiscovery(fetchImpl);
1124
- const authUrl = buildXAIAuthorizeUrl({
1125
- authorizationEndpoint: discovery.authorization_endpoint,
1126
- redirectUri,
1127
- codeChallenge: pkce.challenge,
1128
- state,
1129
- nonce
1130
- });
1131
- output.log(
1132
- `Open the following URL in your browser to log in to xAI Grok (SuperGrok):
1133
- ${authUrl}
1134
-
1135
- Docs: ${XAI_OAUTH_DOCS_URL}`
1136
- );
1137
- if (deps.openBrowser) {
1138
- try {
1139
- await deps.openBrowser(authUrl);
1140
- } catch (err) {
1141
- error.error(
1142
- `Failed to open browser automatically: ${toErrorMessage(err)}`
1143
- );
1144
- }
1145
- }
1146
- const callback = await handle.waitForCode();
1147
- const token = await exchangeXAIToken(
1148
- fetchImpl,
1149
- callback.code,
1150
- redirectUri,
1151
- pkce.verifier
1152
- );
1153
- const now = (deps.now ?? Date.now)();
1154
- return tokenToCredential(token, now);
1155
- } finally {
1156
- await handle.close();
993
+ async function refreshAnthropicToken(credential, deps = {}) {
994
+ if (!credential.refreshToken) {
995
+ throw new Error("Claude credential has no refresh_token");
1157
996
  }
1158
- }
1159
- async function runXaiOAuthDeviceCode(deps = {}) {
1160
997
  const fetchImpl = deps.fetchImpl ?? fetch;
1161
- const output = deps.output ?? console;
1162
- const error = deps.error ?? console;
1163
- const sleep3 = deps.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
1164
- const now = deps.now ?? Date.now;
1165
- const discovery = await xaiOAuthDiscovery(fetchImpl, {
1166
- requireDeviceAuthorization: true
998
+ const response = await fetchImpl(ANTHROPIC_OAUTH_TOKEN_URL, {
999
+ method: "POST",
1000
+ headers: {
1001
+ "Content-Type": "application/json",
1002
+ "anthropic-beta": ANTHROPIC_OAUTH_BETA,
1003
+ "User-Agent": "nolo-cli userOAuthProvider"
1004
+ },
1005
+ body: JSON.stringify({
1006
+ grant_type: "refresh_token",
1007
+ client_id: ANTHROPIC_OAUTH_CLIENT_ID,
1008
+ refresh_token: credential.refreshToken
1009
+ }),
1010
+ signal: AbortSignal.timeout(3e4)
1167
1011
  });
1168
- const deviceAuthorizationEndpoint = discovery.device_authorization_endpoint;
1169
- if (!deviceAuthorizationEndpoint) {
1170
- throw new Error("xAI OIDC discovery missing device_authorization_endpoint");
1012
+ const payload = await response.json().catch(() => ({}));
1013
+ if (!response.ok) {
1014
+ const detail = typeof payload.error_description === "string" ? payload.error_description : typeof payload.error === "string" ? payload.error : `HTTP ${response.status}`;
1015
+ throw new Error(`Claude token refresh failed: ${detail}`);
1171
1016
  }
1172
- const start = await requestXaiDeviceCode(fetchImpl, deviceAuthorizationEndpoint);
1173
- const browserUrl = start.verificationUriComplete ?? start.verificationUri;
1174
- const expiresMinutes = Math.max(1, Math.round(start.expiresInMs / 6e4));
1175
- output.log("Authorize nolo-cli for xAI Grok (device code / headless):");
1176
- output.log(` URL: ${start.verificationUri}`);
1177
- if (start.verificationUriComplete) {
1178
- output.log(` Complete URL: ${start.verificationUriComplete}`);
1017
+ if (typeof payload.access_token !== "string" || !payload.access_token.trim()) {
1018
+ throw new Error("Claude token refresh response missing access_token");
1179
1019
  }
1180
- output.log(` Code: ${start.userCode}`);
1181
- output.log(
1182
- ` Code expires in ~${expiresMinutes} minute(s). Never share the code or tokens.`
1183
- );
1184
- if (deps.openBrowser) {
1185
- try {
1186
- const opened = await deps.openBrowser(browserUrl);
1187
- if (!opened) {
1188
- output.log("Could not open a browser automatically. Open the URL above.");
1189
- }
1190
- } catch (err) {
1191
- error.error(
1192
- `Failed to open browser automatically: ${toErrorMessage(err)}`
1193
- );
1194
- }
1195
- } else {
1196
- output.log("Open the URL above in a browser and enter the code to approve.");
1197
- }
1198
- const token = await pollXaiDeviceCodeToken({
1199
- fetchImpl,
1200
- tokenEndpoint: discovery.token_endpoint,
1201
- deviceCode: start.deviceCode,
1202
- expiresInMs: start.expiresInMs,
1203
- intervalMs: start.intervalMs,
1204
- sleep: sleep3,
1020
+ const now = deps.now?.() ?? Date.now();
1021
+ return normalizeAnthropicTokenPayload({
1022
+ payload,
1023
+ baseCredential: credential,
1205
1024
  now
1206
1025
  });
1207
- return tokenToCredential(token, now());
1208
- }
1209
- async function refreshXaiOAuthToken(credential) {
1210
- if (!credential.refreshToken) {
1211
- throw new Error("xAI credential has no refresh_token");
1212
- }
1213
- const fetchImpl = fetch;
1214
- const discovery = await xaiOAuthDiscovery(fetchImpl);
1215
- const tokenEndpoint = validateXAIEndpoint(discovery.token_endpoint, "token_endpoint");
1216
- const body = new URLSearchParams({
1217
- grant_type: "refresh_token",
1218
- client_id: XAI_OAUTH_CLIENT_ID,
1219
- refresh_token: credential.refreshToken
1220
- });
1221
- let response;
1222
- try {
1223
- response = await fetchImpl(tokenEndpoint, {
1224
- method: "POST",
1225
- headers: {
1226
- "Content-Type": "application/x-www-form-urlencoded",
1227
- Accept: "application/json"
1228
- },
1229
- body,
1230
- signal: AbortSignal.timeout(TOKEN_REQUEST_TIMEOUT_MS)
1231
- });
1232
- } catch (error) {
1233
- throw new Error(
1234
- `xAI token refresh failed: ${toErrorMessage(error)}`
1235
- );
1236
- }
1237
- const data = await readJsonBody(response, "xAI token refresh");
1238
- if (!response.ok) {
1239
- const detail = typeof data.error_description === "string" && data.error_description || typeof data.error === "string" && data.error || "";
1240
- throw new Error(
1241
- `xAI token refresh failed: ${response.status}${detail ? ` ${detail}` : ""}`
1242
- );
1243
- }
1244
- if (typeof data.access_token !== "string" || !data.access_token) {
1245
- throw new Error("xAI token refresh response missing access_token");
1246
- }
1247
- const expiresIn = asOptionalFiniteNumber(data.expires_in);
1248
- if (expiresIn === void 0) {
1249
- throw new Error("xAI token refresh response missing expires_in");
1250
- }
1251
- const newRefresh = typeof data.refresh_token === "string" && data.refresh_token ? data.refresh_token : credential.refreshToken;
1252
- const now = Date.now();
1253
- return {
1254
- ...credential,
1255
- accessToken: data.access_token,
1256
- refreshToken: newRefresh,
1257
- expiresAt: now + expiresIn * 1e3 - ACCESS_TOKEN_CLIENT_SKEW_MS2,
1258
- obtainedAt: now
1259
- };
1260
1026
  }
1027
+ var anthropicRefresh = refreshAnthropicToken;
1261
1028
 
1262
- // packages/cli/oauth/flows/cursor.ts
1029
+ // packages/agent-runtime/cursorOAuth.ts
1263
1030
  var CURSOR_LOGIN_URL = "https://cursor.com/loginDeepControl";
1264
1031
  var CURSOR_POLL_URL = "https://api2.cursor.sh/auth/poll";
1265
1032
  var CURSOR_REFRESH_URL = "https://api2.cursor.sh/auth/exchange_user_api_key";
1266
- var POLL_MAX_ATTEMPTS = 150;
1267
- var POLL_BASE_DELAY_MS = 1e3;
1268
- var POLL_MAX_DELAY_MS = 1e4;
1269
- var POLL_BACKOFF_MULTIPLIER = 1.2;
1270
- var POLL_MAX_CONSECUTIVE_ERRORS = 3;
1271
- var ACCESS_TOKEN_CLIENT_SKEW_MS3 = 5 * 60 * 1e3;
1033
+ var CURSOR_POLL_MAX_ATTEMPTS = 150;
1034
+ var CURSOR_POLL_BASE_DELAY_MS = 1e3;
1035
+ var CURSOR_POLL_MAX_DELAY_MS = 1e4;
1036
+ var CURSOR_POLL_BACKOFF_MULTIPLIER = 1.2;
1037
+ var CURSOR_POLL_MAX_CONSECUTIVE_ERRORS = 3;
1038
+ var CURSOR_ACCESS_TOKEN_CLIENT_SKEW_MS = 5 * 60 * 1e3;
1039
+ var CURSOR_TOKEN_REQUEST_TIMEOUT_MS = 3e4;
1272
1040
  function decodeJwtExp(token) {
1273
1041
  try {
1274
1042
  const parts = token.split(".");
1275
- if (parts.length !== 3) return void 0;
1276
- const payload = parts[1];
1277
- if (!payload) return void 0;
1278
- const decoded = JSON.parse(
1279
- Buffer.from(payload.replace(/-/g, "+").replace(/_/g, "/"), "base64").toString("utf8")
1280
- );
1281
- if (decoded && typeof decoded === "object" && typeof decoded.exp === "number") {
1282
- return decoded.exp * 1e3 - ACCESS_TOKEN_CLIENT_SKEW_MS3;
1043
+ if (parts.length < 2) return null;
1044
+ const payloadJson = Buffer.from(parts[1], "base64url").toString("utf-8");
1045
+ const payload = JSON.parse(payloadJson);
1046
+ if (typeof payload.exp === "number" && Number.isFinite(payload.exp)) {
1047
+ return payload.exp * 1e3;
1283
1048
  }
1049
+ return null;
1284
1050
  } catch {
1051
+ return null;
1285
1052
  }
1286
- return void 0;
1287
- }
1288
- function sleep2(ms, signal) {
1289
- if (signal) {
1290
- return new Promise((resolve, reject) => {
1291
- if (signal.aborted) {
1292
- reject(new Error("Aborted"));
1293
- return;
1294
- }
1295
- const timer = setTimeout(resolve, ms);
1296
- signal.addEventListener(
1297
- "abort",
1298
- () => {
1299
- clearTimeout(timer);
1300
- reject(new Error("Aborted"));
1301
- },
1302
- { once: true }
1303
- );
1304
- });
1305
- }
1306
- return new Promise((resolve) => setTimeout(resolve, ms));
1307
1053
  }
1308
- async function pollCursorAuth(uuid, verifier, deps = {}) {
1309
- const fetchImpl = deps.fetchImpl ?? fetch;
1310
- const sleepFn = deps.sleepFn ?? ((ms) => sleep2(ms));
1311
- let delay = POLL_BASE_DELAY_MS;
1312
- let consecutiveErrors = 0;
1313
- for (let attempt = 0; attempt < POLL_MAX_ATTEMPTS; attempt++) {
1314
- await sleepFn(delay);
1315
- let response;
1316
- try {
1317
- response = await fetchImpl(
1318
- `${CURSOR_POLL_URL}?uuid=${encodeURIComponent(uuid)}&verifier=${encodeURIComponent(verifier)}`
1319
- );
1320
- } catch {
1321
- consecutiveErrors++;
1322
- if (consecutiveErrors >= POLL_MAX_CONSECUTIVE_ERRORS) {
1323
- throw new Error("Too many consecutive network errors during Cursor auth polling");
1324
- }
1325
- continue;
1326
- }
1327
- if (response.status === 404) {
1328
- consecutiveErrors = 0;
1329
- delay = Math.min(delay * POLL_BACKOFF_MULTIPLIER, POLL_MAX_DELAY_MS);
1330
- continue;
1331
- }
1332
- if (response.ok) {
1333
- const data = await response.json();
1334
- if (typeof data.accessToken !== "string" || typeof data.refreshToken !== "string") {
1335
- throw new Error("Cursor poll response missing accessToken or refreshToken");
1336
- }
1337
- return { accessToken: data.accessToken, refreshToken: data.refreshToken };
1338
- }
1339
- consecutiveErrors++;
1340
- if (consecutiveErrors >= POLL_MAX_CONSECUTIVE_ERRORS) {
1341
- throw new Error(`Cursor auth poll failed: ${response.status}`);
1342
- }
1343
- }
1344
- throw new Error("Cursor authentication polling timed out");
1345
- }
1346
- async function runCursorOAuthLogin(deps = {}) {
1347
- const output = deps.output ?? console;
1348
- const fetchImpl = deps.fetchImpl ?? fetch;
1349
- const pkce = generatePkcePair();
1350
- const uuid = crypto.randomUUID();
1351
- const params = new URLSearchParams({
1352
- challenge: pkce.challenge,
1353
- uuid,
1354
- mode: "login",
1355
- redirectTarget: "cli"
1356
- });
1357
- const loginUrl = `${CURSOR_LOGIN_URL}?${params.toString()}`;
1358
- output.log(
1359
- `
1360
- Open this URL in your browser to authorize Cursor:
1361
- ${loginUrl}
1362
-
1363
- Waiting for browser authentication... (polling ${CURSOR_POLL_URL})`
1364
- );
1365
- const openBrowser = deps.openBrowser;
1366
- if (openBrowser) {
1367
- try {
1368
- await openBrowser(loginUrl);
1369
- } catch {
1370
- }
1054
+ function normalizeCursorTokenPayload(args) {
1055
+ const { payload, baseCredential, now } = args;
1056
+ if (typeof payload.accessToken !== "string" || !payload.accessToken.trim()) {
1057
+ throw new Error("Cursor token refresh response missing accessToken");
1371
1058
  }
1372
- const { accessToken, refreshToken } = await pollCursorAuth(uuid, pkce.verifier, {
1373
- fetchImpl,
1374
- ...deps.sleep ? { sleepFn: deps.sleep } : {}
1375
- });
1376
- const now = deps.now?.() ?? Date.now();
1377
- const expiresAt = decodeJwtExp(accessToken) ?? now + 3600 * 1e3 - ACCESS_TOKEN_CLIENT_SKEW_MS3;
1059
+ const accessToken = payload.accessToken.trim();
1060
+ const expiresAt = decodeJwtExp(accessToken) ?? now + 3600 * 1e3 - CURSOR_ACCESS_TOKEN_CLIENT_SKEW_MS;
1061
+ const newRefresh = typeof payload.refreshToken === "string" && payload.refreshToken.trim() ? payload.refreshToken.trim() : baseCredential?.refreshToken;
1378
1062
  return {
1063
+ ...baseCredential ?? {},
1379
1064
  provider: "cursor",
1380
1065
  accessToken,
1381
- refreshToken,
1066
+ ...newRefresh ? { refreshToken: newRefresh } : {},
1382
1067
  expiresAt,
1383
1068
  obtainedAt: now
1384
1069
  };
1385
1070
  }
1386
- var cursorRefresh = async (credential, deps = {}) => {
1071
+ async function refreshCursorToken(credential, deps = {}) {
1387
1072
  if (!credential.refreshToken) {
1388
1073
  throw new Error("Cursor credential has no refresh_token");
1389
1074
  }
1390
1075
  const fetchImpl = deps.fetchImpl ?? fetch;
1391
- const response = await fetchImpl(CURSOR_REFRESH_URL, {
1392
- method: "POST",
1393
- headers: {
1394
- Authorization: `Bearer ${credential.refreshToken}`,
1395
- "Content-Type": "application/json"
1396
- },
1397
- body: "{}",
1398
- signal: AbortSignal.timeout(3e4)
1399
- });
1076
+ let response;
1077
+ try {
1078
+ response = await fetchImpl(CURSOR_REFRESH_URL, {
1079
+ method: "POST",
1080
+ headers: {
1081
+ Authorization: `Bearer ${credential.refreshToken}`,
1082
+ "Content-Type": "application/json"
1083
+ },
1084
+ body: "{}",
1085
+ signal: AbortSignal.timeout(CURSOR_TOKEN_REQUEST_TIMEOUT_MS)
1086
+ });
1087
+ } catch (error) {
1088
+ throw new Error(
1089
+ `Cursor token refresh failed: ${toErrorMessage(error)}`
1090
+ );
1091
+ }
1400
1092
  if (!response.ok) {
1401
1093
  let detail = "";
1402
1094
  try {
@@ -1407,22 +1099,20 @@ var cursorRefresh = async (credential, deps = {}) => {
1407
1099
  `Cursor token refresh failed: ${response.status}${detail ? ` ${detail}` : ""}`
1408
1100
  );
1409
1101
  }
1410
- const data = await response.json();
1411
- if (typeof data.accessToken !== "string" || !data.accessToken) {
1412
- throw new Error("Cursor token refresh response missing accessToken");
1102
+ let data;
1103
+ try {
1104
+ data = await response.json();
1105
+ } catch {
1106
+ throw new Error("Cursor token refresh response is not valid JSON");
1413
1107
  }
1414
1108
  const now = deps.now?.() ?? Date.now();
1415
- const expiresAt = decodeJwtExp(data.accessToken) ?? now + 3600 * 1e3 - ACCESS_TOKEN_CLIENT_SKEW_MS3;
1416
- const newRefresh = typeof data.refreshToken === "string" && data.refreshToken ? data.refreshToken : credential.refreshToken;
1417
- return {
1418
- ...credential,
1419
- provider: "cursor",
1420
- accessToken: data.accessToken,
1421
- refreshToken: newRefresh,
1422
- expiresAt,
1423
- obtainedAt: now
1424
- };
1425
- };
1109
+ return normalizeCursorTokenPayload({
1110
+ payload: data,
1111
+ baseCredential: credential,
1112
+ now
1113
+ });
1114
+ }
1115
+ var cursorRefresh = refreshCursorToken;
1426
1116
 
1427
1117
  export {
1428
1118
  startCallbackServer,
@@ -1431,10 +1121,40 @@ export {
1431
1121
  refreshAntigravityOAuthToken,
1432
1122
  runOpenAiCodexDeviceCode,
1433
1123
  runOpenAiCodexBrowserPkce,
1434
- refreshOpenAiCodexToken,
1435
- runXaiOAuthLogin,
1436
- runXaiOAuthDeviceCode,
1437
- refreshXaiOAuthToken,
1438
- runCursorOAuthLogin,
1124
+ refreshOpenAiCodexToken2 as refreshOpenAiCodexToken,
1125
+ XAI_OAUTH_CLIENT_ID,
1126
+ XAI_OAUTH_SCOPE,
1127
+ XAI_OAUTH_REDIRECT_HOST,
1128
+ XAI_OAUTH_REDIRECT_PORT,
1129
+ XAI_OAUTH_REDIRECT_PATH,
1130
+ XAI_OAUTH_DOCS_URL,
1131
+ XAI_DEVICE_CODE_GRANT_TYPE,
1132
+ XAI_DEVICE_CODE_DEFAULT_INTERVAL_MS,
1133
+ XAI_DEVICE_CODE_MIN_INTERVAL_MS,
1134
+ XAI_DEVICE_CODE_SLOW_DOWN_INCREMENT_MS,
1135
+ XAI_DEVICE_CODE_DEFAULT_EXPIRES_MS,
1136
+ XAI_ACCESS_TOKEN_CLIENT_SKEW_MS,
1137
+ XAI_TOKEN_REQUEST_TIMEOUT_MS,
1138
+ validateXAIEndpoint,
1139
+ readJsonBody,
1140
+ xaiOAuthDiscovery,
1141
+ xaiRefresh,
1142
+ ANTHROPIC_OAUTH_CLIENT_ID,
1143
+ ANTHROPIC_OAUTH_AUTHORIZE_URL,
1144
+ ANTHROPIC_OAUTH_TOKEN_URL,
1145
+ ANTHROPIC_OAUTH_CALLBACK_PORT,
1146
+ ANTHROPIC_OAUTH_REDIRECT_URI,
1147
+ ANTHROPIC_OAUTH_SCOPES,
1148
+ normalizeAnthropicTokenPayload,
1149
+ anthropicRefresh,
1150
+ CURSOR_LOGIN_URL,
1151
+ CURSOR_POLL_URL,
1152
+ CURSOR_POLL_MAX_ATTEMPTS,
1153
+ CURSOR_POLL_BASE_DELAY_MS,
1154
+ CURSOR_POLL_MAX_DELAY_MS,
1155
+ CURSOR_POLL_BACKOFF_MULTIPLIER,
1156
+ CURSOR_POLL_MAX_CONSECUTIVE_ERRORS,
1157
+ CURSOR_ACCESS_TOKEN_CLIENT_SKEW_MS,
1158
+ decodeJwtExp,
1439
1159
  cursorRefresh
1440
1160
  };