From 16c325c8083696d74100c923854832062f6d10a3 Mon Sep 17 00:00:00 2001 From: Jiang Bohan Date: Fri, 13 Feb 2026 11:42:24 +0800 Subject: [PATCH 1/2] fix(oauth): don't expire OAuth credentials that have refresh_token Codex and Claude Code OAuth tokens with refresh_token can auto-renew, so they should not be considered expired based on last_refresh time or file mtime. Previously, credentials were hardcoded to expire after 1 hour, causing valid Codex sessions to show as unconfigured. Co-Authored-By: Claude Opus 4.6 --- .../agent/providers/oauth/cli-credentials.ts | 26 +++++++------------ 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/packages/core/src/agent/providers/oauth/cli-credentials.ts b/packages/core/src/agent/providers/oauth/cli-credentials.ts index 2d1da4e0..906d6943 100644 --- a/packages/core/src/agent/providers/oauth/cli-credentials.ts +++ b/packages/core/src/agent/providers/oauth/cli-credentials.ts @@ -176,7 +176,9 @@ export function readClaudeCliCredentials(): ClaudeCliCredential | null { export function hasValidClaudeCliCredentials(): boolean { const creds = readClaudeCliCredentials(); if (!creds) return false; - // Check if not expired (with 5 minute buffer) + // OAuth with refresh_token can auto-renew; always valid + if (creds.type === "oauth" && creds.refresh) return true; + // Token-only: check if not expired (with 5 minute buffer) return creds.expires > Date.now() + 5 * 60 * 1000; } @@ -214,14 +216,8 @@ function readCodexKeychainCredentials(): CodexCliCredential | null { if (typeof accessToken !== "string" || !accessToken) return null; if (typeof refreshToken !== "string" || !refreshToken) return null; - const lastRefreshRaw = parsed.last_refresh; - const lastRefresh = - typeof lastRefreshRaw === "string" || typeof lastRefreshRaw === "number" - ? new Date(lastRefreshRaw).getTime() - : Date.now(); - const expires = Number.isFinite(lastRefresh) - ? lastRefresh + 60 * 60 * 1000 - : Date.now() + 60 * 60 * 1000; + // OAuth with refresh_token can auto-renew; don't expire based on last_refresh + const expires = Infinity; return { type: "oauth", @@ -252,13 +248,8 @@ function readCodexFileCredentials(): CodexCliCredential | null { if (typeof accessToken !== "string" || !accessToken) return null; if (typeof refreshToken !== "string" || !refreshToken) return null; - let expires: number; - try { - const stat = fs.statSync(authPath); - expires = stat.mtimeMs + 60 * 60 * 1000; - } catch { - expires = Date.now() + 60 * 60 * 1000; - } + // OAuth with refresh_token can auto-renew; don't expire based on file mtime + const expires = Infinity; return { type: "oauth", @@ -292,6 +283,8 @@ export function readCodexCliCredentials(): CodexCliCredential | null { export function hasValidCodexCliCredentials(): boolean { const creds = readCodexCliCredentials(); if (!creds) return false; + // With refresh_token, credentials are always valid (auto-renew) + if (creds.refresh) return true; return creds.expires > Date.now() + 5 * 60 * 1000; } @@ -356,6 +349,7 @@ export function getCliCredentialStatus(): CliCredentialStatus[] { function formatDuration(ms: number): string { if (ms <= 0) return "expired"; + if (!Number.isFinite(ms)) return "never"; const hours = Math.floor(ms / (60 * 60 * 1000)); const minutes = Math.floor((ms % (60 * 60 * 1000)) / (60 * 1000)); if (hours > 0) return `${hours}h ${minutes}m`; From a490c737cc2af5589e121939f069ac2c83233901 Mon Sep 17 00:00:00 2001 From: Jiang Bohan Date: Fri, 13 Feb 2026 11:55:16 +0800 Subject: [PATCH 2/2] feat(providers): add gpt-5.3-codex and update OpenAI model lists Co-Authored-By: Claude Opus 4.6 --- packages/core/src/agent/providers/registry.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/core/src/agent/providers/registry.ts b/packages/core/src/agent/providers/registry.ts index 105a4190..b3455496 100644 --- a/packages/core/src/agent/providers/registry.ts +++ b/packages/core/src/agent/providers/registry.ts @@ -58,8 +58,8 @@ const PROVIDER_REGISTRY: Record = { id: "openai-codex", name: "Codex (OAuth)", authMethod: "oauth", - defaultModel: "gpt-5.2", - models: ["gpt-5.2", "gpt-5.2-codex", "gpt-5.1-codex", "gpt-5.1-codex-mini", "gpt-5.1-codex-max", "gpt-5-mini"], + defaultModel: "gpt-5.3-codex", + models: ["gpt-5.3-codex", "gpt-5.2-codex", "gpt-5.2", "gpt-5.1-codex-max", "gpt-5.1-codex-mini"], loginCommand: "codex login", }, "anthropic": { @@ -75,7 +75,7 @@ const PROVIDER_REGISTRY: Record = { name: "OpenAI", authMethod: "api-key", defaultModel: "gpt-4o", - models: ["gpt-5.2", "gpt-5-mini", "gpt-4.1", "gpt-4.1-mini", "gpt-4o", "gpt-4o-mini", "o3", "o3-mini"], + models: ["gpt-5.3-codex", "gpt-5.2", "gpt-5-mini", "gpt-4.1", "gpt-4.1-mini", "gpt-4o", "gpt-4o-mini", "o3", "o3-mini"], loginUrl: "https://platform.openai.com/api-keys", }, "kimi-coding": {