feat: Enhance model resolution for Cursor models

- Added support for Cursor models in the model resolver, allowing cursor-prefixed models to pass through unchanged.
- Implemented logic to handle bare Cursor model IDs by adding the cursor- prefix.
- Updated logging to provide detailed information on model resolution processes for both Claude and Cursor models.
- Expanded unit tests to cover new Cursor model handling scenarios, ensuring robust validation of model resolution logic.
This commit is contained in:
Shirone
2025-12-28 01:55:40 +01:00
parent 0bcc8fca5d
commit b32eacc913
6 changed files with 134 additions and 10 deletions

View File

@@ -4,7 +4,13 @@
*/
// Re-export constants from types
export { CLAUDE_MODEL_MAP, DEFAULT_MODELS, type ModelAlias } from '@automaker/types';
export {
CLAUDE_MODEL_MAP,
CURSOR_MODEL_MAP,
DEFAULT_MODELS,
type ModelAlias,
type CursorModelId,
} from '@automaker/types';
// Export resolver functions
export { resolveModelString, getEffectiveModel } from './resolver.js';

View File

@@ -3,16 +3,17 @@
*
* Provides centralized model resolution logic:
* - Maps Claude model aliases to full model strings
* - Passes through Cursor models unchanged (handled by CursorProvider)
* - Provides default models per provider
* - Handles multiple model sources with priority
*/
import { CLAUDE_MODEL_MAP, DEFAULT_MODELS } from '@automaker/types';
import { CLAUDE_MODEL_MAP, CURSOR_MODEL_MAP, DEFAULT_MODELS } from '@automaker/types';
/**
* Resolve a model key/alias to a full model string
*
* @param modelKey - Model key (e.g., "opus", "gpt-5.2", "claude-sonnet-4-20250514")
* @param modelKey - Model key (e.g., "opus", "cursor-composer-1", "claude-sonnet-4-20250514")
* @param defaultModel - Fallback model if modelKey is undefined
* @returns Full model string
*/
@@ -20,11 +21,42 @@ export function resolveModelString(
modelKey?: string,
defaultModel: string = DEFAULT_MODELS.claude
): string {
console.log(
`[ModelResolver] resolveModelString called with modelKey: "${modelKey}", defaultModel: "${defaultModel}"`
);
// No model specified - use default
if (!modelKey) {
console.log(`[ModelResolver] No model specified, using default: ${defaultModel}`);
return defaultModel;
}
// Cursor model with explicit prefix (e.g., "cursor-composer-1") - pass through unchanged
// CursorProvider will strip the prefix when calling the CLI
if (modelKey.startsWith('cursor-')) {
const cursorModelId = modelKey.replace('cursor-', '');
// Verify it's a valid Cursor model
if (cursorModelId in CURSOR_MODEL_MAP) {
console.log(
`[ModelResolver] Using Cursor model: ${modelKey} (valid model ID: ${cursorModelId})`
);
return modelKey;
}
// Could be a cursor-prefixed model not in our map yet - still pass through
console.log(`[ModelResolver] Passing through cursor-prefixed model: ${modelKey}`);
return modelKey;
}
// Check if it's a bare Cursor model ID (e.g., "composer-1", "auto", "gpt-4o")
if (modelKey in CURSOR_MODEL_MAP) {
// Return with cursor- prefix so provider routing works correctly
const prefixedModel = `cursor-${modelKey}`;
console.log(
`[ModelResolver] Detected bare Cursor model ID: "${modelKey}" -> "${prefixedModel}"`
);
return prefixedModel;
}
// Full Claude model string - pass through unchanged
if (modelKey.includes('claude-')) {
console.log(`[ModelResolver] Using full Claude model string: ${modelKey}`);
@@ -34,7 +66,7 @@ export function resolveModelString(
// Look up Claude model alias
const resolved = CLAUDE_MODEL_MAP[modelKey];
if (resolved) {
console.log(`[ModelResolver] Resolved model alias: "${modelKey}" -> "${resolved}"`);
console.log(`[ModelResolver] Resolved Claude model alias: "${modelKey}" -> "${resolved}"`);
return resolved;
}