[codex] Fix Codex OAuth status auth label (#76197)

Merged via squash.

Prepared head SHA: a0168232b5
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
This commit is contained in:
Mariano
2026-05-02 20:34:00 +02:00
committed by GitHub
parent 38990c0e09
commit ba5723d38b
5 changed files with 130 additions and 19 deletions

View File

@@ -2,6 +2,14 @@
Docs: https://docs.openclaw.ai
## Unreleased
### Changes
### Fixes
- Status: show the `openai-codex` OAuth profile for `openai/gpt-*` sessions running through the native Codex runtime instead of reporting auth as unknown. (#76197) Thanks @mbelinky.
## 2026.5.2
### Highlights

View File

@@ -534,6 +534,91 @@ describe("buildStatusReply subagent summary", () => {
expect(normalized).not.toContain("Fast · codex");
});
it("uses Codex OAuth auth labels for openai models running on the Codex harness", async () => {
registerStatusCodexHarness();
await withTempHome(
async (dir) => {
const authPath = path.join(
dir,
".openclaw",
"agents",
"main",
"agent",
"auth-profiles.json",
);
fs.mkdirSync(path.dirname(authPath), { recursive: true });
fs.writeFileSync(
authPath,
JSON.stringify({
version: 1,
profiles: {
"openai-codex:status": {
type: "oauth",
provider: "openai-codex",
access: "access-token",
refresh: "refresh-token",
expires: Date.now() + 60_000,
},
},
}),
"utf8",
);
const commonParams = {
sessionEntry: {
sessionId: "sess-status-codex-oauth",
updatedAt: 0,
},
sessionKey: "agent:main:main",
parentSessionKey: "agent:main:main",
sessionScope: "per-sender" as const,
statusChannel: "mobilechat",
provider: "openai",
model: "gpt-5.5",
contextTokens: 32_000,
resolvedFastMode: false,
resolvedVerboseLevel: "off" as const,
resolvedReasoningLevel: "off" as const,
resolveDefaultThinkingLevel: async () => undefined,
isGroup: false,
defaultGroupActivation: () => "mention" as const,
};
const codexText = await buildStatusText({
cfg: {
...baseCfg,
agents: {
defaults: {
agentRuntime: { id: "codex", fallback: "none" },
},
},
},
...commonParams,
});
const piText = await buildStatusText({
cfg: baseCfg,
...commonParams,
});
const normalizedCodex = normalizeTestText(codexText);
const normalizedPi = normalizeTestText(piText);
expect(normalizedCodex).toContain("Model: openai/gpt-5.5");
expect(normalizedCodex).toContain("oauth (openai-codex:status)");
expect(normalizedCodex).toContain("openai-codex:status");
expect(normalizedPi).toContain("Model: openai/gpt-5.5");
expect(normalizedPi).toContain("unknown");
expect(normalizedPi).not.toContain("openai-codex:status");
},
{
env: {
OPENAI_API_KEY: undefined,
OPENAI_OAUTH_TOKEN: undefined,
},
},
);
});
it("uses workspace-scoped auth evidence in /status auth labels", async () => {
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-status-auth-label-"));
const workspaceDir = path.join(tempRoot, "workspace");

View File

@@ -213,7 +213,7 @@ export function buildPreferredClawHubSpec(raw: string): string | null {
}
function normalizeReadinessPhase(readiness: ClawHubPackageReadiness): string {
return normalizeLowercaseStringOrEmpty(String(readiness.phase ?? readiness.status ?? ""));
return normalizeLowercaseStringOrEmpty(readiness.phase ?? readiness.status ?? "");
}
export function isClawHubReadinessInstallReady(

View File

@@ -60,8 +60,8 @@ export type ClawHubArtifactScanState =
| "suspicious"
| "malicious"
| "not-run"
| string;
export type ClawHubArtifactModerationState = "approved" | "quarantined" | "revoked" | string;
| (string & {});
export type ClawHubArtifactModerationState = "approved" | "quarantined" | "revoked" | (string & {});
export type ClawHubResolvedArtifact =
| {
source: "clawhub";
@@ -115,7 +115,7 @@ export type ClawHubPackageReadinessPhase =
| "metadata-ready"
| "blocked"
| "ready-for-openclaw"
| string;
| (string & {});
export type ClawHubPackageReadiness = {
ready?: boolean | null;
readyForOpenClaw?: boolean | null;
@@ -124,12 +124,12 @@ export type ClawHubPackageReadiness = {
status?: ClawHubPackageReadinessPhase | null;
package?: {
name?: string | null;
family?: ClawHubPackageFamily | string | null;
channel?: ClawHubPackageChannel | string | null;
family?: ClawHubPackageFamily | (string & {}) | null;
channel?: ClawHubPackageChannel | (string & {}) | null;
isOfficial?: boolean | null;
} | null;
packageName?: string | null;
artifactKind?: ClawHubArtifactKind | string | null;
artifactKind?: ClawHubArtifactKind | (string & {}) | null;
blockers?: string[];
scanState?: ClawHubArtifactScanState | null;
moderationState?: ClawHubArtifactModerationState | null;

View File

@@ -136,6 +136,18 @@ async function resolveStatusHarnessId(params: {
}
}
function resolveStatusAuthProvider(params: {
provider: string;
effectiveHarness?: string;
}): string {
const harness = normalizeOptionalLowercaseString(params.effectiveHarness);
const provider = normalizeOptionalLowercaseString(params.provider);
if (harness === "codex" && provider === "openai") {
return "openai-codex";
}
return params.provider;
}
function formatAgentTaskCountsLine(agentId: string): string | undefined {
const snapshot = buildTaskStatusSnapshot(listTasksForAgentIdForStatus(agentId));
if (snapshot.totalCount === 0) {
@@ -178,10 +190,23 @@ export async function buildStatusText(params: BuildStatusTextParams): Promise<st
selectedModel: model,
sessionEntry,
});
const effectiveHarness =
params.resolvedHarness ??
(await resolveStatusHarnessId({
cfg,
provider,
model,
agentId: statusAgentId,
sessionKey,
sessionEntry,
}));
const selectedModelAuth = Object.hasOwn(params, "modelAuthOverride")
? params.modelAuthOverride
: resolveModelAuthLabel({
provider,
provider: resolveStatusAuthProvider({
provider,
effectiveHarness,
}),
cfg,
sessionEntry,
agentDir: statusAgentDir,
@@ -192,7 +217,10 @@ export async function buildStatusText(params: BuildStatusTextParams): Promise<st
? params.activeModelAuthOverride
: modelRefs.activeDiffers
? resolveModelAuthLabel({
provider: modelRefs.active.provider,
provider: resolveStatusAuthProvider({
provider: modelRefs.active.provider,
effectiveHarness,
}),
cfg,
sessionEntry,
agentDir: statusAgentDir,
@@ -297,16 +325,6 @@ export async function buildStatusText(params: BuildStatusTextParams): Promise<st
agentId: statusAgentId,
sessionEntry,
}).enabled;
const effectiveHarness =
params.resolvedHarness ??
(await resolveStatusHarnessId({
cfg,
provider,
model,
agentId: statusAgentId,
sessionKey,
sessionEntry,
}));
const agentFallbacksOverride = resolveAgentModelFallbacksOverride(cfg, statusAgentId);
const { buildStatusMessage } = await loadStatusMessageRuntime();
const explicitThinkingDefault =