* 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
102 lines
2.2 KiB
TypeScript
102 lines
2.2 KiB
TypeScript
const SECRET_ENV_KEYS = [
|
|
'OPENAI_API_KEY',
|
|
'OPENAI_AUTH_HEADER_VALUE',
|
|
'CODEX_API_KEY',
|
|
'GEMINI_API_KEY',
|
|
'GOOGLE_API_KEY',
|
|
'MISTRAL_API_KEY',
|
|
'BNKR_API_KEY',
|
|
] as const
|
|
|
|
export type SecretValueSource = Partial<
|
|
Record<(typeof SECRET_ENV_KEYS)[number], string | undefined>
|
|
>
|
|
|
|
export function sanitizeApiKey(
|
|
key: string | null | undefined,
|
|
): string | undefined {
|
|
if (!key || key === 'SUA_CHAVE') return undefined
|
|
return key
|
|
}
|
|
|
|
function looksLikeSecretValue(value: string): boolean {
|
|
const trimmed = value.trim()
|
|
if (!trimmed) return false
|
|
|
|
if (trimmed.startsWith('sk-') || trimmed.startsWith('sk-ant-')) {
|
|
return true
|
|
}
|
|
|
|
if (trimmed.startsWith('AIza')) {
|
|
return true
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
function collectSecretValues(
|
|
sources: Array<SecretValueSource | null | undefined>,
|
|
): string[] {
|
|
const values = new Set<string>()
|
|
|
|
for (const source of sources) {
|
|
if (!source) continue
|
|
|
|
for (const key of SECRET_ENV_KEYS) {
|
|
const value = sanitizeApiKey(source[key])
|
|
if (value) {
|
|
values.add(value)
|
|
}
|
|
}
|
|
}
|
|
|
|
return [...values]
|
|
}
|
|
|
|
export function maskSecretForDisplay(
|
|
value: string | null | undefined,
|
|
): string | undefined {
|
|
const sanitized = sanitizeApiKey(value)
|
|
if (!sanitized) return undefined
|
|
|
|
if (sanitized.length <= 8) {
|
|
return 'configured'
|
|
}
|
|
|
|
return `${sanitized.slice(0, 3)}...${sanitized.slice(-3)}`
|
|
}
|
|
|
|
export function redactSecretValueForDisplay(
|
|
value: string | null | undefined,
|
|
...sources: Array<SecretValueSource | null | undefined>
|
|
): string | undefined {
|
|
if (!value) return undefined
|
|
|
|
const trimmed = value.trim()
|
|
if (!trimmed) return trimmed
|
|
|
|
const secretValues = collectSecretValues(sources)
|
|
if (secretValues.includes(trimmed) || looksLikeSecretValue(trimmed)) {
|
|
return maskSecretForDisplay(trimmed) ?? 'configured'
|
|
}
|
|
|
|
return trimmed
|
|
}
|
|
|
|
export function sanitizeProviderConfigValue(
|
|
value: string | null | undefined,
|
|
...sources: Array<SecretValueSource | null | undefined>
|
|
): string | undefined {
|
|
if (!value) return undefined
|
|
|
|
const trimmed = value.trim()
|
|
if (!trimmed) return undefined
|
|
|
|
const secretValues = collectSecretValues(sources)
|
|
if (secretValues.includes(trimmed) || looksLikeSecretValue(trimmed)) {
|
|
return undefined
|
|
}
|
|
|
|
return trimmed
|
|
}
|