()
| 275 | type: "oauth", |
| 276 | label: "Login with DigitalOcean", |
| 277 | async authorize() { |
| 278 | await startOAuthServer() |
| 279 | const state = generateState() |
| 280 | const callbackPromise = waitForOAuthCallback(state) |
| 281 | const url = buildAuthorizeUrl(state) |
| 282 | await open(url).catch(() => undefined) |
| 283 | return { |
| 284 | url, |
| 285 | instructions: |
| 286 | "Sign in to DigitalOcean in your browser. OpenCode will use your DigitalOcean API token directly for inference and load your Inference Routers. Re-run /connect to refresh routers later.", |
| 287 | method: "auto" as const, |
| 288 | async callback() { |
| 289 | try { |
| 290 | const tokens = await callbackPromise |
| 291 | const routerResult = await listRouters(tokens.access_token) |
| 292 | const routers = routerResult.ok ? routerResult.routers : [] |
| 293 | if (!routerResult.ok) { |
| 294 | } |
| 295 | return { |
| 296 | type: "success" as const, |
| 297 | provider: "digitalocean", |
| 298 | key: tokens.access_token, |
| 299 | metadata: { |
| 300 | oauth_access: tokens.access_token, |
| 301 | oauth_expires: String(Date.now() + tokens.expires_in * 1000), |
| 302 | oauth_scopes: OAUTH_SCOPES, |
| 303 | routers: JSON.stringify( |
| 304 | routers.map((r) => ({ name: r.name, uuid: r.uuid, description: r.description })), |
| 305 | ), |
| 306 | routers_fetched_at: String(Date.now()), |
| 307 | }, |
| 308 | } |
| 309 | } catch (err) { |
| 310 | return { type: "failed" as const } |
| 311 | } finally { |
| 312 | stopOAuthServer() |
| 313 | } |
| 314 | }, |
| 315 | } |
| 316 | }, |
| 317 | }, |
| 318 | { |
| 319 | type: "api", |
no test coverage detected