fix: Resolve Claude-compatible provider for backlog plan when client sends model (#809)

When the Plan dialog sends a model (e.g. MiniMax-M2.1 from phase
settings), the server now:

- Calls getProviderByModelId() so the correct provider config
  (baseUrl, credentials) is used for backlog plan generation.
- Falls back to getPhaseModelWithOverrides('backlogPlanningModel')
  when model lookup finds no provider, so the phase's provider is
  used when the model matches.
- Uses a plain system prompt instead of the claude_code preset when
  a Claude-compatible provider is set; the preset is for native
  Claude CLI and can break requests to MiniMax/GLM APIs.

Previously the request was sent to the default Anthropic endpoint
and/or used the preset, causing plan generation to fail for
MiniMax/GLM users.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Patrick Patel
2026-02-24 22:21:05 -06:00
committed by GitHub
parent 51e9a23ba1
commit 09a4d3f15a

View File

@@ -35,6 +35,7 @@ import {
getUseClaudeCodeSystemPromptSetting, getUseClaudeCodeSystemPromptSetting,
getPromptCustomization, getPromptCustomization,
getPhaseModelWithOverrides, getPhaseModelWithOverrides,
getProviderByModelId,
} from '../../lib/settings-helpers.js'; } from '../../lib/settings-helpers.js';
/** Maximum number of retry attempts for transient CLI failures */ /** Maximum number of retry attempts for transient CLI failures */
@@ -231,6 +232,35 @@ export async function generateBacklogPlan(
effectiveModel = resolved.model; effectiveModel = resolved.model;
thinkingLevel = resolved.thinkingLevel; thinkingLevel = resolved.thinkingLevel;
credentials = await settingsService?.getCredentials(); credentials = await settingsService?.getCredentials();
// Resolve Claude-compatible provider when client sends a model (e.g. MiniMax, GLM)
if (settingsService) {
const providerResult = await getProviderByModelId(
effectiveModel,
settingsService,
'[BacklogPlan]'
);
if (providerResult.provider) {
claudeCompatibleProvider = providerResult.provider;
if (providerResult.credentials) {
credentials = providerResult.credentials;
}
}
// Fallback: use phase settings provider if model lookup found nothing (e.g. model
// string format differs from provider's model id, but backlog planning phase has providerId).
if (!claudeCompatibleProvider) {
const phaseResult = await getPhaseModelWithOverrides(
'backlogPlanningModel',
settingsService,
projectPath,
'[BacklogPlan]'
);
const phaseResolved = resolvePhaseModel(phaseResult.phaseModel);
if (phaseResult.provider && phaseResolved.model === effectiveModel) {
claudeCompatibleProvider = phaseResult.provider;
credentials = phaseResult.credentials ?? credentials;
}
}
}
} else if (settingsService) { } else if (settingsService) {
// Use settings-based model with provider info // Use settings-based model with provider info
const phaseResult = await getPhaseModelWithOverrides( const phaseResult = await getPhaseModelWithOverrides(
@@ -291,8 +321,12 @@ CRITICAL INSTRUCTIONS:
${userPrompt}`; ${userPrompt}`;
finalSystemPrompt = undefined; // System prompt is now embedded in the user prompt finalSystemPrompt = undefined; // System prompt is now embedded in the user prompt
} else if (claudeCompatibleProvider) {
// Claude-compatible providers (MiniMax, GLM, etc.) use a plain API; do not use
// the claude_code preset (which is for Claude CLI/subprocess and can break the request).
finalSystemPrompt = systemPrompt;
} else if (useClaudeCodeSystemPrompt) { } else if (useClaudeCodeSystemPrompt) {
// Use claude_code preset for Claude models so the SDK subprocess // Use claude_code preset for native Claude so the SDK subprocess
// authenticates via CLI OAuth or API key the same way all other SDK calls do. // authenticates via CLI OAuth or API key the same way all other SDK calls do.
finalSystemPrompt = { finalSystemPrompt = {
type: 'preset', type: 'preset',