MCPcopy Index your code
hub / github.com/anomalyco/opencode / XaiAuthPlugin

Function XaiAuthPlugin

packages/opencode/src/plugin/xai.ts:458–626  ·  view source on GitHub ↗
(input: PluginInput, options: XaiAuthPluginOptions = {})

Source from the content-addressed store, hash-verified

456}
457
458export async function XaiAuthPlugin(input: PluginInput, options: XaiAuthPluginOptions = {}): Promise<Hooks> {
459 return {
460 auth: {
461 provider: "xai",
462 async loader(getAuth) {
463 const auth = await getAuth()
464 if (auth.type !== "oauth") return {}
465
466 // Single-flight refresh: collapse concurrent fetches from this loaded
467 // provider onto one HTTP call so we don't replay a rotating refresh_token.
468 let refreshPromise: Promise<RefreshResult> | undefined
469
470 return {
471 // Dummy bearer keeps the AI SDK from bailing on "missing apiKey"; the
472 // real OAuth token is injected by the fetch override below.
473 // We intentionally do NOT set baseURL — @ai-sdk/xai already defaults
474 // to https://api.x.ai/v1 and overriding here would silently route
475 // around a user-configured gateway.
476 apiKey: OAUTH_DUMMY_KEY,
477 async fetch(requestInput: RequestInfo | URL, init?: RequestInit) {
478 let currentAuth = await getAuth()
479 // Auth can flip from oauth to api mid-session (user re-runs
480 // /connect with a pasted key). When that happens, pass the
481 // request through untouched so the AI SDK's own apiKey-based
482 // Authorization header reaches xAI unmodified.
483 if (currentAuth.type !== "oauth") return fetch(requestInput, init)
484
485 // Refresh either when the stored expires timestamp is within the
486 // skew window, or — for JWT access tokens — when the JWT exp
487 // claim itself is. The stored expires field is best-effort
488 // (xAI doesn't always return expires_in) so the JWT check is the
489 // load-bearing one for tokens that lack a fresh stored deadline.
490 const expiresSoon =
491 !currentAuth.expires ||
492 currentAuth.expires - Date.now() <= ACCESS_TOKEN_REFRESH_SKEW_MS ||
493 accessTokenIsExpiring(currentAuth.access)
494 if (expiresSoon) {
495 if (!refreshPromise) {
496 const refreshToken = currentAuth.refresh
497 refreshPromise = refreshAccessToken(refreshToken, options)
498 .then(async (tokens) => {
499 const refreshedExpires = Date.now() + (tokens.expires_in ?? 3600) * 1000
500 const refreshedRefresh = tokens.refresh_token || refreshToken
501 // Persist the rotated pair as best-effort. xAI has already consumed the
502 // old refresh_token by the time we get here; an auth.set failure leaves
503 // the on-disk state stale but the in-memory result is still valid for
504 // this turn. The next live refresh against the stale disk state will
505 // 4xx and force re-login — a known cross-process limitation.
506 await input.client.auth
507 .set({
508 path: { id: "xai" },
509 body: {
510 type: "oauth",
511 access: tokens.access_token,
512 refresh: refreshedRefresh,
513 expires: refreshedExpires,
514 },
515 })

Callers 1

xai.test.tsFile · 0.90

Calls 8

requestDeviceCodeFunction · 0.85
pollDeviceCodeTokenFunction · 0.85
startOAuthServerFunction · 0.70
generatePKCEFunction · 0.70
generateStateFunction · 0.70
buildAuthorizeUrlFunction · 0.70
waitForOAuthCallbackFunction · 0.70
stopOAuthServerFunction · 0.70

Tested by

no test coverage detected