Fix custom providers not passing model name properly

This commit is contained in:
gsxdsm
2026-02-14 19:24:10 -08:00
parent 5ffbfb3217
commit bcc854234c
6 changed files with 68 additions and 18 deletions

View File

@@ -219,18 +219,21 @@ export function createEnhanceHandler(
}
}
// Resolve the model - use provider resolved model, passed model, or default to sonnet
const resolvedModel =
providerResolvedModel || resolveModelString(model, CLAUDE_MODEL_MAP.sonnet);
// Resolve the model for API call.
// CRITICAL: For custom providers (GLM, MiniMax), pass the provider's model ID (e.g. "GLM-4.7")
// to the API, NOT the resolved Claude model - otherwise we get "model not found"
const modelForApi = claudeCompatibleProvider
? model
: providerResolvedModel || resolveModelString(model, CLAUDE_MODEL_MAP.sonnet);
logger.debug(`Using model: ${resolvedModel}`);
logger.debug(`Using model: ${modelForApi}`);
// Use simpleQuery - provider abstraction handles routing to correct provider
// The system prompt is combined with user prompt since some providers
// don't have a separate system prompt concept
const result = await simpleQuery({
prompt: [systemPrompt, projectContext, userPrompt].filter(Boolean).join('\n\n'),
model: resolvedModel,
model: modelForApi,
cwd: process.cwd(), // Enhancement doesn't need a specific working directory
maxTurns: 1,
allowedTools: [],

View File

@@ -188,8 +188,11 @@ ${basePrompt}`;
}
}
// Use provider resolved model if available, otherwise use original model
const effectiveModel = providerResolvedModel || (model as string);
// CRITICAL: For custom providers (GLM, MiniMax), pass the provider's model ID (e.g. "GLM-4.7")
// to the API, NOT the resolved Claude model - otherwise we get "model not found"
const effectiveModel = claudeCompatibleProvider
? (model as string)
: providerResolvedModel || (model as string);
logger.info(`Using model: ${effectiveModel}`);
// Use streamingQuery with event callbacks

View File

@@ -325,8 +325,9 @@ export class AgentService {
const effectiveThinkingLevel = thinkingLevel ?? session.thinkingLevel;
const effectiveReasoningEffort = reasoningEffort ?? session.reasoningEffort;
// When using a provider model, use the resolved Claude model (from mapsToClaudeModel)
// e.g., "GLM-4.5-Air" -> "claude-haiku-4-5"
// When using a custom provider (GLM, MiniMax), use resolved Claude model for SDK config
// (thinking level budgets, allowedTools) but we MUST pass the provider's model ID
// (e.g. "GLM-4.7") to the API - not "claude-sonnet-4-20250514" which causes "model not found"
const modelForSdk = providerResolvedModel || model;
const sessionModelForSdk = providerResolvedModel ? undefined : session.model;
@@ -387,10 +388,16 @@ export class AgentService {
}
// Get provider for this model (with prefix)
const provider = ProviderFactory.getProviderForModel(effectiveModel);
// When using custom provider (GLM, MiniMax), requestedModel routes to Claude provider
const modelForProvider = claudeCompatibleProvider ? requestedModel : effectiveModel;
const provider = ProviderFactory.getProviderForModel(modelForProvider);
// Strip provider prefix - providers should receive bare model IDs
const bareModel = stripProviderPrefix(effectiveModel);
// CRITICAL: For custom providers (GLM, MiniMax), pass the provider's model ID (e.g. "GLM-4.7")
// to the API, NOT the resolved Claude model - otherwise we get "model not found"
const bareModel = claudeCompatibleProvider
? requestedModel
: stripProviderPrefix(effectiveModel);
// Build options for provider
const options: ExecuteOptions = {

View File

@@ -20,7 +20,7 @@ import { createLogger, loadContextFiles, classifyError } from '@automaker/utils'
import { getFeatureDir } from '@automaker/platform';
import * as secureFs from '../../lib/secure-fs.js';
import { validateWorkingDirectory } from '../../lib/sdk-options.js';
import { getPromptCustomization } from '../../lib/settings-helpers.js';
import { getPromptCustomization, getProviderByModelId } from '../../lib/settings-helpers.js';
import { TypedEventBus } from '../typed-event-bus.js';
import { ConcurrencyManager } from '../concurrency-manager.js';
import { WorktreeResolver } from '../worktree-resolver.js';
@@ -169,6 +169,23 @@ export class AutoModeServiceFacade {
const provider = ProviderFactory.getProviderForModel(resolvedModel);
const effectiveBareModel = stripProviderPrefix(resolvedModel);
// Resolve custom provider (GLM, MiniMax, etc.) for baseUrl and credentials
let claudeCompatibleProvider:
| import('@automaker/types').ClaudeCompatibleProvider
| undefined;
let credentials: import('@automaker/types').Credentials | undefined;
if (resolvedModel && settingsService) {
const providerResult = await getProviderByModelId(
resolvedModel,
settingsService,
'[AutoModeFacade]'
);
if (providerResult.provider) {
claudeCompatibleProvider = providerResult.provider;
credentials = providerResult.credentials;
}
}
await agentExecutor.execute(
{
workDir,
@@ -187,6 +204,8 @@ export class AutoModeServiceFacade {
branchName: opts?.branchName as string | null | undefined,
provider,
effectiveBareModel,
credentials,
claudeCompatibleProvider,
},
{
waitForApproval: (fId, projPath) => planApprovalService.waitForApproval(fId, projPath),
@@ -273,6 +292,23 @@ export class AutoModeServiceFacade {
const provider = ProviderFactory.getProviderForModel(resolvedModel);
const effectiveBareModel = stripProviderPrefix(resolvedModel);
// Resolve custom provider (GLM, MiniMax, etc.) for baseUrl and credentials
let claudeCompatibleProvider:
| import('@automaker/types').ClaudeCompatibleProvider
| undefined;
let credentials: import('@automaker/types').Credentials | undefined;
if (resolvedModel && settingsService) {
const providerResult = await getProviderByModelId(
resolvedModel,
settingsService,
'[AutoModeFacade]'
);
if (providerResult.provider) {
claudeCompatibleProvider = providerResult.provider;
credentials = providerResult.credentials;
}
}
await agentExecutor.execute(
{
workDir,
@@ -290,6 +326,8 @@ export class AutoModeServiceFacade {
branchName: opts?.branchName,
provider,
effectiveBareModel,
credentials,
claudeCompatibleProvider,
},
{
waitForApproval: (fId, projPath) => planApprovalService.waitForApproval(fId, projPath),

View File

@@ -230,10 +230,9 @@ export class IdeationService {
);
if (providerResult.provider) {
claudeCompatibleProvider = providerResult.provider;
// Use resolved model from provider if available (maps to Claude model)
if (providerResult.resolvedModel) {
modelId = providerResult.resolvedModel;
}
// CRITICAL: For custom providers, use the provider's model ID (e.g. "GLM-4.7")
// for the API call, NOT the resolved Claude model - otherwise we get "model not found"
modelId = options.model;
credentials = providerResult.credentials ?? credentials;
}
}

View File

@@ -466,7 +466,7 @@ export const CLAUDE_PROVIDER_TEMPLATES: ClaudeCompatibleProviderTemplate[] = [
defaultModels: [
{ id: 'GLM-4.5-Air', displayName: 'GLM 4.5 Air', mapsToClaudeModel: 'haiku' },
{ id: 'GLM-4.7', displayName: 'GLM 4.7', mapsToClaudeModel: 'sonnet' },
{ id: 'GLM-4.7', displayName: 'GLM 4.7', mapsToClaudeModel: 'opus' },
{ id: 'GLM-5', displayName: 'GLM 5', mapsToClaudeModel: 'opus' },
],
},
{
@@ -549,7 +549,7 @@ export const CLAUDE_API_PROFILE_TEMPLATES: ClaudeApiProfileTemplate[] = [
modelMappings: {
haiku: 'GLM-4.5-Air',
sonnet: 'GLM-4.7',
opus: 'GLM-4.7',
opus: 'GLM-5',
},
disableNonessentialTraffic: true,
description: '3× usage at fraction of cost via GLM Coding Plan',