feat: /login支持codex订阅登录

This commit is contained in:
Bill
2026-05-08 20:35:34 +08:00
parent 73e54d4bbc
commit c7cb3d8f93
17 changed files with 1318 additions and 39 deletions

View File

@@ -9,6 +9,10 @@ import { isEnvTruthy } from './envUtils.js'
import type { EffortLevel } from 'src/entrypoints/sdk/runtimeTypes.js'
import { resolveAntModel } from './model/antModels.js'
import { getAntModelOverrideConfig } from './model/antModels.js'
import {
isChatGPTAuthMode,
isChatGPTCodexReasoningModel,
} from './model/chatgptModels.js'
export type { EffortLevel }
@@ -32,6 +36,13 @@ export function modelSupportsEffort(model: string): boolean {
if (supported3P !== undefined) {
return supported3P
}
if (
getAPIProvider() === 'openai' &&
isChatGPTAuthMode() &&
isChatGPTCodexReasoningModel(model)
) {
return true
}
// Supported by a subset of Claude 4 models
if (
m.includes('opus-4-7') ||
@@ -87,6 +98,13 @@ export function modelSupportsXhighEffort(model: string): boolean {
if (supported3P !== undefined) {
return supported3P
}
if (
getAPIProvider() === 'openai' &&
isChatGPTAuthMode() &&
isChatGPTCodexReasoningModel(model)
) {
return true
}
if (model.toLowerCase().includes('opus-4-7')) {
return true
}
@@ -200,6 +218,16 @@ export function resolveAppliedEffort(
if (resolved === 'xhigh' && !modelSupportsXhighEffort(model)) {
return 'high'
}
// OpenAI Responses uses xhigh as its highest public reasoning effort.
// Keep /effort max usable as a familiar alias in ChatGPT subscription mode.
if (
resolved === 'max' &&
getAPIProvider() === 'openai' &&
isChatGPTAuthMode() &&
modelSupportsXhighEffort(model)
) {
return 'xhigh'
}
// API rejects 'max' on non-Opus-4.6 models — downgrade to 'high'.
if (resolved === 'max' && !modelSupportsMaxEffort(model)) {
return 'high'
@@ -347,6 +375,14 @@ export function getDefaultEffortForModel(
// the model launch DRI and research. Default effort is a sensitive setting
// that can greatly affect model quality and bashing.
if (
getAPIProvider() === 'openai' &&
isChatGPTAuthMode() &&
isChatGPTCodexReasoningModel(model)
) {
return 'medium'
}
// Default effort on Opus 4.6 to medium for Pro.
// Max/Team also get medium when the tengu_grey_step2 config is enabled.
if (

View File

@@ -12,7 +12,7 @@
* config vars (endpoint, project, region, auth) do.
*
* Note: OpenAI provider uses OPENAI_* env vars (OPENAI_API_KEY, OPENAI_BASE_URL,
* OPENAI_MODEL, OPENAI_DEFAULT_*_MODEL, OPENAI_SMALL_FAST_MODEL) which are all
* OPENAI_MODEL, OPENAI_AUTH_MODE, OPENAI_DEFAULT_*_MODEL, OPENAI_SMALL_FAST_MODEL) which are all
* provider-managed to keep routing config isolated from Anthropic settings.
*/
const PROVIDER_MANAGED_ENV_VARS = new Set([
@@ -58,6 +58,7 @@ const PROVIDER_MANAGED_ENV_VARS = new Set([
'ANTHROPIC_DEFAULT_SONNET_MODEL_NAME',
'ANTHROPIC_DEFAULT_SONNET_MODEL_SUPPORTED_CAPABILITIES',
// OpenAI provider specific
'OPENAI_AUTH_MODE',
'OPENAI_API_KEY',
'OPENAI_BASE_URL',
'OPENAI_MODEL',

View File

@@ -0,0 +1,52 @@
export type ChatGPTCodexModelOption = {
value: string
label: string
description: string
}
export const CHATGPT_CODEX_DEFAULT_MODEL = 'gpt-5.5'
export const CHATGPT_CODEX_FAST_MODEL = 'gpt-5.4-mini'
export const CHATGPT_CODEX_MODEL_OPTIONS: ChatGPTCodexModelOption[] = [
{
value: 'gpt-5.5',
label: 'GPT-5.5',
description: 'Frontier model for complex coding, research, and real-world work',
},
{
value: 'gpt-5.4',
label: 'GPT-5.4',
description: 'Strong model for everyday coding',
},
{
value: 'gpt-5.4-mini',
label: 'GPT-5.4-Mini',
description: 'Small, fast, and cost-efficient model for simpler coding tasks',
},
{
value: 'gpt-5.3-codex',
label: 'GPT-5.3-Codex',
description: 'Coding-optimized model',
},
{
value: 'gpt-5.3-codex-spark',
label: 'GPT-5.3-Codex-Spark',
description: 'Ultra-fast coding model',
},
{
value: 'gpt-5.2',
label: 'GPT-5.2',
description: 'Optimized for professional work and long-running agents',
},
]
export function isChatGPTAuthMode(): boolean {
return process.env.OPENAI_AUTH_MODE === 'chatgpt'
}
export function isChatGPTCodexReasoningModel(model: string): boolean {
const normalized = model.toLowerCase().replace(/\[1m\]$/, '')
return CHATGPT_CODEX_MODEL_OPTIONS.some(
option => option.value.toLowerCase() === normalized,
)
}

View File

@@ -29,6 +29,11 @@ import { LIGHTNING_BOLT } from '../../constants/figures.js'
import { isModelAllowed } from './modelAllowlist.js'
import { type ModelAlias, isModelAlias } from './aliases.js'
import { capitalize } from '../stringUtils.js'
import {
CHATGPT_CODEX_DEFAULT_MODEL,
CHATGPT_CODEX_FAST_MODEL,
isChatGPTAuthMode,
} from './chatgptModels.js'
export type ModelShortName = string
export type ModelName = string
@@ -36,6 +41,9 @@ export type ModelSetting = ModelName | ModelAlias | null
export function getSmallFastModel(): ModelName {
const provider = getAPIProvider()
if (provider === 'openai' && isChatGPTAuthMode()) {
return process.env.OPENAI_SMALL_FAST_MODEL ?? CHATGPT_CODEX_FAST_MODEL
}
// Provider-specific small fast model
if (provider === 'openai' && process.env.OPENAI_SMALL_FAST_MODEL) {
return process.env.OPENAI_SMALL_FAST_MODEL
@@ -115,6 +123,9 @@ export function getBestModel(): ModelName {
// @[MODEL LAUNCH]: Update the default Opus model (3P providers may lag so keep defaults unchanged).
export function getDefaultOpusModel(): ModelName {
const provider = getAPIProvider()
if (provider === 'openai' && isChatGPTAuthMode()) {
return CHATGPT_CODEX_DEFAULT_MODEL
}
// For OpenAI provider, check OPENAI_DEFAULT_OPUS_MODEL first
if (provider === 'openai' && process.env.OPENAI_DEFAULT_OPUS_MODEL) {
return process.env.OPENAI_DEFAULT_OPUS_MODEL
@@ -140,6 +151,9 @@ export function getDefaultOpusModel(): ModelName {
// @[MODEL LAUNCH]: Update the default Sonnet model (3P providers may lag so keep defaults unchanged).
export function getDefaultSonnetModel(): ModelName {
const provider = getAPIProvider()
if (provider === 'openai' && isChatGPTAuthMode()) {
return CHATGPT_CODEX_DEFAULT_MODEL
}
// For OpenAI provider, check OPENAI_DEFAULT_SONNET_MODEL first
if (provider === 'openai' && process.env.OPENAI_DEFAULT_SONNET_MODEL) {
return process.env.OPENAI_DEFAULT_SONNET_MODEL
@@ -162,6 +176,9 @@ export function getDefaultSonnetModel(): ModelName {
// @[MODEL LAUNCH]: Update the default Haiku model (3P providers may lag so keep defaults unchanged).
export function getDefaultHaikuModel(): ModelName {
const provider = getAPIProvider()
if (provider === 'openai' && isChatGPTAuthMode()) {
return CHATGPT_CODEX_FAST_MODEL
}
// For OpenAI provider, check OPENAI_DEFAULT_HAIKU_MODEL first
if (provider === 'openai' && process.env.OPENAI_DEFAULT_HAIKU_MODEL) {
return process.env.OPENAI_DEFAULT_HAIKU_MODEL

View File

@@ -33,6 +33,11 @@ import {
} from './model.js'
import { has1mContext } from '../context.js'
import { getGlobalConfig } from '../config.js'
import {
CHATGPT_CODEX_DEFAULT_MODEL,
CHATGPT_CODEX_MODEL_OPTIONS,
isChatGPTAuthMode,
} from './chatgptModels.js'
// @[MODEL LAUNCH]: Update all the available and default model option strings below.
@@ -336,6 +341,23 @@ function getOpusPlanOption(): ModelOption {
}
}
function getChatGPTCodexModelOptions(): ModelOption[] {
return [
{
value: null,
label: 'Default (recommended)',
description: `Use the default ChatGPT Codex model (currently ${CHATGPT_CODEX_DEFAULT_MODEL})`,
descriptionForModel: `Default ChatGPT Codex model (currently ${CHATGPT_CODEX_DEFAULT_MODEL})`,
},
...CHATGPT_CODEX_MODEL_OPTIONS.map(model => ({
value: model.value,
label: model.label,
description: model.description,
descriptionForModel: `${model.description} (${model.value})`,
})),
]
}
// @[MODEL LAUNCH]: Update the model picker lists below to include/reorder options for the new model.
// Each user tier (ant, Max/Team Premium, Pro/Team Standard/Enterprise, PAYG 1P, PAYG 3P) has its own list.
function getModelOptionsBase(fastMode = false): ModelOption[] {
@@ -357,6 +379,10 @@ function getModelOptionsBase(fastMode = false): ModelOption[] {
]
}
if (getAPIProvider() === 'openai' && isChatGPTAuthMode()) {
return getChatGPTCodexModelOptions()
}
if (isClaudeAISubscriber()) {
if (isMaxSubscriber() || isTeamPremiumSubscriber()) {
// Max and Team Premium users: Default = Opus 4.7 1M (merged), plus Opus 4.6 1M