fix: honor Codex auth order for OpenAI PI (#82605)

* fix: honor Codex auth order for OpenAI PI

* docs: add PR reference for OpenAI PI auth fix
This commit is contained in:
Peter Steinberger
2026-05-16 15:26:27 +01:00
committed by GitHub
parent 16e5d6692d
commit 9dedc4d95c
19 changed files with 450 additions and 26 deletions

View File

@@ -43,6 +43,7 @@ Docs: https://docs.openclaw.ai
- Telegram: persist polling updates through restart replay so queued same-topic messages resume in order instead of losing context after a gateway restart. (#82256) Thanks @VACInc.
- Gateway/Gmail: abort in-flight Gmail watcher startup and hot-reload restarts before shutdown so reloads cannot spawn `gog serve` after the Gateway is closing. Thanks @frankekn.
- Agents/Codex: fall back to the embedded PI runner when OpenAI's implicit Codex harness preference cannot find a registered Codex plugin, preventing OpenAI-compatible gateway requests from failing with an unregistered harness error. Fixes #82437.
- Agents/OpenAI: honor `openai-codex:*` entries placed ahead of API-key backups in `auth.order.openai` for explicit OpenAI PI runs, and accept `models auth login --provider openai-codex --device-code` for headless sign-in. Fixes #82521. (#82605)
- CLI/channels: install missing externalized same-id channel plugins during `channels add --channel <id>`, so recovery for WhatsApp and other externalized stock channels does not require a separate `plugins enable` step. Fixes #82533.
- MCP plugin tools: forward host MCP `tools/call` `AbortSignal` through `createPluginToolsMcpHandlers().callTool` into plugin `tool.execute`, so host cancellation actually cancels in-flight plugin tool calls instead of letting them run to completion. Fixes #82424. (#82443) Thanks @joshavant.
- Plugins: accept deprecated `api.on("deactivate")` registrations as a dated compatibility alias for `gateway_stop`, so external plugin cleanup handlers run on Gateway shutdown while authors get migration guidance.

View File

@@ -894,6 +894,7 @@ async function agentCommandInternal(
const acceptedAuthProviders = listOpenAIAuthProfileProvidersForAgentRuntime({
provider: providerForAuthProfileValidation,
harnessRuntime: validationHarnessPolicy.runtime,
config: cfg,
}).map((candidateProvider) =>
resolveProviderIdForAuth(candidateProvider, { config: cfg, workspaceDir }),
);

View File

@@ -337,6 +337,40 @@ describe("resolveAuthProfileOrder", () => {
expect(order).toEqual(["openai-codex:personal", "openai:default"]);
});
it("keeps Codex profiles listed in the friendly OpenAI order for Codex auth", async () => {
const store: AuthProfileStore = {
version: 1,
profiles: {
"openai-codex:personal": {
type: "oauth",
provider: "openai-codex",
access: "access",
refresh: "refresh",
expires: Date.now() + 60_000,
},
"openai:backup": {
type: "api_key",
provider: "openai",
key: "sk-platform",
},
},
};
const order = resolveAuthProfileOrder({
cfg: {
auth: {
order: {
openai: ["openai-codex:personal", "openai:backup"],
},
},
},
store,
provider: "openai-codex",
});
expect(order).toEqual(["openai-codex:personal", "openai:backup"]);
});
it("keeps direct OpenAI Codex auth order ahead of the friendly OpenAI alias", async () => {
const store: AuthProfileStore = {
version: 1,

View File

@@ -256,6 +256,7 @@ async function resolveRuntimeModel(params: {
agentId: params.agentId,
sessionKey: params.sessionKey,
}).runtime,
config: params.cfg,
}),
agentDir: params.agentDir,
sessionEntry: params.sessionEntry,

View File

@@ -463,6 +463,11 @@ export function runAgentAttempt(params: {
config: params.cfg,
workspaceDir: params.workspaceDir,
});
const embeddedPiHarnessOverride =
requestedAgentHarnessId ??
(agentHarnessPolicy.runtime === "pi" && embeddedPiProvider !== params.providerOverride
? "pi"
: undefined);
if (!isRawModelRun && isCliProvider(cliExecutionProvider, params.cfg)) {
const cliSessionBinding = getCliSessionBinding(params.sessionEntry, cliExecutionProvider);
const resolveReusableCliSessionBinding = async () => {
@@ -609,7 +614,8 @@ export function runAgentAttempt(params: {
sessionFile: params.sessionFile,
workspaceDir: params.workspaceDir,
config: params.cfg,
agentHarnessId: requestedAgentHarnessId,
agentHarnessId: embeddedPiHarnessOverride,
agentHarnessRuntimeOverride: embeddedPiHarnessOverride,
skillsSnapshot: params.skillsSnapshot,
prompt: effectivePrompt,
images: params.isFallbackRetry ? undefined : params.opts.images,

View File

@@ -7,6 +7,7 @@ import {
resolveAuthProfileDisplayLabel,
resolveAuthProfileOrder,
} from "./auth-profiles.js";
import { isStoredCredentialCompatibleWithAuthProvider } from "./auth-profiles/order.js";
import {
readClaudeCliCredentialsCached,
readCodexCliCredentialsCached,
@@ -21,6 +22,7 @@ export function resolveModelAuthLabel(params: {
agentDir?: string;
workspaceDir?: string;
includeExternalProfiles?: boolean;
acceptedProviderIds?: readonly string[];
}): string | undefined {
const resolvedProvider = params.provider?.trim();
if (!resolvedProvider) {
@@ -39,17 +41,37 @@ export function resolveModelAuthLabel(params: {
}),
});
const profileOverride = params.sessionEntry?.authProfileOverride?.trim();
const order = resolveAuthProfileOrder({
cfg: params.cfg,
store,
provider: providerKey,
preferredProfile: profileOverride,
});
const acceptedProviderKeys = [
...new Set(
[...(params.acceptedProviderIds ?? []).map(normalizeProviderId), providerKey].filter(Boolean),
),
];
const order = [
...new Set(
acceptedProviderKeys.flatMap((acceptedProvider) =>
resolveAuthProfileOrder({
cfg: params.cfg,
store,
provider: acceptedProvider,
preferredProfile: profileOverride,
}),
),
),
];
const candidates = [profileOverride, ...order].filter(Boolean) as string[];
for (const profileId of candidates) {
const profile = store.profiles[profileId];
if (!profile || normalizeProviderId(profile.provider) !== providerKey) {
if (
!profile ||
!acceptedProviderKeys.some((acceptedProvider) =>
isStoredCredentialCompatibleWithAuthProvider({
cfg: params.cfg,
provider: acceptedProvider,
credential: profile,
}),
)
) {
continue;
}
const label = resolveAuthProfileDisplayLabel({

View File

@@ -5,6 +5,7 @@ import {
modelSelectionShouldEnsureCodexPlugin,
openAIProviderUsesCodexRuntimeByDefault,
resolveOpenAIRuntimeProviderForPi,
resolveSelectedOpenAIPiRuntimeProvider,
} from "./openai-codex-routing.js";
describe("OpenAI Codex routing policy", () => {
@@ -51,6 +52,96 @@ describe("OpenAI Codex routing policy", () => {
).toBe("openai-codex");
});
it("keeps explicit OpenAI PI Codex auth order ahead of API-key backups", () => {
const config = {
auth: {
order: {
openai: ["openai-codex:work", "openai:backup"],
},
},
} satisfies OpenClawConfig;
expect(
listOpenAIAuthProfileProvidersForAgentRuntime({
provider: "openai",
harnessRuntime: "pi",
config,
}),
).toEqual(["openai-codex", "openai"]);
expect(
resolveSelectedOpenAIPiRuntimeProvider({
provider: "openai",
harnessRuntime: "pi",
config,
}),
).toBe("openai-codex");
expect(
resolveOpenAIRuntimeProviderForPi({
provider: "openai",
harnessRuntime: "pi",
config,
}),
).toBe("openai");
});
it("keeps explicit OpenAI PI API-key auth order ahead of Codex backups", () => {
const config = {
auth: {
order: {
openai: ["openai:backup", "openai-codex:work"],
},
},
} satisfies OpenClawConfig;
expect(
listOpenAIAuthProfileProvidersForAgentRuntime({
provider: "openai",
harnessRuntime: "pi",
config,
}),
).toEqual(["openai", "openai-codex"]);
expect(
resolveSelectedOpenAIPiRuntimeProvider({
provider: "openai",
harnessRuntime: "pi",
config,
}),
).toBe("openai");
});
it("does not route custom OpenAI-compatible PI configs through Codex auth order", () => {
const config = {
models: {
providers: {
openai: {
baseUrl: "https://proxy.example.test/v1",
models: [],
},
},
},
auth: {
order: {
openai: ["openai-codex:work", "openai:backup"],
},
},
} satisfies OpenClawConfig;
expect(
listOpenAIAuthProfileProvidersForAgentRuntime({
provider: "openai",
harnessRuntime: "pi",
config,
}),
).toEqual(["openai", "openai-codex"]);
expect(
resolveSelectedOpenAIPiRuntimeProvider({
provider: "openai",
harnessRuntime: "pi",
config,
}),
).toBe("openai");
});
it("validates Codex harness auth through the Codex provider contract", () => {
expect(
listOpenAIAuthProfileProvidersForAgentRuntime({

View File

@@ -2,7 +2,7 @@ import type { OpenClawConfig } from "../config/types.openclaw.js";
import { normalizeOptionalLowercaseString } from "../shared/string-coerce.js";
import { normalizeEmbeddedAgentRuntime } from "./pi-embedded-runner/runtime.js";
import { resolveProviderIdForAuth } from "./provider-auth-aliases.js";
import { normalizeProviderId } from "./provider-id.js";
import { findNormalizedProviderValue, normalizeProviderId } from "./provider-id.js";
export const OPENAI_PROVIDER_ID = "openai";
export const OPENAI_CODEX_PROVIDER_ID = "openai-codex";
@@ -78,6 +78,20 @@ export function hasOpenAICodexAuthProfileOverride(value: unknown): boolean {
);
}
function configuredOpenAIAuthOrderStartsWithCodexProfile(config: OpenClawConfig | undefined) {
if (!openAIProviderUsesCodexRuntimeByDefault({ provider: OPENAI_PROVIDER_ID, config })) {
return false;
}
const configuredOpenAIOrder = findNormalizedProviderValue(
config?.auth?.order,
OPENAI_PROVIDER_ID,
);
const firstProfile = configuredOpenAIOrder?.find(
(profileId) => typeof profileId === "string" && profileId.trim().length > 0,
);
return hasOpenAICodexAuthProfileOverride(firstProfile);
}
export function shouldRouteOpenAIPiThroughCodexAuthProvider(params: {
provider: string;
harnessRuntime?: string;
@@ -87,16 +101,16 @@ export function shouldRouteOpenAIPiThroughCodexAuthProvider(params: {
config?: OpenClawConfig;
workspaceDir?: string;
}): boolean {
if (
!isOpenAIProvider(params.provider) ||
!hasOpenAICodexAuthProfileOverride(params.authProfileId)
) {
if (!isOpenAIProvider(params.provider)) {
return false;
}
const runtime = normalizeEmbeddedAgentRuntime(params.agentHarnessId ?? params.harnessRuntime);
if (runtime !== "pi") {
return false;
}
if (!hasOpenAICodexAuthProfileOverride(params.authProfileId)) {
return false;
}
const aliasLookupParams = {
config: params.config,
workspaceDir: params.workspaceDir,
@@ -112,6 +126,7 @@ export function listOpenAIAuthProfileProvidersForAgentRuntime(params: {
provider: string;
harnessRuntime?: string;
agentHarnessId?: string;
config?: OpenClawConfig;
}): string[] {
if (!isOpenAIProvider(params.provider)) {
return [params.provider];
@@ -123,6 +138,9 @@ export function listOpenAIAuthProfileProvidersForAgentRuntime(params: {
return [OPENAI_CODEX_PROVIDER_ID];
}
if (runtime === "pi") {
if (configuredOpenAIAuthOrderStartsWithCodexProfile(params.config)) {
return [OPENAI_CODEX_PROVIDER_ID, OPENAI_PROVIDER_ID];
}
return [OPENAI_PROVIDER_ID, OPENAI_CODEX_PROVIDER_ID];
}
return [params.provider];
@@ -150,6 +168,27 @@ export function resolveOpenAIRuntimeProviderForPi(params: {
: params.provider;
}
export function resolveSelectedOpenAIPiRuntimeProvider(params: {
provider: string;
harnessRuntime?: string;
agentHarnessId?: string;
authProfileProvider?: string;
authProfileId?: string;
config?: OpenClawConfig;
workspaceDir?: string;
}): string {
if (shouldRouteOpenAIPiThroughCodexAuthProvider(params)) {
return OPENAI_CODEX_PROVIDER_ID;
}
const runtime = normalizeEmbeddedAgentRuntime(params.agentHarnessId ?? params.harnessRuntime);
return isOpenAIProvider(params.provider) &&
runtime === "pi" &&
!params.authProfileId?.trim() &&
configuredOpenAIAuthOrderStartsWithCodexProfile(params.config)
? OPENAI_CODEX_PROVIDER_ID
: params.provider;
}
export function resolveContextConfigProviderForRuntime(params: {
provider: string;
runtimeId?: string;

View File

@@ -343,6 +343,69 @@ describe("runEmbeddedPiAgent", () => {
expect(ensureOpenClawModelsJsonMock).not.toHaveBeenCalled();
});
it("resolves explicit OpenAI PI runs through Codex when auth order starts with Codex OAuth", async () => {
const sessionFile = nextSessionFile();
const cfg = {
...createEmbeddedPiRunnerOpenAiConfig(["mock-1"]),
agents: {
defaults: {
models: {
"openai/mock-1": {
agentRuntime: { id: "pi" },
},
},
},
},
auth: {
order: {
openai: ["openai-codex:work", "openai:backup"],
},
},
};
runEmbeddedAttemptMock.mockResolvedValueOnce(
makeEmbeddedRunnerAttempt({
assistantTexts: ["ok"],
lastAssistant: buildEmbeddedRunnerAssistant({
content: [{ type: "text", text: "ok" }],
}),
}),
);
await runEmbeddedPiAgent({
sessionId: "codex-first-pi",
sessionFile,
workspaceDir,
config: cfg,
prompt: "hello",
provider: "openai",
model: "mock-1",
timeoutMs: 5_000,
agentDir,
runId: nextRunId("codex-first-pi"),
enqueue: immediateEnqueue,
});
expect(resolveModelAsyncMock).toHaveBeenNthCalledWith(
1,
"openai",
"mock-1",
agentDir,
cfg,
expect.objectContaining({ skipPiDiscovery: true }),
);
expect(resolveModelAsyncMock).toHaveBeenNthCalledWith(
2,
"openai-codex",
"mock-1",
agentDir,
cfg,
expect.objectContaining({ skipPiDiscovery: true }),
);
expect(
(firstRunEmbeddedAttemptParams() as { model?: { provider?: string } }).model?.provider,
).toBe("openai-codex");
});
it("backfills a trimmed session key from sessionId when the embedded run omits it", async () => {
const sessionFile = nextSessionFile();
const cfg = createEmbeddedPiRunnerOpenAiConfig(["mock-1"]);

View File

@@ -61,7 +61,11 @@ import {
shouldPreferExplicitConfigApiKeyAuth,
} from "../model-auth.js";
import { ensureOpenClawModelsJson } from "../models-config.js";
import { resolveContextConfigProviderForRuntime } from "../openai-codex-routing.js";
import {
listOpenAIAuthProfileProvidersForAgentRuntime,
resolveContextConfigProviderForRuntime,
resolveSelectedOpenAIPiRuntimeProvider,
} from "../openai-codex-routing.js";
import {
retireSessionMcpRuntime,
retireSessionMcpRuntimeForSessionKey,
@@ -552,6 +556,16 @@ export async function runEmbeddedPiAgent(
agentHarnessRuntimeOverride: params.agentHarnessRuntimeOverride,
});
const pluginHarnessOwnsTransport = agentHarness.id !== "pi";
const modelConfigProvider = provider;
const selectedPiRuntimeProvider = resolveSelectedOpenAIPiRuntimeProvider({
provider,
harnessRuntime: agentHarness.id,
agentHarnessId: agentHarness.id,
authProfileProvider: params.authProfileId?.split(":", 1)[0],
authProfileId: params.authProfileId,
config: params.config,
workspaceDir: resolvedWorkspace,
});
const dynamicModelResolution = await resolveModelAsync(
provider,
modelId,
@@ -565,7 +579,7 @@ export async function runEmbeddedPiAgent(
workspaceDir: resolvedWorkspace,
},
);
const modelResolution =
let modelResolution =
dynamicModelResolution.model || pluginHarnessOwnsTransport
? dynamicModelResolution
: await (async () => {
@@ -576,6 +590,22 @@ export async function runEmbeddedPiAgent(
workspaceDir: resolvedWorkspace,
});
})();
if (selectedPiRuntimeProvider !== provider && modelResolution.model) {
const runtimeModelResolution = await resolveModelAsync(
selectedPiRuntimeProvider,
modelId,
agentDir,
params.config,
{
skipPiDiscovery: true,
workspaceDir: resolvedWorkspace,
},
);
if (runtimeModelResolution.model) {
provider = selectedPiRuntimeProvider;
modelResolution = runtimeModelResolution;
}
}
const { model, error, authStorage, modelRegistry } = modelResolution;
if (!model) {
throw new FailoverError(error ?? `Unknown model: ${provider}/${modelId}`, {
@@ -592,7 +622,7 @@ export async function runEmbeddedPiAgent(
cfg: params.config,
provider,
contextConfigProvider: resolveContextConfigProviderForRuntime({
provider,
provider: modelConfigProvider,
runtimeId: agentHarness.id,
}),
modelId,
@@ -719,12 +749,23 @@ export async function runEmbeddedPiAgent(
}
const profileOrder = shouldPreferExplicitConfigApiKeyAuth(params.config, provider)
? []
: resolveAuthProfileOrder({
cfg: params.config,
store: authStore,
provider,
preferredProfile: preferredProfileId,
});
: [
...new Set(
listOpenAIAuthProfileProvidersForAgentRuntime({
provider,
harnessRuntime: agentHarness.id,
agentHarnessId: agentHarness.id,
config: params.config,
}).flatMap((authProvider) =>
resolveAuthProfileOrder({
cfg: params.config,
store: authStore,
provider: authProvider,
preferredProfile: preferredProfileId,
}),
),
),
];
const providerPreferredProfileId = lockedProfileId
? undefined
: resolveProviderAuthProfileId({

View File

@@ -1791,6 +1791,11 @@ export async function runAgentTurnWithFallback(params: {
config: runtimeConfig,
workspaceDir: params.followupRun.run.workspaceDir,
});
const embeddedRunHarnessOverride =
sessionRuntimeOverride ??
(agentHarnessPolicy.runtime === "pi" && embeddedRunProvider !== provider
? "pi"
: undefined);
return (async () => {
let attemptCompactionCount = 0;
const lifecycleBackstop = createEmbeddedLifecycleTerminalBackstop({
@@ -1810,8 +1815,8 @@ export async function runAgentTurnWithFallback(params: {
...senderContext,
...runBaseParams,
provider: embeddedRunProvider,
agentHarnessId: sessionRuntimeOverride,
agentHarnessRuntimeOverride: sessionRuntimeOverride,
agentHarnessId: embeddedRunHarnessOverride,
agentHarnessRuntimeOverride: embeddedRunHarnessOverride,
sandboxSessionKey: params.runtimePolicySessionKey,
prompt: params.commandBody,
transcriptPrompt: params.transcriptCommandBody,

View File

@@ -716,6 +716,87 @@ describe("buildStatusReply subagent summary", () => {
);
});
it("uses Codex OAuth auth labels for explicit OpenAI PI auth order", async () => {
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 * 60_000,
},
"openai:backup": {
type: "api_key",
provider: "openai",
key: "sk-test",
},
},
}),
"utf8",
);
const text = await buildStatusText({
cfg: {
...baseCfg,
agents: {
defaults: {
models: {
"openai/gpt-5.5": {
agentRuntime: { id: "pi" },
},
},
},
},
auth: {
order: {
openai: ["openai-codex:status", "openai:backup"],
},
},
},
sessionEntry: {
sessionId: "sess-status-openai-pi-codex-oauth",
updatedAt: 0,
},
sessionKey: "agent:main:main",
parentSessionKey: "agent:main:main",
sessionScope: "per-sender",
statusChannel: "mobilechat",
provider: "openai",
model: "gpt-5.5",
contextTokens: 32_000,
resolvedHarness: "pi",
resolvedFastMode: false,
resolvedVerboseLevel: "off",
resolvedReasoningLevel: "off",
resolveDefaultThinkingLevel: async () => undefined,
isGroup: false,
defaultGroupActivation: () => "mention",
});
const normalized = normalizeTestText(text);
expect(normalized).toContain("Model: openai/gpt-5.5");
expect(normalized).toContain("oauth (openai-codex:status)");
expect(normalized).not.toContain("api-key (openai:backup)");
},
{ env: { OPENAI_API_KEY: undefined } },
);
});
it("uses Claude CLI OAuth auth labels for anthropic models running on the Claude CLI runtime", async () => {
await withTempHome(
async (dir) => {

View File

@@ -880,6 +880,7 @@ export async function runPreparedReply(
? listOpenAIAuthProfileProvidersForAgentRuntime({
provider,
harnessRuntime: agentHarnessPolicy.runtime,
config: cfg,
})
: [provider];
const resolveActiveSessionProviderForAuthProfile = (): string => {

View File

@@ -328,6 +328,7 @@ export async function createModelSelectionState(params: {
const acceptedAuthProviders = listOpenAIAuthProfileProvidersForAgentRuntime({
provider,
harnessRuntime: harnessPolicy.runtime,
config: cfg,
}).map(normalizeProviderId);
if (!profile || !acceptedAuthProviders.includes(profileProvider ?? "")) {
await clearSessionAuthProfileOverride({

View File

@@ -209,6 +209,22 @@ describe("models cli", () => {
});
});
it("maps --device-code to the provider device-code auth method", async () => {
await runModelsCommand([
"models",
"auth",
"login",
"--provider",
"openai-codex",
"--device-code",
]);
expectCommandOptions(modelsAuthLoginCommand, {
provider: "openai-codex",
method: "device-code",
});
});
it("passes list-specific --agent and --json to models auth list", async () => {
await runModelsCommand(["models", "auth", "list", "--agent", "poe", "--json"]);

View File

@@ -332,15 +332,21 @@ export function registerModelsCli(program: Command) {
.description("Run a provider plugin auth flow (OAuth/API key)")
.option("--provider <id>", "Provider id registered by a plugin")
.option("--method <id>", "Provider auth method id")
.option("--device-code", "Use the provider device-code auth method", false)
.option("--set-default", "Apply the provider's default model recommendation", false)
.action(async (opts, command) => {
if (opts.deviceCode && typeof opts.method === "string" && opts.method !== "device-code") {
throw new Error(
"--device-code cannot be combined with --method unless method is device-code.",
);
}
await withModelsRuntime(async ({ defaultRuntime, resolveModelAgentOption }) => {
const agent = resolveModelAgentOption(command);
const { modelsAuthLoginCommand } = await import("../commands/models/auth.js");
await modelsAuthLoginCommand(
{
provider: opts.provider as string | undefined,
method: opts.method as string | undefined,
method: opts.deviceCode ? "device-code" : (opts.method as string | undefined),
setDefault: Boolean(opts.setDefault),
agent,
},

View File

@@ -26,6 +26,7 @@ function resolveAuthProviderCandidates(params: {
...listOpenAIAuthProfileProvidersForAgentRuntime({
provider: params.provider,
harnessRuntime: harnessPolicy.runtime,
config: params.config,
}),
]),
];

View File

@@ -794,6 +794,7 @@ async function prepareCronRunContext(params: {
agentId,
sessionKey: agentSessionKey,
}).runtime,
config: cfgWithAgentDefaults,
}),
agentDir,
sessionEntry: cronSession.sessionEntry,

View File

@@ -11,6 +11,7 @@ import { resolveContextTokensForModel } from "../agents/context.js";
import { resolveFastModeState } from "../agents/fast-mode.js";
import { resolveModelAuthLabel } from "../agents/model-auth-label.js";
import { areRuntimeModelRefsEquivalent } from "../agents/model-runtime-aliases.js";
import { listOpenAIAuthProfileProvidersForAgentRuntime } from "../agents/openai-codex-routing.js";
import {
resolveInternalSessionKey,
resolveMainSessionAlias,
@@ -147,7 +148,7 @@ async function resolveStatusHarnessId(params: {
agentHarnessId: params.sessionEntry?.agentHarnessId,
});
const id = normalizeOptionalLowercaseString(selected.id);
return id && id !== "pi" ? id : undefined;
return id || undefined;
} catch {
return undefined;
}
@@ -234,15 +235,26 @@ export async function buildStatusText(params: BuildStatusTextParams): Promise<st
provider,
effectiveHarness,
});
const selectedAuthProviders = listOpenAIAuthProfileProvidersForAgentRuntime({
provider,
harnessRuntime: effectiveHarness,
config: cfg,
});
const activeProvider = modelRefs.active.provider || provider;
const activeStatusProvider = resolveStatusRuntimeProvider({
provider: activeProvider,
effectiveHarness,
});
const activeAuthProviders = listOpenAIAuthProfileProvidersForAgentRuntime({
provider: activeProvider,
harnessRuntime: effectiveHarness,
config: cfg,
});
let selectedModelAuth = Object.hasOwn(params, "modelAuthOverride")
? params.modelAuthOverride
: resolveModelAuthLabel({
provider: selectedStatusProvider,
acceptedProviderIds: selectedAuthProviders,
cfg,
sessionEntry,
agentDir: statusAgentDir,
@@ -254,6 +266,7 @@ export async function buildStatusText(params: BuildStatusTextParams): Promise<st
: modelRefs.activeDiffers
? resolveModelAuthLabel({
provider: activeStatusProvider,
acceptedProviderIds: activeAuthProviders,
cfg,
sessionEntry,
agentDir: statusAgentDir,