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

Function pollDeviceCodeToken

packages/opencode/src/plugin/xai.ts:237–286  ·  view source on GitHub ↗
(
  device: DeviceCodeResponse,
  options: XaiAuthPluginOptions & { sleep?: (ms: number) => Promise<void>; now?: () => number } = {},
)

Source from the content-addressed store, hash-verified

235}
236
237export async function pollDeviceCodeToken(
238 device: DeviceCodeResponse,
239 options: XaiAuthPluginOptions & { sleep?: (ms: number) => Promise<void>; now?: () => number } = {},
240): Promise<TokenResponse> {
241 const sleep = options.sleep ?? defaultSleep
242 const now = options.now ?? (() => Date.now())
243 const expiresInMs = positiveSecondsToMs(device.expires_in, DEVICE_CODE_DEFAULT_EXPIRES_MS)
244 const deadline = now() + expiresInMs
245 let intervalMs = Math.max(
246 positiveSecondsToMs(device.interval, DEVICE_CODE_DEFAULT_INTERVAL_MS),
247 DEVICE_CODE_MIN_INTERVAL_MS,
248 )
249
250 while (now() < deadline) {
251 const response = await fetch(options.tokenUrl ?? TOKEN_URL, {
252 method: "POST",
253 headers: authHeaders(),
254 body: new URLSearchParams({
255 grant_type: DEVICE_CODE_GRANT_TYPE,
256 client_id: CLIENT_ID,
257 device_code: device.device_code,
258 }).toString(),
259 })
260 if (response.ok) return (await response.json()) as TokenResponse
261
262 const body = (await response.json().catch(() => ({}))) as DeviceTokenErrorBody
263 const remaining = Math.max(0, deadline - now())
264 // RFC 8628 §3.5: authorization_pending = keep polling at the same
265 // interval; slow_down = bump the interval by ≥5s and keep polling.
266 // Anything else is terminal.
267 if (body.error === "authorization_pending") {
268 await sleep(Math.min(intervalMs + OAUTH_POLLING_SAFETY_MARGIN_MS, remaining))
269 continue
270 }
271 if (body.error === "slow_down") {
272 intervalMs += DEVICE_CODE_SLOW_DOWN_INCREMENT_MS
273 await sleep(Math.min(intervalMs + OAUTH_POLLING_SAFETY_MARGIN_MS, remaining))
274 continue
275 }
276 if (body.error === "access_denied" || body.error === "authorization_denied") {
277 throw new Error("xAI device authorization was denied")
278 }
279 if (body.error === "expired_token") {
280 throw new Error("xAI device code expired - please re-run login")
281 }
282 const detail = body.error_description ?? body.error ?? ""
283 throw new Error(`xAI device token exchange failed (${response.status})${detail ? `: ${detail}` : ""}`)
284 }
285 throw new Error("xAI device authorization timed out")
286}
287
288// CORS allowlist for the loopback callback. The redirect_uri itself is
289// already bound to 127.0.0.1 and gated by PKCE+state, so we only accept

Callers 2

xai.test.tsFile · 0.90
XaiAuthPluginFunction · 0.85

Calls 5

positiveSecondsToMsFunction · 0.85
fetchFunction · 0.70
authHeadersFunction · 0.70
jsonMethod · 0.65
sleepFunction · 0.50

Tested by

no test coverage detected