import { loginOpenAICodex, type OAuthCredentials } from "@mariozechner/pi-ai/oauth"; import type { RuntimeEnv } from "../runtime.js"; import type { WizardPrompter } from "../wizard/prompts.js"; import { createVpsAwareOAuthHandlers } from "./provider-oauth-flow.js"; import { formatOpenAIOAuthTlsPreflightFix, runOpenAIOAuthTlsPreflight, } from "./provider-openai-codex-oauth-tls.js"; export async function loginOpenAICodexOAuth(params: { prompter: WizardPrompter; runtime: RuntimeEnv; isRemote: boolean; openUrl: (url: string) => Promise; localBrowserMessage?: string; }): Promise { const { prompter, runtime, isRemote, openUrl, localBrowserMessage } = params; const preflight = await runOpenAIOAuthTlsPreflight(); if (!preflight.ok && preflight.kind === "tls-cert") { const hint = formatOpenAIOAuthTlsPreflightFix(preflight); runtime.error(hint); await prompter.note(hint, "OAuth prerequisites"); throw new Error(preflight.message); } await 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.", ].join("\n") : [ "Browser will open for OpenAI authentication.", "If the callback doesn't auto-complete, paste the redirect URL.", "OpenAI OAuth uses localhost:1455 for the callback.", ].join("\n"), "OpenAI Codex OAuth", ); const spin = prompter.progress("Starting OAuth flow…"); try { const { onAuth: baseOnAuth, onPrompt } = createVpsAwareOAuthHandlers({ isRemote, prompter, runtime, spin, openUrl, localBrowserMessage: localBrowserMessage ?? "Complete sign-in in browser…", }); const creds = await loginOpenAICodex({ onAuth: baseOnAuth, onPrompt, onProgress: (msg: string) => spin.update(msg), }); spin.stop("OpenAI OAuth complete"); return creds ?? null; } catch (err) { spin.stop("OpenAI OAuth failed"); runtime.error(String(err)); await prompter.note("Trouble with OAuth? See https://docs.openclaw.ai/start/faq", "OAuth help"); throw err; } }