feat(ai): AI model handling with reasoning support (#8539)

This commit is contained in:
naman-bruno
2026-07-08 22:04:35 +05:30
committed by GitHub
parent 7ce3bf431f
commit 12961db95d
4 changed files with 31 additions and 8 deletions

View File

@@ -245,6 +245,7 @@ const registerChatIpc = ({ mainWindow, resolveModel, pickDefaultModelId, isAiEna
abortSignal: controller.signal
});
let streamError = null;
for await (const part of result.fullStream) {
if (controller.signal.aborted) break;
switch (part.type) {
@@ -271,11 +272,17 @@ const registerChatIpc = ({ mainWindow, resolveModel, pickDefaultModelId, isAiEna
send('main:ai-chat-tool-done', { requestId, toolName: part.toolName });
break;
}
case 'error': {
streamError = part.error;
break;
}
default:
break;
}
}
if (streamError) throw streamError;
activeStreams.delete(requestId);
if (controller.signal.aborted) {

View File

@@ -12,6 +12,7 @@ const {
clearSdkCache,
isKnownProviderId,
isBuiltInModelId,
isReasoningModel,
validateApiKeyForProvider,
providerLabel
} = require('./providers');
@@ -162,7 +163,7 @@ const registerAiIpc = (mainWindow) => {
system,
prompt,
maxOutputTokens: maxTokens ?? 1024,
temperature: temperature ?? 0.3
...(isReasoningModel(modelId) ? {} : { temperature: temperature ?? 0.3 })
});
return { text };
} catch (err) {
@@ -344,7 +345,7 @@ const registerAiIpc = (mainWindow) => {
model,
system,
maxOutputTokens: maxTokens ?? 2048,
temperature: temperature ?? 0.7,
...(isReasoningModel(modelId) ? {} : { temperature: temperature ?? 0.7 }),
abortSignal: controller.signal
};
if (messages) {

View File

@@ -40,16 +40,27 @@ const PROVIDERS = {
* Static model catalog for built-in providers. User-defined custom models for
* OpenAI-compatible endpoints are layered on top at lookup time.
*/
// `reasoning: true` marks models whose SDK path rejects temperature/stopSequences
// (OpenAI Responses API reasoning models) or accepts them only when thinking is
// off (Anthropic Claude 4+). Callers doing latency-critical work like
// autocomplete drop those params for reasoning models to silence warnings.
const MODEL_DEFINITIONS = {
// OpenAI
'gpt-4o-mini': { provider: 'openai', modelId: 'gpt-4o-mini', label: 'GPT-4o Mini' },
'gpt-4o': { provider: 'openai', modelId: 'gpt-4o', label: 'GPT-4o' },
'gpt-5': { provider: 'openai', modelId: 'gpt-5', label: 'GPT-5' },
'gpt-5-mini': { provider: 'openai', modelId: 'gpt-5-mini', label: 'GPT-5 Mini' },
'gpt-5': { provider: 'openai', modelId: 'gpt-5', label: 'GPT-5', reasoning: true },
'gpt-5-mini': { provider: 'openai', modelId: 'gpt-5-mini', label: 'GPT-5 Mini', reasoning: true },
// Anthropic
'claude-opus-4-7': { provider: 'anthropic', modelId: 'claude-opus-4-7', label: 'Claude Opus 4.7' },
'claude-sonnet-4-6': { provider: 'anthropic', modelId: 'claude-sonnet-4-6', label: 'Claude Sonnet 4.6' },
'claude-haiku-4-5': { provider: 'anthropic', modelId: 'claude-haiku-4-5-20251001', label: 'Claude Haiku 4.5' }
'claude-opus-4-7': { provider: 'anthropic', modelId: 'claude-opus-4-7', label: 'Claude Opus 4.7', reasoning: true },
'claude-sonnet-4-6': { provider: 'anthropic', modelId: 'claude-sonnet-4-6', label: 'Claude Sonnet 4.6', reasoning: true },
'claude-haiku-4-5': { provider: 'anthropic', modelId: 'claude-haiku-4-5-20251001', label: 'Claude Haiku 4.5', reasoning: true }
};
const isReasoningModel = (modelId) => Boolean(MODEL_DEFINITIONS[modelId]?.reasoning);
const isOpenAiReasoningModel = (modelId) => {
const def = MODEL_DEFINITIONS[modelId];
return Boolean(def?.reasoning && def?.provider === 'openai');
};
// Cache SDK instances. Built-in keyed by `${providerId}:${apiKey}`; compat
@@ -208,7 +219,9 @@ const getModel = (modelId, { aiPreferences, getApiKey }) => {
throw new Error(`${providerLabel(def.providerId, aiPreferences)} is missing a Base URL. Set one in Preferences > AI.`);
}
return getSdk({ providerId: def.providerId, apiKey, baseURL: def.baseURL })(def.sdkModelId);
const sdk = getSdk({ providerId: def.providerId, apiKey, baseURL: def.baseURL });
if (isOpenAiCompatibleProviderId(def.providerId)) return sdk.chat(def.sdkModelId);
return sdk(def.sdkModelId);
};
/**
@@ -273,6 +286,8 @@ module.exports = {
getCompatEndpoint,
isKnownProviderId,
isBuiltInModelId,
isReasoningModel,
isOpenAiReasoningModel,
validateApiKeyForProvider,
providerLabel
};