fix(proxy): support opt-in OpenAI reasoning shaping

This commit is contained in:
Tam Nhu Tran committed 2026-06-03 11:08:41 -04:00
1 parent 288ee71c82
commit 8282ff68a1
4 files changed
+158 -10

No files matched your search

+9 -3
View File
@@ -11,6 +11,7 @@ export interface OpenAICompatProfileConfig {
apiKey: string;
provider: DroidProvider;
insecure?: boolean;
forceOpenAIReasoningModel?: boolean;
model?: string;
opusModel?: string;
sonnetModel?: string;
@@ -28,12 +29,18 @@ export interface OpenAICompatProfileEnv {
ANTHROPIC_SMALL_FAST_MODEL?: string;
CCS_DROID_PROVIDER?: string;
CCS_OPENAI_PROXY_INSECURE?: string;
CCS_OPENAI_REASONING_MODEL?: string;
}
export function isOpenAICompatProvider(provider: DroidProvider | null): provider is DroidProvider {
return provider === 'openai' || provider === 'generic-chat-completion-api';
}
function isTruthyEnv(value: string | undefined): boolean {
const normalized = value?.trim().toLowerCase();
return normalized === '1' || normalized === 'true' || normalized === 'yes' || normalized === 'on';
}
export function resolveOpenAICompatProfileConfig(
profileName: string,
settingsPath: string,
@@ -63,9 +70,8 @@ export function resolveOpenAICompatProfileConfig(
baseUrl,
apiKey,
provider,
insecure:
env.CCS_OPENAI_PROXY_INSECURE === '1' ||
env.CCS_OPENAI_PROXY_INSECURE?.toLowerCase() === 'true',
insecure: isTruthyEnv(env.CCS_OPENAI_PROXY_INSECURE),
forceOpenAIReasoningModel: isTruthyEnv(env.CCS_OPENAI_REASONING_MODEL),
model: env.ANTHROPIC_MODEL?.trim() || undefined,
opusModel: env.ANTHROPIC_DEFAULT_OPUS_MODEL?.trim() || undefined,
sonnetModel: env.ANTHROPIC_DEFAULT_SONNET_MODEL?.trim() || undefined,
+13 -7
View File
@@ -31,15 +31,21 @@ function buildUpstreamHeaders(profile: OpenAICompatProfileConfig): Record<string
};
}
function isDirectOpenAIReasoningChatModel(
function isKnownOpenAIReasoningChatModel(model: string | undefined): boolean {
if (typeof model !== 'string') {
return false;
}
const normalized = model.trim().toLowerCase();
const modelName = normalized.split('/').pop() || normalized;
return DIRECT_OPENAI_REASONING_CHAT_MODEL.test(modelName);
}
function shouldShapeOpenAIReasoningChatPayload(
profile: OpenAICompatProfileConfig,
model: string | undefined
): boolean {
return (
profile.provider === 'openai' &&
typeof model === 'string' &&
DIRECT_OPENAI_REASONING_CHAT_MODEL.test(model.trim().toLowerCase())
);
return profile.forceOpenAIReasoningModel === true || isKnownOpenAIReasoningChatModel(model);
}
function isMiniMaxOpenAICompatProfile(profile: OpenAICompatProfileConfig): boolean {
@@ -124,7 +130,7 @@ function shapeUpstreamChatPayload(
shaped = shapeMiniMaxChatPayload(shaped);
}
if (!isDirectOpenAIReasoningChatModel(profile, shaped.model)) {
if (!shouldShapeOpenAIReasoningChatPayload(profile, shaped.model)) {
return shaped;
}