From 12ae39a1b825c226bcfc725749ce40dd5480f9fd Mon Sep 17 00:00:00 2001 From: bft-codebot Date: Fri, 1 May 2026 20:37:05 +0000 Subject: [PATCH] sync(bfmono): fix(workloop): preserve Codex auth refresh failures (+19 more) (bfmono@76e21a05f) This PR is an automated gambitmono sync of bfmono Gambit packages. - Source: `packages/gambit/` - Core: `packages/gambit/packages/gambit-core/` - bfmono rev: 76e21a05f Changes: - 76e21a05f fix(workloop): preserve Codex auth refresh failures - 224cfdca6 fix(gambit): fall back without host service token - 668e393de feat(gambit): add browser introspection live commands - 4d8a6ad7b feat(workloop): bridge runtime Codex refresh to host services - 81ac0db58 feat(gambit): add live browser pointer refs - 62e132a24 chore(browser): move runtime out of Gambit - e6c80f928 test(gambit): remove legacy chat suites - 49c9b67e3 chore(gambit): remove dead chat provider adapters - 8b4af5051 fix(gambit): preserve responses continuation context - d9127ae36 feat(gambit): expose structured responses runtime - 522e10d5e feat(gambit): make provider execution responses-only - 13bfdfe34 fix(gambit): pass codex runtime tools - 477a6e8fa fix(gambit): preserve structured text spacing - c31a35389 fix(gambit): read workloop codex auth bundle env - ca19ea448 chore(workloop): rename desktop app from bfdesktop - 0715225a7 fix(gambit): parse mock Codex string ids portably - e4fad187d fix(browser-runtime): use repo-relative automation imports - 549d9dafa fix(browser-runtime): use explicit Deno exports - 46d961d01 fix(browser-runtime): detect stale live sessions - bd2b9d937 fix(bfdesktop): route Chief browser MCP tool calls Do not edit this repo directly; make changes in bfmono and re-run the sync. --- src/providers/codex.ts | 57 ++++++++++++++++++++++---- src/providers/codex_app_server.test.ts | 35 ++++++++++++++++ 2 files changed, 83 insertions(+), 9 deletions(-) create mode 100644 src/providers/codex_app_server.test.ts diff --git a/src/providers/codex.ts b/src/providers/codex.ts index 75cb8ff4..1ed5e30c 100644 --- a/src/providers/codex.ts +++ b/src/providers/codex.ts @@ -676,14 +676,21 @@ async function appServerRequestResult(input: { } if (input.method === "account/chatgptAuthTokens/refresh") { const bridge = requireCodexHostAuthBridge(); - const refreshed = await bridge.refreshAuthTokens({ - previousAccountId: typeof input.params.previousAccountId === "string" - ? input.params.previousAccountId - : null, - reason: typeof input.params.reason === "string" && input.params.reason - ? input.params.reason - : "account/chatgptAuthTokens/refresh", - }); + let refreshed: CodexChatgptAuthTokens; + try { + refreshed = await bridge.refreshAuthTokens({ + previousAccountId: typeof input.params.previousAccountId === "string" + ? input.params.previousAccountId + : null, + reason: typeof input.params.reason === "string" && input.params.reason + ? input.params.reason + : "account/chatgptAuthTokens/refresh", + }); + } catch (error) { + return { + error: appServerHostRequestFailure(error), + }; + } return { result: { accessToken: refreshed.accessToken, @@ -701,6 +708,18 @@ async function appServerRequestResult(input: { }; } +function appServerHostRequestFailure(error: unknown): { + code: number; + message: string; +} { + return { + code: -32000, + message: error instanceof Error && error.message + ? error.message + : String(error), + }; +} + async function bootstrapCodexExternalAuth(input: { request: ( method: string, @@ -1257,7 +1276,14 @@ async function defaultAppServerTurnRunner( method, params: safeJsonObjectFromRecord(params), }); - const response = await appServerRequestResult({ method, params }); + let response: Awaited>; + try { + response = await appServerRequestResult({ method, params }); + } catch (error) { + response = { + error: appServerHostRequestFailure(error), + }; + } logCodexAppServerDebug("message:host_response", { method, requestId, @@ -2561,6 +2587,19 @@ export function safeJsonForTest(text: string): Record { return safeJsonObject(text); } +export async function appServerRequestResultForTest(input: { + method: string; + params: Record; +}): Promise<{ + result?: Record; + error?: { + code: number; + message: string; + }; +}> { + return await appServerRequestResult(input); +} + export function sanitizeCodexSpawnArgsForTest( args: Array, ): Array { diff --git a/src/providers/codex_app_server.test.ts b/src/providers/codex_app_server.test.ts new file mode 100644 index 00000000..ee3eadcf --- /dev/null +++ b/src/providers/codex_app_server.test.ts @@ -0,0 +1,35 @@ +import { assertEquals } from "@std/assert"; +import { + appServerRequestResultForTest, + setCodexHostAuthBridgeForTests, +} from "./codex.ts"; + +Deno.test("codex app-server refresh host failures are returned as RPC errors", async () => { + setCodexHostAuthBridgeForTests({ + readAuthTokens: () => { + throw new Error("not expected"); + }, + refreshAuthTokens: () => { + throw new SyntaxError("Unexpected end of JSON input"); + }, + }); + + try { + const response = await appServerRequestResultForTest({ + method: "account/chatgptAuthTokens/refresh", + params: { + previousAccountId: "acct-test", + reason: "account/chatgptAuthTokens/refresh", + }, + }); + + assertEquals(response, { + error: { + code: -32000, + message: "Unexpected end of JSON input", + }, + }); + } finally { + setCodexHostAuthBridgeForTests(null); + } +});