mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 18:20:44 +00:00
Fix Codex auth handoff for the app-server harness (#69990)
* Codex: fix auth bridge token shape * Codex: preserve selected auth tokens * Codex: prefer selected profile id token * Codex: honor inherited Codex home --------- Co-authored-by: Val Alexander <68980965+BunsDev@users.noreply.github.com>
This commit is contained in:
@@ -89,6 +89,7 @@ describe("bridgeCodexAppServerStartOptions", () => {
|
||||
refresh_token: "refresh-token",
|
||||
account_id: "acct-123",
|
||||
},
|
||||
last_refresh: expect.any(String),
|
||||
});
|
||||
if (process.platform !== "win32") {
|
||||
const authStat = await fs.stat(path.join(result.env?.CODEX_HOME ?? "", "auth.json"));
|
||||
@@ -96,6 +97,171 @@ describe("bridgeCodexAppServerStartOptions", () => {
|
||||
}
|
||||
});
|
||||
|
||||
it("hydrates Codex-only auth fields from a matching Codex CLI auth file", async () => {
|
||||
const sourceCodexHome = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-codex-source-home-"));
|
||||
tempDirs.push(sourceCodexHome);
|
||||
await fs.writeFile(
|
||||
path.join(sourceCodexHome, "auth.json"),
|
||||
`${JSON.stringify(
|
||||
{
|
||||
auth_mode: "chatgpt",
|
||||
tokens: {
|
||||
id_token: "source-id-token",
|
||||
access_token: "access-token",
|
||||
refresh_token: "refresh-token",
|
||||
account_id: "acct-123",
|
||||
},
|
||||
last_refresh: "2026-04-22T00:00:00.000Z",
|
||||
},
|
||||
null,
|
||||
2,
|
||||
)}\n`,
|
||||
);
|
||||
const agentDir = await createAgentDirWithDefaultProfile({
|
||||
accountId: "acct-123",
|
||||
});
|
||||
|
||||
const result = await bridgeCodexAppServerStartOptions({
|
||||
startOptions: {
|
||||
transport: "stdio",
|
||||
command: "codex",
|
||||
args: ["app-server"],
|
||||
headers: {},
|
||||
env: { CODEX_HOME: sourceCodexHome },
|
||||
},
|
||||
agentDir,
|
||||
});
|
||||
|
||||
expect(result.env?.CODEX_HOME).not.toBe(sourceCodexHome);
|
||||
const authFile = JSON.parse(
|
||||
await fs.readFile(path.join(result.env?.CODEX_HOME ?? "", "auth.json"), "utf8"),
|
||||
);
|
||||
expect(authFile).toEqual({
|
||||
auth_mode: "chatgpt",
|
||||
tokens: {
|
||||
id_token: "source-id-token",
|
||||
access_token: "access-token",
|
||||
refresh_token: "refresh-token",
|
||||
account_id: "acct-123",
|
||||
},
|
||||
last_refresh: "2026-04-22T00:00:00.000Z",
|
||||
});
|
||||
});
|
||||
|
||||
it("keeps the selected profile tokens when hydrating from a same-account Codex CLI auth file", async () => {
|
||||
const sourceCodexHome = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-codex-source-home-"));
|
||||
tempDirs.push(sourceCodexHome);
|
||||
await fs.writeFile(
|
||||
path.join(sourceCodexHome, "auth.json"),
|
||||
`${JSON.stringify(
|
||||
{
|
||||
auth_mode: "chatgpt",
|
||||
tokens: {
|
||||
id_token: "source-id-token",
|
||||
access_token: "stale-source-access-token",
|
||||
refresh_token: "stale-source-refresh-token",
|
||||
account_id: "acct-123",
|
||||
},
|
||||
last_refresh: "2026-04-22T00:00:00.000Z",
|
||||
},
|
||||
null,
|
||||
2,
|
||||
)}\n`,
|
||||
);
|
||||
const agentDir = await createAgentDirWithDefaultProfile({
|
||||
access: "selected-profile-access-token",
|
||||
refresh: "selected-profile-refresh-token",
|
||||
accountId: "acct-123",
|
||||
idToken: "selected-profile-id-token",
|
||||
});
|
||||
|
||||
const result = await bridgeCodexAppServerStartOptions({
|
||||
startOptions: {
|
||||
transport: "stdio",
|
||||
command: "codex",
|
||||
args: ["app-server"],
|
||||
headers: {},
|
||||
env: { CODEX_HOME: sourceCodexHome },
|
||||
},
|
||||
agentDir,
|
||||
});
|
||||
|
||||
expect(result.env?.CODEX_HOME).not.toBe(sourceCodexHome);
|
||||
const authFile = JSON.parse(
|
||||
await fs.readFile(path.join(result.env?.CODEX_HOME ?? "", "auth.json"), "utf8"),
|
||||
);
|
||||
expect(authFile).toEqual({
|
||||
auth_mode: "chatgpt",
|
||||
tokens: {
|
||||
id_token: "selected-profile-id-token",
|
||||
access_token: "selected-profile-access-token",
|
||||
refresh_token: "selected-profile-refresh-token",
|
||||
account_id: "acct-123",
|
||||
},
|
||||
last_refresh: "2026-04-22T00:00:00.000Z",
|
||||
});
|
||||
});
|
||||
|
||||
it("hydrates from inherited CODEX_HOME when start options do not override it", async () => {
|
||||
const sourceCodexHome = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-codex-source-home-"));
|
||||
tempDirs.push(sourceCodexHome);
|
||||
await fs.writeFile(
|
||||
path.join(sourceCodexHome, "auth.json"),
|
||||
`${JSON.stringify(
|
||||
{
|
||||
auth_mode: "chatgpt",
|
||||
tokens: {
|
||||
id_token: "source-id-token",
|
||||
access_token: "access-token",
|
||||
refresh_token: "refresh-token",
|
||||
account_id: "acct-123",
|
||||
},
|
||||
last_refresh: "2026-04-22T00:00:00.000Z",
|
||||
},
|
||||
null,
|
||||
2,
|
||||
)}\n`,
|
||||
);
|
||||
const previousCodexHome = process.env.CODEX_HOME;
|
||||
process.env.CODEX_HOME = sourceCodexHome;
|
||||
try {
|
||||
const agentDir = await createAgentDirWithDefaultProfile({
|
||||
accountId: "acct-123",
|
||||
});
|
||||
|
||||
const result = await bridgeCodexAppServerStartOptions({
|
||||
startOptions: {
|
||||
transport: "stdio",
|
||||
command: "codex",
|
||||
args: ["app-server"],
|
||||
headers: {},
|
||||
},
|
||||
agentDir,
|
||||
});
|
||||
|
||||
expect(result.env?.CODEX_HOME).not.toBe(sourceCodexHome);
|
||||
const authFile = JSON.parse(
|
||||
await fs.readFile(path.join(result.env?.CODEX_HOME ?? "", "auth.json"), "utf8"),
|
||||
);
|
||||
expect(authFile).toEqual({
|
||||
auth_mode: "chatgpt",
|
||||
tokens: {
|
||||
id_token: "source-id-token",
|
||||
access_token: "access-token",
|
||||
refresh_token: "refresh-token",
|
||||
account_id: "acct-123",
|
||||
},
|
||||
last_refresh: "2026-04-22T00:00:00.000Z",
|
||||
});
|
||||
} finally {
|
||||
if (previousCodexHome === undefined) {
|
||||
delete process.env.CODEX_HOME;
|
||||
} else {
|
||||
process.env.CODEX_HOME = previousCodexHome;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it("leaves start options unchanged when canonical oauth is unavailable", async () => {
|
||||
const agentDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-codex-app-server-"));
|
||||
tempDirs.push(agentDir);
|
||||
|
||||
@@ -13,6 +13,7 @@ export async function bridgeCodexAppServerStartOptions(params: {
|
||||
agentDir: params.agentDir,
|
||||
bridgeDir: "harness-auth",
|
||||
profileId,
|
||||
sourceCodexHome: params.startOptions.env?.CODEX_HOME,
|
||||
});
|
||||
if (!bridge) {
|
||||
return params.startOptions;
|
||||
|
||||
Reference in New Issue
Block a user