Add OpenAI responses mode and custom auth headers (#906)
* Add OpenAI profile responses and custom auth header support * Fix knowledge graph config reference in query loop * Address OpenAI profile review edge cases * Remove unused getGlobalConfig import Delete an unused import of getGlobalConfig from src/query.ts. This cleans up dead code and avoids unused-import lint warnings; no functional behavior changes. * Address follow-up OpenAI profile review comments * Refine OpenAI responses auth review fixes * Fix custom auth header default scheme
This commit is contained in:
@@ -52,6 +52,10 @@ const PROFILE_ENV_KEYS = [
|
||||
'CLAUDE_CODE_USE_FOUNDRY',
|
||||
'OPENAI_BASE_URL',
|
||||
'OPENAI_MODEL',
|
||||
'OPENAI_API_FORMAT',
|
||||
'OPENAI_AUTH_HEADER',
|
||||
'OPENAI_AUTH_SCHEME',
|
||||
'OPENAI_AUTH_HEADER_VALUE',
|
||||
'OPENAI_API_KEY',
|
||||
'CODEX_API_KEY',
|
||||
'CODEX_CREDENTIAL_SOURCE',
|
||||
@@ -79,6 +83,7 @@ const PROFILE_ENV_KEYS = [
|
||||
|
||||
const SECRET_ENV_KEYS = [
|
||||
'OPENAI_API_KEY',
|
||||
'OPENAI_AUTH_HEADER_VALUE',
|
||||
'CODEX_API_KEY',
|
||||
'GEMINI_API_KEY',
|
||||
'GOOGLE_API_KEY',
|
||||
@@ -93,6 +98,10 @@ export type ProviderProfile = 'openai' | 'ollama' | 'codex' | 'gemini' | 'atomic
|
||||
export type ProfileEnv = {
|
||||
OPENAI_BASE_URL?: string
|
||||
OPENAI_MODEL?: string
|
||||
OPENAI_API_FORMAT?: 'chat_completions' | 'responses'
|
||||
OPENAI_AUTH_HEADER?: string
|
||||
OPENAI_AUTH_SCHEME?: 'bearer' | 'raw'
|
||||
OPENAI_AUTH_HEADER_VALUE?: string
|
||||
OPENAI_API_KEY?: string
|
||||
CODEX_API_KEY?: string
|
||||
CODEX_CREDENTIAL_SOURCE?: 'oauth' | 'existing'
|
||||
@@ -125,6 +134,7 @@ export type ProfileFile = {
|
||||
type SecretValueSource = Partial<
|
||||
Record<
|
||||
| 'OPENAI_API_KEY'
|
||||
| 'OPENAI_AUTH_HEADER_VALUE'
|
||||
| 'CODEX_API_KEY'
|
||||
| 'GEMINI_API_KEY'
|
||||
| 'GOOGLE_API_KEY'
|
||||
@@ -320,16 +330,26 @@ export function buildOpenAIProfileEnv(options: {
|
||||
model?: string | null
|
||||
baseUrl?: string | null
|
||||
apiKey?: string | null
|
||||
apiFormat?: 'chat_completions' | 'responses' | null
|
||||
authHeader?: string | null
|
||||
authScheme?: 'bearer' | 'raw' | null
|
||||
authHeaderValue?: string | null
|
||||
processEnv?: NodeJS.ProcessEnv
|
||||
}): ProfileEnv | null {
|
||||
const processEnv = options.processEnv ?? process.env
|
||||
const key = sanitizeApiKey(options.apiKey ?? processEnv.OPENAI_API_KEY)
|
||||
if (!key) {
|
||||
const authHeaderValue = sanitizeApiKey(
|
||||
options.authHeaderValue ?? processEnv.OPENAI_AUTH_HEADER_VALUE,
|
||||
)
|
||||
if (!key && !authHeaderValue) {
|
||||
return null
|
||||
}
|
||||
|
||||
const defaultModel = getGoalDefaultOpenAIModel(options.goal)
|
||||
const secretSource: SecretValueSource = { OPENAI_API_KEY: key }
|
||||
const secretSource: SecretValueSource = {
|
||||
OPENAI_API_KEY: key,
|
||||
OPENAI_AUTH_HEADER_VALUE: authHeaderValue,
|
||||
}
|
||||
const shellOpenAIModel = normalizeProfileModel(
|
||||
sanitizeProviderConfigValue(
|
||||
processEnv.OPENAI_MODEL,
|
||||
@@ -344,8 +364,9 @@ export function buildOpenAIProfileEnv(options: {
|
||||
model: shellOpenAIModel,
|
||||
baseUrl: shellOpenAIBaseUrl,
|
||||
fallbackModel: defaultModel,
|
||||
apiFormat: processEnv.OPENAI_API_FORMAT,
|
||||
})
|
||||
const useShellOpenAIConfig = shellOpenAIRequest.transport === 'chat_completions'
|
||||
const useShellOpenAIConfig = shellOpenAIRequest.transport !== 'codex_responses'
|
||||
|
||||
return {
|
||||
OPENAI_BASE_URL:
|
||||
@@ -358,7 +379,11 @@ export function buildOpenAIProfileEnv(options: {
|
||||
) ||
|
||||
(useShellOpenAIConfig ? shellOpenAIModel : undefined) ||
|
||||
defaultModel,
|
||||
OPENAI_API_KEY: key,
|
||||
...(options.apiFormat ? { OPENAI_API_FORMAT: options.apiFormat } : {}),
|
||||
...(options.authHeader ? { OPENAI_AUTH_HEADER: options.authHeader } : {}),
|
||||
...(options.authScheme ? { OPENAI_AUTH_SCHEME: options.authScheme } : {}),
|
||||
...(authHeaderValue ? { OPENAI_AUTH_HEADER_VALUE: authHeaderValue } : {}),
|
||||
...(key ? { OPENAI_API_KEY: key } : {}),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -622,6 +647,12 @@ export async function buildLaunchEnv(options: {
|
||||
persistedEnv.OPENAI_BASE_URL,
|
||||
persistedEnv,
|
||||
)
|
||||
const persistedOpenAIApiFormat = persistedEnv.OPENAI_API_FORMAT
|
||||
const persistedOpenAIAuthHeader = persistedEnv.OPENAI_AUTH_HEADER
|
||||
const persistedOpenAIAuthScheme = persistedEnv.OPENAI_AUTH_SCHEME
|
||||
const persistedOpenAIAuthHeaderValue = sanitizeApiKey(
|
||||
persistedEnv.OPENAI_AUTH_HEADER_VALUE,
|
||||
)
|
||||
const shellOpenAIModel = normalizeProfileModel(
|
||||
sanitizeProviderConfigValue(
|
||||
processEnv.OPENAI_MODEL,
|
||||
@@ -723,6 +754,10 @@ export async function buildLaunchEnv(options: {
|
||||
delete env.GOOGLE_API_KEY
|
||||
delete env.OPENAI_BASE_URL
|
||||
delete env.OPENAI_MODEL
|
||||
delete env.OPENAI_API_FORMAT
|
||||
delete env.OPENAI_AUTH_HEADER
|
||||
delete env.OPENAI_AUTH_SCHEME
|
||||
delete env.OPENAI_AUTH_HEADER_VALUE
|
||||
delete env.OPENAI_API_KEY
|
||||
delete env.CODEX_API_KEY
|
||||
delete env.CHATGPT_ACCOUNT_ID
|
||||
@@ -790,6 +825,10 @@ export async function buildLaunchEnv(options: {
|
||||
delete env.GOOGLE_API_KEY
|
||||
delete env.OPENAI_BASE_URL
|
||||
delete env.OPENAI_MODEL
|
||||
delete env.OPENAI_API_FORMAT
|
||||
delete env.OPENAI_AUTH_HEADER
|
||||
delete env.OPENAI_AUTH_SCHEME
|
||||
delete env.OPENAI_AUTH_HEADER_VALUE
|
||||
delete env.OPENAI_API_KEY
|
||||
delete env.CODEX_API_KEY
|
||||
delete env.CHATGPT_ACCOUNT_ID
|
||||
@@ -829,6 +868,10 @@ export async function buildLaunchEnv(options: {
|
||||
(await resolveOllamaModel(options.goal))
|
||||
|
||||
delete env.OPENAI_API_KEY
|
||||
delete env.OPENAI_API_FORMAT
|
||||
delete env.OPENAI_AUTH_HEADER
|
||||
delete env.OPENAI_AUTH_SCHEME
|
||||
delete env.OPENAI_AUTH_HEADER_VALUE
|
||||
delete env.CODEX_API_KEY
|
||||
delete env.CHATGPT_ACCOUNT_ID
|
||||
delete env.CODEX_ACCOUNT_ID
|
||||
@@ -849,6 +892,10 @@ export async function buildLaunchEnv(options: {
|
||||
''
|
||||
|
||||
delete env.OPENAI_API_KEY
|
||||
delete env.OPENAI_API_FORMAT
|
||||
delete env.OPENAI_AUTH_HEADER
|
||||
delete env.OPENAI_AUTH_SCHEME
|
||||
delete env.OPENAI_AUTH_HEADER_VALUE
|
||||
delete env.CODEX_API_KEY
|
||||
delete env.CHATGPT_ACCOUNT_ID
|
||||
delete env.CODEX_ACCOUNT_ID
|
||||
@@ -863,6 +910,10 @@ export async function buildLaunchEnv(options: {
|
||||
: DEFAULT_CODEX_BASE_URL
|
||||
env.OPENAI_MODEL = persistedOpenAIModel || 'codexplan'
|
||||
delete env.OPENAI_API_KEY
|
||||
delete env.OPENAI_API_FORMAT
|
||||
delete env.OPENAI_AUTH_HEADER
|
||||
delete env.OPENAI_AUTH_SCHEME
|
||||
delete env.OPENAI_AUTH_HEADER_VALUE
|
||||
|
||||
const codexKey =
|
||||
sanitizeApiKey(processEnv.CODEX_API_KEY) ||
|
||||
@@ -895,16 +946,18 @@ export async function buildLaunchEnv(options: {
|
||||
model: shellOpenAIModel,
|
||||
baseUrl: shellOpenAIBaseUrl,
|
||||
fallbackModel: defaultOpenAIModel,
|
||||
apiFormat: processEnv.OPENAI_API_FORMAT,
|
||||
})
|
||||
const persistedOpenAIRequest = resolveProviderRequest({
|
||||
model: persistedOpenAIModel,
|
||||
baseUrl: persistedOpenAIBaseUrl,
|
||||
fallbackModel: defaultOpenAIModel,
|
||||
apiFormat: persistedOpenAIApiFormat,
|
||||
})
|
||||
const useShellOpenAIConfig = shellOpenAIRequest.transport === 'chat_completions'
|
||||
const useShellOpenAIConfig = shellOpenAIRequest.transport !== 'codex_responses'
|
||||
const usePersistedOpenAIConfig =
|
||||
(!persistedOpenAIModel && !persistedOpenAIBaseUrl) ||
|
||||
persistedOpenAIRequest.transport === 'chat_completions'
|
||||
persistedOpenAIRequest.transport !== 'codex_responses'
|
||||
|
||||
env.OPENAI_BASE_URL =
|
||||
(useShellOpenAIConfig ? shellOpenAIBaseUrl : undefined) ||
|
||||
@@ -914,6 +967,38 @@ export async function buildLaunchEnv(options: {
|
||||
(useShellOpenAIConfig ? shellOpenAIModel : undefined) ||
|
||||
(usePersistedOpenAIConfig ? persistedOpenAIModel : undefined) ||
|
||||
defaultOpenAIModel
|
||||
const openAIApiFormat =
|
||||
processEnv.OPENAI_API_FORMAT ||
|
||||
(usePersistedOpenAIConfig ? persistedOpenAIApiFormat : undefined)
|
||||
if (openAIApiFormat) {
|
||||
env.OPENAI_API_FORMAT = openAIApiFormat
|
||||
} else {
|
||||
delete env.OPENAI_API_FORMAT
|
||||
}
|
||||
const openAIAuthHeader =
|
||||
processEnv.OPENAI_AUTH_HEADER ||
|
||||
(usePersistedOpenAIConfig ? persistedOpenAIAuthHeader : undefined)
|
||||
if (openAIAuthHeader) {
|
||||
env.OPENAI_AUTH_HEADER = openAIAuthHeader
|
||||
} else {
|
||||
delete env.OPENAI_AUTH_HEADER
|
||||
}
|
||||
const openAIAuthScheme =
|
||||
processEnv.OPENAI_AUTH_SCHEME ||
|
||||
(usePersistedOpenAIConfig ? persistedOpenAIAuthScheme : undefined)
|
||||
if (openAIAuthScheme) {
|
||||
env.OPENAI_AUTH_SCHEME = openAIAuthScheme
|
||||
} else {
|
||||
delete env.OPENAI_AUTH_SCHEME
|
||||
}
|
||||
const openAIAuthHeaderValue =
|
||||
sanitizeApiKey(processEnv.OPENAI_AUTH_HEADER_VALUE) ||
|
||||
(usePersistedOpenAIConfig ? persistedOpenAIAuthHeaderValue : undefined)
|
||||
if (openAIAuthHeaderValue) {
|
||||
env.OPENAI_AUTH_HEADER_VALUE = openAIAuthHeaderValue
|
||||
} else {
|
||||
delete env.OPENAI_AUTH_HEADER_VALUE
|
||||
}
|
||||
const openAIKey = processEnv.OPENAI_API_KEY || persistedEnv.OPENAI_API_KEY
|
||||
if (openAIKey) {
|
||||
env.OPENAI_API_KEY = openAIKey
|
||||
|
||||
Reference in New Issue
Block a user