Merge origin/main into codex/provider-profile-recommendations

Preserve provider recommendation workflows while integrating Codex profile support, safer launch isolation, and updated docs/scripts from upstream main.
This commit is contained in:
Vasanthdev2004
2026-04-01 17:33:07 +05:30
21 changed files with 2141 additions and 188 deletions

View File

@@ -1,14 +1,24 @@
import {
DEFAULT_CODEX_BASE_URL,
DEFAULT_OPENAI_BASE_URL,
isCodexBaseUrl,
resolveCodexApiCredentials,
resolveProviderRequest,
} from '../services/api/providerConfig.ts'
import {
getGoalDefaultOpenAIModel,
type RecommendationGoal,
} from './providerRecommendation.ts'
export type ProviderProfile = 'openai' | 'ollama'
export type ProviderProfile = 'openai' | 'ollama' | 'codex'
export type ProfileEnv = {
OPENAI_BASE_URL?: string
OPENAI_MODEL?: string
OPENAI_API_KEY?: string
CODEX_API_KEY?: string
CHATGPT_ACCOUNT_ID?: string
CODEX_ACCOUNT_ID?: string
}
export type ProfileFile = {
@@ -40,6 +50,7 @@ export function buildOllamaProfileEnv(
export function buildOpenAIProfileEnv(options: {
goal: RecommendationGoal
model?: string | null
baseUrl?: string | null
apiKey?: string | null
processEnv?: NodeJS.ProcessEnv
}): ProfileEnv | null {
@@ -49,13 +60,57 @@ export function buildOpenAIProfileEnv(options: {
return null
}
const defaultModel = getGoalDefaultOpenAIModel(options.goal)
const shellOpenAIRequest = resolveProviderRequest({
model: processEnv.OPENAI_MODEL,
baseUrl: processEnv.OPENAI_BASE_URL,
fallbackModel: defaultModel,
})
const useShellOpenAIConfig = shellOpenAIRequest.transport === 'chat_completions'
return {
OPENAI_BASE_URL: processEnv.OPENAI_BASE_URL || 'https://api.openai.com/v1',
OPENAI_MODEL: options.model || getGoalDefaultOpenAIModel(options.goal),
OPENAI_BASE_URL:
options.baseUrl ||
(useShellOpenAIConfig ? processEnv.OPENAI_BASE_URL : undefined) ||
DEFAULT_OPENAI_BASE_URL,
OPENAI_MODEL:
options.model ||
(useShellOpenAIConfig ? processEnv.OPENAI_MODEL : undefined) ||
defaultModel,
OPENAI_API_KEY: key,
}
}
export function buildCodexProfileEnv(options: {
model?: string | null
baseUrl?: string | null
apiKey?: string | null
processEnv?: NodeJS.ProcessEnv
}): ProfileEnv | null {
const processEnv = options.processEnv ?? process.env
const key = sanitizeApiKey(options.apiKey ?? processEnv.CODEX_API_KEY)
const credentialEnv = key
? ({ ...processEnv, CODEX_API_KEY: key } as NodeJS.ProcessEnv)
: processEnv
const credentials = resolveCodexApiCredentials(credentialEnv)
if (!credentials.apiKey || !credentials.accountId) {
return null
}
const env: ProfileEnv = {
OPENAI_BASE_URL: options.baseUrl || DEFAULT_CODEX_BASE_URL,
OPENAI_MODEL: options.model || 'codexplan',
}
if (key) {
env.CODEX_API_KEY = key
}
env.CHATGPT_ACCOUNT_ID = credentials.accountId
return env
}
export function createProfileFile(
profile: ProviderProfile,
env: ProfileEnv,
@@ -103,21 +158,75 @@ export async function buildLaunchEnv(options: {
persistedEnv.OPENAI_MODEL ||
(await resolveOllamaModel(options.goal))
if (!processEnv.OPENAI_API_KEY || processEnv.OPENAI_API_KEY === 'SUA_CHAVE') {
delete env.OPENAI_API_KEY
}
delete env.OPENAI_API_KEY
delete env.CODEX_API_KEY
delete env.CHATGPT_ACCOUNT_ID
delete env.CODEX_ACCOUNT_ID
return env
}
if (options.profile === 'codex') {
env.OPENAI_BASE_URL =
persistedEnv.OPENAI_BASE_URL && isCodexBaseUrl(persistedEnv.OPENAI_BASE_URL)
? persistedEnv.OPENAI_BASE_URL
: DEFAULT_CODEX_BASE_URL
env.OPENAI_MODEL = persistedEnv.OPENAI_MODEL || 'codexplan'
delete env.OPENAI_API_KEY
const codexKey =
sanitizeApiKey(processEnv.CODEX_API_KEY) ||
sanitizeApiKey(persistedEnv.CODEX_API_KEY)
const liveCodexCredentials = resolveCodexApiCredentials(processEnv)
const codexAccountId =
processEnv.CHATGPT_ACCOUNT_ID ||
processEnv.CODEX_ACCOUNT_ID ||
liveCodexCredentials.accountId ||
persistedEnv.CHATGPT_ACCOUNT_ID ||
persistedEnv.CODEX_ACCOUNT_ID
if (codexKey) {
env.CODEX_API_KEY = codexKey
} else {
delete env.CODEX_API_KEY
}
if (codexAccountId) {
env.CHATGPT_ACCOUNT_ID = codexAccountId
} else {
delete env.CHATGPT_ACCOUNT_ID
}
delete env.CODEX_ACCOUNT_ID
return env
}
const defaultOpenAIModel = getGoalDefaultOpenAIModel(options.goal)
const shellOpenAIRequest = resolveProviderRequest({
model: processEnv.OPENAI_MODEL,
baseUrl: processEnv.OPENAI_BASE_URL,
fallbackModel: defaultOpenAIModel,
})
const persistedOpenAIRequest = resolveProviderRequest({
model: persistedEnv.OPENAI_MODEL,
baseUrl: persistedEnv.OPENAI_BASE_URL,
fallbackModel: defaultOpenAIModel,
})
const useShellOpenAIConfig = shellOpenAIRequest.transport === 'chat_completions'
const usePersistedOpenAIConfig =
(!persistedEnv.OPENAI_MODEL && !persistedEnv.OPENAI_BASE_URL) ||
persistedOpenAIRequest.transport === 'chat_completions'
env.OPENAI_BASE_URL =
processEnv.OPENAI_BASE_URL ||
persistedEnv.OPENAI_BASE_URL ||
'https://api.openai.com/v1'
(useShellOpenAIConfig ? processEnv.OPENAI_BASE_URL : undefined) ||
(usePersistedOpenAIConfig ? persistedEnv.OPENAI_BASE_URL : undefined) ||
DEFAULT_OPENAI_BASE_URL
env.OPENAI_MODEL =
processEnv.OPENAI_MODEL ||
persistedEnv.OPENAI_MODEL ||
getGoalDefaultOpenAIModel(options.goal)
(useShellOpenAIConfig ? processEnv.OPENAI_MODEL : undefined) ||
(usePersistedOpenAIConfig ? persistedEnv.OPENAI_MODEL : undefined) ||
defaultOpenAIModel
env.OPENAI_API_KEY = processEnv.OPENAI_API_KEY || persistedEnv.OPENAI_API_KEY
delete env.CODEX_API_KEY
delete env.CHATGPT_ACCOUNT_ID
delete env.CODEX_ACCOUNT_ID
return env
}