()
| 475 | instructions: `Enter code: ${deviceData.user_code}`, |
| 476 | method: "auto" as const, |
| 477 | async callback() { |
| 478 | while (true) { |
| 479 | const response = await fetch(`${ISSUER}/api/accounts/deviceauth/token`, { |
| 480 | method: "POST", |
| 481 | headers: { |
| 482 | "Content-Type": "application/json", |
| 483 | "User-Agent": `opencode/${InstallationVersion}`, |
| 484 | }, |
| 485 | body: JSON.stringify({ |
| 486 | device_auth_id: deviceData.device_auth_id, |
| 487 | user_code: deviceData.user_code, |
| 488 | }), |
| 489 | }) |
| 490 | |
| 491 | if (response.ok) { |
| 492 | const data = (await response.json()) as { |
| 493 | authorization_code: string |
| 494 | code_verifier: string |
| 495 | } |
| 496 | |
| 497 | const tokenResponse = await fetch(`${ISSUER}/oauth/token`, { |
| 498 | method: "POST", |
| 499 | headers: { "Content-Type": "application/x-www-form-urlencoded" }, |
| 500 | body: new URLSearchParams({ |
| 501 | grant_type: "authorization_code", |
| 502 | code: data.authorization_code, |
| 503 | redirect_uri: `${ISSUER}/deviceauth/callback`, |
| 504 | client_id: CLIENT_ID, |
| 505 | code_verifier: data.code_verifier, |
| 506 | }).toString(), |
| 507 | }) |
| 508 | |
| 509 | if (!tokenResponse.ok) { |
| 510 | throw new Error(`Token exchange failed: ${tokenResponse.status}`) |
| 511 | } |
| 512 | |
| 513 | const tokens: TokenResponse = await tokenResponse.json() |
| 514 | |
| 515 | return { |
| 516 | type: "success" as const, |
| 517 | refresh: tokens.refresh_token, |
| 518 | access: tokens.access_token, |
| 519 | expires: Date.now() + (tokens.expires_in ?? 3600) * 1000, |
| 520 | accountId: extractAccountId(tokens), |
| 521 | } |
| 522 | } |
| 523 | |
| 524 | if (response.status !== 403 && response.status !== 404) { |
| 525 | return { type: "failed" as const } |
| 526 | } |
| 527 | |
| 528 | await sleep(interval + OAUTH_POLLING_SAFETY_MARGIN_MS) |
| 529 | } |
| 530 | }, |
| 531 | } |
| 532 | }, |
| 533 | }, |
nothing calls this directly
no test coverage detected