({ client }: PluginInput)
| 74 | * ``` |
| 75 | */ |
| 76 | export const ArcticCodexAuth: Plugin = async ({ client }: PluginInput) => { |
| 77 | return { |
| 78 | auth: { |
| 79 | provider: PROVIDER_ID, |
| 80 | /** |
| 81 | * Loader function that configures OAuth authentication and request handling |
| 82 | * |
| 83 | * This function: |
| 84 | * 1. Validates OAuth authentication |
| 85 | * 2. Extracts ChatGPT account ID from access token |
| 86 | * 3. Loads user configuration from opencode.json |
| 87 | * 4. Fetches Codex system instructions from GitHub (cached) |
| 88 | * 5. Returns SDK configuration with custom fetch implementation |
| 89 | * |
| 90 | * @param getAuth - Function to retrieve current auth state |
| 91 | * @param provider - Provider configuration from opencode.json |
| 92 | * @returns SDK configuration object or empty object for non-OAuth auth |
| 93 | */ |
| 94 | async loader(getAuth: () => Promise<Auth.Info>, provider: unknown) { |
| 95 | const auth = await getAuth(); |
| 96 | |
| 97 | // Support both standard oauth and internal codex auth types |
| 98 | if (auth.type !== "oauth" && auth.type !== "codex") { |
| 99 | return {}; |
| 100 | } |
| 101 | |
| 102 | // Normalize token access (codex uses accessToken, oauth uses access) |
| 103 | const accessToken = (auth as any).accessToken ?? (auth as any).access; |
| 104 | |
| 105 | // Extract ChatGPT account ID from JWT access token |
| 106 | const decoded = decodeJWT(accessToken); |
| 107 | const accountId = decoded?.[JWT_CLAIM_PATH]?.chatgpt_account_id; |
| 108 | |
| 109 | if (!accountId) { |
| 110 | console.error(`[${PLUGIN_NAME}] ${ERROR_MESSAGES.NO_ACCOUNT_ID}`); |
| 111 | return {}; |
| 112 | } |
| 113 | // Extract user configuration (global + per-model options) |
| 114 | const providerConfig = provider as |
| 115 | | { options?: Record<string, unknown>; models?: UserConfig["models"] } |
| 116 | | undefined; |
| 117 | const userConfig: UserConfig = { |
| 118 | global: providerConfig?.options || {}, |
| 119 | models: providerConfig?.models || {}, |
| 120 | }; |
| 121 | |
| 122 | // Load plugin configuration and determine CODEX_MODE |
| 123 | // Priority: CODEX_MODE env var > config file > default (true) |
| 124 | const pluginConfig = loadPluginConfig(); |
| 125 | const codexMode = getCodexMode(pluginConfig); |
| 126 | |
| 127 | // Return SDK configuration |
| 128 | return { |
| 129 | apiKey: DUMMY_API_KEY, |
| 130 | baseURL: CODEX_BASE_URL, |
| 131 | /** |
| 132 | * Custom fetch implementation for Codex API |
| 133 | * |
no test coverage detected