| import type { ApplyAuthChoiceParams, ApplyAuthChoiceResult } from "./auth-choice.apply.js"; |
| import { loginChutes } from "./chutes-oauth.js"; |
| import { isRemoteEnvironment } from "./oauth-env.js"; |
| import { createVpsAwareOAuthHandlers } from "./oauth-flow.js"; |
| import { applyAuthProfileConfig, writeOAuthCredentials } from "./onboard-auth.js"; |
| import { openUrl } from "./onboard-helpers.js"; |
|
|
| export async function applyAuthChoiceOAuth( |
| params: ApplyAuthChoiceParams, |
| ): Promise<ApplyAuthChoiceResult | null> { |
| if (params.authChoice === "chutes") { |
| let nextConfig = params.config; |
| const isRemote = isRemoteEnvironment(); |
| const redirectUri = |
| process.env.CHUTES_OAUTH_REDIRECT_URI?.trim() || "http://127.0.0.1:1456/oauth-callback"; |
| const scopes = process.env.CHUTES_OAUTH_SCOPES?.trim() || "openid profile chutes:invoke"; |
| const clientId = |
| process.env.CHUTES_CLIENT_ID?.trim() || |
| String( |
| await params.prompter.text({ |
| message: "Enter Chutes OAuth client id", |
| placeholder: "cid_xxx", |
| validate: (value) => (value?.trim() ? undefined : "Required"), |
| }), |
| ).trim(); |
| const clientSecret = process.env.CHUTES_CLIENT_SECRET?.trim() || undefined; |
|
|
| await params.prompter.note( |
| isRemote |
| ? [ |
| "You are running in a remote/VPS environment.", |
| "A URL will be shown for you to open in your LOCAL browser.", |
| "After signing in, paste the redirect URL back here.", |
| "", |
| `Redirect URI: ${redirectUri}`, |
| ].join("\n") |
| : [ |
| "Browser will open for Chutes authentication.", |
| "If the callback doesn't auto-complete, paste the redirect URL.", |
| "", |
| `Redirect URI: ${redirectUri}`, |
| ].join("\n"), |
| "Chutes OAuth", |
| ); |
|
|
| const spin = params.prompter.progress("Starting OAuth flow…"); |
| try { |
| const { onAuth, onPrompt } = createVpsAwareOAuthHandlers({ |
| isRemote, |
| prompter: params.prompter, |
| runtime: params.runtime, |
| spin, |
| openUrl, |
| localBrowserMessage: "Complete sign-in in browser…", |
| }); |
|
|
| const creds = await loginChutes({ |
| app: { |
| clientId, |
| clientSecret, |
| redirectUri, |
| scopes: scopes.split(/\s+/).filter(Boolean), |
| }, |
| manual: isRemote, |
| onAuth, |
| onPrompt, |
| onProgress: (msg) => spin.update(msg), |
| }); |
|
|
| spin.stop("Chutes OAuth complete"); |
| const profileId = await writeOAuthCredentials("chutes", creds, params.agentDir); |
| nextConfig = applyAuthProfileConfig(nextConfig, { |
| profileId, |
| provider: "chutes", |
| mode: "oauth", |
| }); |
| } catch (err) { |
| spin.stop("Chutes OAuth failed"); |
| params.runtime.error(String(err)); |
| await params.prompter.note( |
| [ |
| "Trouble with OAuth?", |
| "Verify CHUTES_CLIENT_ID (and CHUTES_CLIENT_SECRET if required).", |
| `Verify the OAuth app redirect URI includes: ${redirectUri}`, |
| "Chutes docs: https://chutes.ai/docs/sign-in-with-chutes/overview", |
| ].join("\n"), |
| "OAuth help", |
| ); |
| } |
| return { config: nextConfig }; |
| } |
|
|
| return null; |
| } |
|
|