Compare commits

...

2 Commits

Author SHA1 Message Date
Hona 917d18203a fix(opencode): refresh API key after auth changes 2026-08-03 01:01:13 +00:00
Hona 3a0e9efe7d fix(opencode): handle removed OpenAI OAuth auth 2026-08-03 00:53:52 +00:00
2 changed files with 73 additions and 4 deletions
+10 -4
View File
@@ -340,6 +340,16 @@ export async function CodexAuthPlugin(input: PluginInput, options: CodexAuthPlug
return {
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)
if (init?.headers) {
if (init.headers instanceof Headers) {
init.headers.delete("authorization")
@@ -352,10 +362,6 @@ export async function CodexAuthPlugin(input: PluginInput, options: CodexAuthPlug
}
}
const currentAuth = await getAuth()
if (currentAuth.type !== "oauth")
return websocketFetch ? websocketFetch(requestInput, init) : fetch(requestInput, init)
const authWithAccount = currentAuth as typeof currentAuth & { accountId?: string }
if (!currentAuth.access || currentAuth.expires < Date.now()) {
@@ -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")
@@ -149,6 +150,68 @@ describe("plugin.codex", () => {
await enabled.dispose?.()
})
test("passes requests through when OAuth auth is removed after loading", async () => {
let auth:
| {
type: "oauth"
refresh: string
access: string
expires: number
}
| undefined = {
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 = undefined
const response = await loaded.fetch!(server.url, {
headers: { authorization: `Bearer ${OAUTH_DUMMY_KEY}` },
})
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 () => {
const hooks = await CodexAuthPlugin({} as never)
const limit = { context: 1_050_000, input: 922_000, output: 128_000 }