From 917d18203ad791b8929b489753a422c714bfe4f4 Mon Sep 17 00:00:00 2001 From: Hona <10430890+Hona@users.noreply.github.com> Date: Mon, 3 Aug 2026 01:01:13 +0000 Subject: [PATCH] fix(opencode): refresh API key after auth changes --- packages/opencode/src/plugin/openai/codex.ts | 6 ++++ packages/opencode/test/plugin/codex.test.ts | 36 ++++++++++++++++++-- 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/packages/opencode/src/plugin/openai/codex.ts b/packages/opencode/src/plugin/openai/codex.ts index 1490755a93..99b8b40028 100644 --- a/packages/opencode/src/plugin/openai/codex.ts +++ b/packages/opencode/src/plugin/openai/codex.ts @@ -341,6 +341,12 @@ export async function CodexAuthPlugin(input: PluginInput, options: CodexAuthPlug apiKey: OAUTH_DUMMY_KEY, async fetch(requestInput: RequestInfo | URL, init?: RequestInit) { const currentAuth = await getAuth() + if (currentAuth?.type === "api") { + const headers = new Headers(init?.headers) + headers.set("authorization", `Bearer ${currentAuth.key}`) + const requestInit = { ...init, headers } + return websocketFetch ? websocketFetch(requestInput, requestInit) : fetch(requestInput, requestInit) + } if (currentAuth?.type !== "oauth") return websocketFetch ? websocketFetch(requestInput, init) : fetch(requestInput, init) diff --git a/packages/opencode/test/plugin/codex.test.ts b/packages/opencode/test/plugin/codex.test.ts index 2ce9b4e17d..8edc524607 100644 --- a/packages/opencode/test/plugin/codex.test.ts +++ b/packages/opencode/test/plugin/codex.test.ts @@ -7,6 +7,7 @@ import { renderOAuthError, type IdTokenClaims, } from "../../src/plugin/openai/codex" +import { OAUTH_DUMMY_KEY } from "../../src/auth" function createTestJwt(payload: object): string { const header = Buffer.from(JSON.stringify({ alg: "none" })).toString("base64url") @@ -174,10 +175,41 @@ describe("plugin.codex", () => { auth = undefined const response = await loaded.fetch!(server.url, { - headers: { authorization: "Bearer current" }, + headers: { authorization: `Bearer ${OAUTH_DUMMY_KEY}` }, }) - expect(await response.json()).toEqual({ authorization: "Bearer current" }) + expect(await response.json()).toEqual({ authorization: `Bearer ${OAUTH_DUMMY_KEY}` }) + }) + + test("uses current API key when OAuth auth is replaced after loading", async () => { + let auth: + | { + type: "oauth" + refresh: string + access: string + expires: number + } + | { type: "api"; key: string } = { + type: "oauth", + refresh: "refresh", + access: "access", + expires: Date.now() + 60_000, + } + using server = Bun.serve({ + port: 0, + fetch(request) { + return Response.json({ authorization: request.headers.get("authorization") }) + }, + }) + const hooks = await CodexAuthPlugin({} as never) + const loaded = await hooks.auth!.loader!(async () => auth as never, {} as never) + auth = { type: "api", key: "sk-current" } + + const response = await loaded.fetch!(server.url, { + headers: { authorization: `Bearer ${OAUTH_DUMMY_KEY}` }, + }) + + expect(await response.json()).toEqual({ authorization: "Bearer sk-current" }) }) test("filters unsupported modes and uses Codex context limits for OAuth GPT models", async () => {