mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 13:10:43 +00:00
fix(agents): detect codex cli auth in status
Fixes #70688. Co-authored-by: Jon Brown <801241+jb510@users.noreply.github.com>
This commit is contained in:
@@ -28,6 +28,7 @@ Docs: https://docs.openclaw.ai
|
||||
### Fixes
|
||||
|
||||
- Codex harness: route native `request_user_input` prompts back to the originating chat, preserve queued follow-up answers, and honor newer app-server command approval amendment decisions.
|
||||
- Codex status: report Codex CLI OAuth as `oauth (codex-cli)` for native `codex/*` sessions instead of showing unknown auth. Fixes #70688. Thanks @jb510.
|
||||
- Codex harness/context-engine: redact context-engine assembly failures before logging, so fallback warnings do not serialize raw error objects. (#70809) Thanks @jalehman.
|
||||
- WhatsApp/onboarding: keep first-run setup entry loading off the Baileys runtime dependency path, so packaged QuickStart installs can show WhatsApp setup before runtime deps are staged. Fixes #70932.
|
||||
- Block streaming: suppress final assembled text after partial block-delivery aborts when the already-sent text chunks exactly cover the final reply, preventing duplicate replies without dropping unrelated short messages. Fixes #70921.
|
||||
|
||||
@@ -7,6 +7,7 @@ const mocks = vi.hoisted(() => ({
|
||||
resolveAuthProfileDisplayLabel: vi.fn(),
|
||||
resolveUsableCustomProviderApiKey: vi.fn(() => null),
|
||||
resolveEnvApiKey: vi.fn(() => null),
|
||||
readCodexCliCredentialsCached: vi.fn<() => unknown>(() => null),
|
||||
}));
|
||||
|
||||
vi.mock("./auth-profiles.js", () => ({
|
||||
@@ -21,6 +22,10 @@ vi.mock("./model-auth.js", () => ({
|
||||
resolveEnvApiKey: mocks.resolveEnvApiKey,
|
||||
}));
|
||||
|
||||
vi.mock("./cli-credentials.js", () => ({
|
||||
readCodexCliCredentialsCached: mocks.readCodexCliCredentialsCached,
|
||||
}));
|
||||
|
||||
let resolveModelAuthLabel: typeof import("./model-auth-label.js").resolveModelAuthLabel;
|
||||
|
||||
describe("resolveModelAuthLabel", () => {
|
||||
@@ -36,6 +41,8 @@ describe("resolveModelAuthLabel", () => {
|
||||
mocks.resolveUsableCustomProviderApiKey.mockReturnValue(null);
|
||||
mocks.resolveEnvApiKey.mockReset();
|
||||
mocks.resolveEnvApiKey.mockReturnValue(null);
|
||||
mocks.readCodexCliCredentialsCached.mockReset();
|
||||
mocks.readCodexCliCredentialsCached.mockReturnValue(null);
|
||||
});
|
||||
|
||||
it("does not include token value in label for token profiles", () => {
|
||||
@@ -112,6 +119,28 @@ describe("resolveModelAuthLabel", () => {
|
||||
expect(label).toBe("oauth (anthropic:oauth)");
|
||||
});
|
||||
|
||||
it("shows codex cli auth for codex provider without auth profiles", () => {
|
||||
mocks.ensureAuthProfileStore.mockReturnValue({
|
||||
version: 1,
|
||||
profiles: {},
|
||||
} as never);
|
||||
mocks.resolveAuthProfileOrder.mockReturnValue([]);
|
||||
mocks.readCodexCliCredentialsCached.mockReturnValue({
|
||||
type: "oauth",
|
||||
provider: "openai-codex",
|
||||
access: "token",
|
||||
refresh: "refresh",
|
||||
expires: Date.now() + 60_000,
|
||||
});
|
||||
|
||||
const label = resolveModelAuthLabel({
|
||||
provider: "codex",
|
||||
cfg: {},
|
||||
});
|
||||
|
||||
expect(label).toBe("oauth (codex-cli)");
|
||||
});
|
||||
|
||||
it("can skip external auth profile overlays for status labels", () => {
|
||||
mocks.loadAuthProfileStoreWithoutExternalProfiles.mockReturnValue({
|
||||
version: 1,
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
resolveAuthProfileDisplayLabel,
|
||||
resolveAuthProfileOrder,
|
||||
} from "./auth-profiles.js";
|
||||
import { readCodexCliCredentialsCached } from "./cli-credentials.js";
|
||||
import { resolveEnvApiKey, resolveUsableCustomProviderApiKey } from "./model-auth.js";
|
||||
import { normalizeProviderId } from "./model-selection.js";
|
||||
|
||||
@@ -64,6 +65,10 @@ export function resolveModelAuthLabel(params: {
|
||||
return `api-key (${envKey.source})`;
|
||||
}
|
||||
|
||||
if (providerKey === "codex" && readCodexCliCredentialsCached({ ttlMs: 5_000 })) {
|
||||
return "oauth (codex-cli)";
|
||||
}
|
||||
|
||||
const customKey = resolveUsableCustomProviderApiKey({
|
||||
cfg: params.cfg,
|
||||
provider: providerKey,
|
||||
|
||||
@@ -92,12 +92,14 @@ let resolveApiKeyForProvider: typeof import("./model-auth.js").resolveApiKeyForP
|
||||
let resolveAwsSdkEnvVarName: typeof import("./model-auth.js").resolveAwsSdkEnvVarName;
|
||||
let resolveModelAuthMode: typeof import("./model-auth.js").resolveModelAuthMode;
|
||||
let resolveUsableCustomProviderApiKey: typeof import("./model-auth.js").resolveUsableCustomProviderApiKey;
|
||||
let cliCredentials: typeof import("./cli-credentials.js");
|
||||
let clearRuntimeConfigSnapshot: typeof import("../config/config.js").clearRuntimeConfigSnapshot;
|
||||
let setRuntimeConfigSnapshot: typeof import("../config/config.js").setRuntimeConfigSnapshot;
|
||||
|
||||
beforeAll(async () => {
|
||||
vi.resetModules();
|
||||
({ clearRuntimeConfigSnapshot, setRuntimeConfigSnapshot } = await import("../config/config.js"));
|
||||
cliCredentials = await import("./cli-credentials.js");
|
||||
({
|
||||
applyAuthHeaderOverride,
|
||||
applyLocalNoAuthHeaderOverride,
|
||||
@@ -259,6 +261,24 @@ describe("resolveModelAuthMode", () => {
|
||||
"aws-sdk",
|
||||
);
|
||||
});
|
||||
|
||||
it("returns oauth for codex when Codex CLI auth is available", () => {
|
||||
const readCodexCliCredentialsCached = vi
|
||||
.spyOn(cliCredentials, "readCodexCliCredentialsCached")
|
||||
.mockReturnValue({
|
||||
type: "oauth",
|
||||
provider: "openai-codex",
|
||||
access: "token",
|
||||
refresh: "refresh",
|
||||
expires: Date.now() + 60_000,
|
||||
});
|
||||
|
||||
try {
|
||||
expect(resolveModelAuthMode("codex", undefined, { version: 1, profiles: {} })).toBe("oauth");
|
||||
} finally {
|
||||
readCodexCliCredentialsCached.mockRestore();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("requireApiKey", () => {
|
||||
|
||||
@@ -27,6 +27,7 @@ import {
|
||||
resolveAuthProfileOrder,
|
||||
resolveAuthStorePathForDisplay,
|
||||
} from "./auth-profiles.js";
|
||||
import * as cliCredentials from "./cli-credentials.js";
|
||||
import { resolveEnvApiKey, type EnvApiKeyResult } from "./model-auth-env.js";
|
||||
import {
|
||||
CUSTOM_LOCAL_AUTH_MARKER,
|
||||
@@ -654,6 +655,13 @@ export function resolveModelAuthMode(
|
||||
return envKey.source.includes("OAUTH_TOKEN") ? "oauth" : "api-key";
|
||||
}
|
||||
|
||||
if (
|
||||
normalizeProviderId(resolved) === "codex" &&
|
||||
cliCredentials.readCodexCliCredentialsCached({ ttlMs: 5_000 })
|
||||
) {
|
||||
return "oauth";
|
||||
}
|
||||
|
||||
if (hasUsableCustomProviderApiKey(cfg, resolved)) {
|
||||
return "api-key";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user