hangwin--mcp-chrome
271 行
7.3 KiB
TypeScript
271 行
7.3 KiB
TypeScript
/**
|
|
* Agent CLI Model Definitions.
|
|
*
|
|
* Static model definitions for each CLI type.
|
|
* Based on the pattern from Claudable (other/cweb).
|
|
*/
|
|
|
|
import type { CodexReasoningEffort } from 'chrome-mcp-shared';
|
|
|
|
// ============================================================
|
|
// Types
|
|
// ============================================================
|
|
|
|
export interface ModelDefinition {
|
|
id: string;
|
|
name: string;
|
|
description?: string;
|
|
supportsImages?: boolean;
|
|
/** Supported reasoning effort levels for Codex models */
|
|
supportedReasoningEfforts?: readonly CodexReasoningEffort[];
|
|
}
|
|
|
|
export type AgentCliType = 'claude' | 'codex' | 'cursor' | 'qwen' | 'glm';
|
|
|
|
// ============================================================
|
|
// Claude Models
|
|
// ============================================================
|
|
|
|
export const CLAUDE_MODELS: ModelDefinition[] = [
|
|
{
|
|
id: 'claude-sonnet-4-5-20250929',
|
|
name: 'Claude Sonnet 4.5',
|
|
description: 'Balanced model with large context window',
|
|
supportsImages: true,
|
|
},
|
|
{
|
|
id: 'claude-opus-4-5-20251101',
|
|
name: 'Claude Opus 4.5',
|
|
description: 'Strongest reasoning model',
|
|
supportsImages: true,
|
|
},
|
|
{
|
|
id: 'claude-haiku-4-5-20251001',
|
|
name: 'Claude Haiku 4.5',
|
|
description: 'Fast and cost-efficient',
|
|
supportsImages: true,
|
|
},
|
|
];
|
|
|
|
export const CLAUDE_DEFAULT_MODEL = 'claude-sonnet-4-5-20250929';
|
|
|
|
// ============================================================
|
|
// Codex Models
|
|
// ============================================================
|
|
|
|
/** Standard reasoning efforts supported by all models */
|
|
const CODEX_STANDARD_EFFORTS: readonly CodexReasoningEffort[] = ['low', 'medium', 'high'];
|
|
/** Extended reasoning efforts (includes xhigh) - only for gpt-5.2 and gpt-5.1-codex-max */
|
|
const CODEX_EXTENDED_EFFORTS: readonly CodexReasoningEffort[] = ['low', 'medium', 'high', 'xhigh'];
|
|
|
|
export const CODEX_MODELS: ModelDefinition[] = [
|
|
{
|
|
id: 'gpt-5.1',
|
|
name: 'GPT-5.1',
|
|
description: 'OpenAI high-quality reasoning model',
|
|
supportedReasoningEfforts: CODEX_STANDARD_EFFORTS,
|
|
},
|
|
{
|
|
id: 'gpt-5.2',
|
|
name: 'GPT-5.2',
|
|
description: 'OpenAI flagship reasoning model with extended effort support',
|
|
supportedReasoningEfforts: CODEX_EXTENDED_EFFORTS,
|
|
},
|
|
{
|
|
id: 'gpt-5.1-codex',
|
|
name: 'GPT-5.1 Codex',
|
|
description: 'Coding-optimized model for agent workflows',
|
|
supportedReasoningEfforts: CODEX_STANDARD_EFFORTS,
|
|
},
|
|
{
|
|
id: 'gpt-5.1-codex-max',
|
|
name: 'GPT-5.1 Codex Max',
|
|
description: 'Highest quality coding model with extended effort support',
|
|
supportedReasoningEfforts: CODEX_EXTENDED_EFFORTS,
|
|
},
|
|
{
|
|
id: 'gpt-5.1-codex-mini',
|
|
name: 'GPT-5.1 Codex Mini',
|
|
description: 'Fast, cost-efficient coding model',
|
|
supportedReasoningEfforts: CODEX_STANDARD_EFFORTS,
|
|
},
|
|
];
|
|
|
|
export const CODEX_DEFAULT_MODEL = 'gpt-5.1';
|
|
|
|
// Codex model alias normalization
|
|
const CODEX_ALIAS_MAP: Record<string, string> = {
|
|
gpt5: 'gpt-5.1',
|
|
gpt_5: 'gpt-5.1',
|
|
'gpt-5': 'gpt-5.1',
|
|
'gpt-5.0': 'gpt-5.1',
|
|
};
|
|
|
|
const CODEX_KNOWN_IDS = new Set(CODEX_MODELS.map((model) => model.id));
|
|
|
|
/**
|
|
* Normalize a Codex model ID, handling aliases and falling back to default.
|
|
*/
|
|
export function normalizeCodexModelId(model?: string | null): string {
|
|
if (!model || typeof model !== 'string') {
|
|
return CODEX_DEFAULT_MODEL;
|
|
}
|
|
|
|
const trimmed = model.trim();
|
|
if (!trimmed) {
|
|
return CODEX_DEFAULT_MODEL;
|
|
}
|
|
|
|
const lower = trimmed.toLowerCase();
|
|
if (CODEX_ALIAS_MAP[lower]) {
|
|
return CODEX_ALIAS_MAP[lower];
|
|
}
|
|
|
|
if (CODEX_KNOWN_IDS.has(lower)) {
|
|
return lower;
|
|
}
|
|
|
|
// If the exact casing exists, allow it
|
|
if (CODEX_KNOWN_IDS.has(trimmed)) {
|
|
return trimmed;
|
|
}
|
|
|
|
return CODEX_DEFAULT_MODEL;
|
|
}
|
|
|
|
/**
|
|
* Get supported reasoning efforts for a Codex model.
|
|
* Returns standard efforts (low/medium/high) for unknown models.
|
|
*/
|
|
export function getCodexReasoningEfforts(modelId?: string | null): readonly CodexReasoningEffort[] {
|
|
const normalized = normalizeCodexModelId(modelId);
|
|
const model = CODEX_MODELS.find((m) => m.id === normalized);
|
|
return model?.supportedReasoningEfforts ?? CODEX_STANDARD_EFFORTS;
|
|
}
|
|
|
|
/**
|
|
* Check if a model supports xhigh reasoning effort.
|
|
*/
|
|
export function supportsXhighEffort(modelId?: string | null): boolean {
|
|
const efforts = getCodexReasoningEfforts(modelId);
|
|
return efforts.includes('xhigh');
|
|
}
|
|
|
|
// ============================================================
|
|
// Cursor Models
|
|
// ============================================================
|
|
|
|
export const CURSOR_MODELS: ModelDefinition[] = [
|
|
{
|
|
id: 'auto',
|
|
name: 'Auto',
|
|
description: 'Cursor auto-selects the best model',
|
|
},
|
|
{
|
|
id: 'claude-sonnet-4-5-20250929',
|
|
name: 'Claude Sonnet 4.5',
|
|
description: 'Anthropic Claude via Cursor',
|
|
supportsImages: true,
|
|
},
|
|
{
|
|
id: 'gpt-4.1',
|
|
name: 'GPT-4.1',
|
|
description: 'OpenAI model via Cursor',
|
|
},
|
|
];
|
|
|
|
export const CURSOR_DEFAULT_MODEL = 'auto';
|
|
|
|
// ============================================================
|
|
// Qwen Models
|
|
// ============================================================
|
|
|
|
export const QWEN_MODELS: ModelDefinition[] = [
|
|
{
|
|
id: 'qwen3-coder-plus',
|
|
name: 'Qwen3 Coder Plus',
|
|
description: 'Balanced 32k context model for coding',
|
|
},
|
|
{
|
|
id: 'qwen3-coder-pro',
|
|
name: 'Qwen3 Coder Pro',
|
|
description: 'Larger 128k context with stronger reasoning',
|
|
},
|
|
{
|
|
id: 'qwen3-coder',
|
|
name: 'Qwen3 Coder',
|
|
description: 'Fast iteration model',
|
|
},
|
|
];
|
|
|
|
export const QWEN_DEFAULT_MODEL = 'qwen3-coder-plus';
|
|
|
|
// ============================================================
|
|
// GLM Models
|
|
// ============================================================
|
|
|
|
export const GLM_MODELS: ModelDefinition[] = [
|
|
{
|
|
id: 'glm-4.6',
|
|
name: 'GLM 4.6',
|
|
description: 'Zhipu GLM 4.6 agent runtime',
|
|
},
|
|
];
|
|
|
|
export const GLM_DEFAULT_MODEL = 'glm-4.6';
|
|
|
|
// ============================================================
|
|
// Aggregated Definitions
|
|
// ============================================================
|
|
|
|
export const CLI_MODEL_DEFINITIONS: Record<AgentCliType, ModelDefinition[]> = {
|
|
claude: CLAUDE_MODELS,
|
|
codex: CODEX_MODELS,
|
|
cursor: CURSOR_MODELS,
|
|
qwen: QWEN_MODELS,
|
|
glm: GLM_MODELS,
|
|
};
|
|
|
|
export const CLI_DEFAULT_MODELS: Record<AgentCliType, string> = {
|
|
claude: CLAUDE_DEFAULT_MODEL,
|
|
codex: CODEX_DEFAULT_MODEL,
|
|
cursor: CURSOR_DEFAULT_MODEL,
|
|
qwen: QWEN_DEFAULT_MODEL,
|
|
glm: GLM_DEFAULT_MODEL,
|
|
};
|
|
|
|
// ============================================================
|
|
// Helper Functions
|
|
// ============================================================
|
|
|
|
/**
|
|
* Get model definitions for a specific CLI type.
|
|
*/
|
|
export function getModelsForCli(cli: string | null | undefined): ModelDefinition[] {
|
|
if (!cli) return [];
|
|
const key = cli.toLowerCase() as AgentCliType;
|
|
return CLI_MODEL_DEFINITIONS[key] || [];
|
|
}
|
|
|
|
/**
|
|
* Get the default model for a CLI type.
|
|
*/
|
|
export function getDefaultModelForCli(cli: string | null | undefined): string {
|
|
if (!cli) return '';
|
|
const key = cli.toLowerCase() as AgentCliType;
|
|
return CLI_DEFAULT_MODELS[key] || '';
|
|
}
|
|
|
|
/**
|
|
* Get display name for a model ID.
|
|
*/
|
|
export function getModelDisplayName(
|
|
cli: string | null | undefined,
|
|
modelId: string | null | undefined,
|
|
): string {
|
|
if (!cli || !modelId) return modelId || '';
|
|
const models = getModelsForCli(cli);
|
|
const model = models.find((m) => m.id === modelId);
|
|
return model?.name || modelId;
|
|
}
|