feat: support per-model thinkingDefault override in models config

The global `agents.defaults.thinkingDefault` forces a single thinking
level for all models.  Users running multiple models with different
reasoning capabilities (e.g. Claude with extended thinking, GPT-4o
without, Gemini Flash with lightweight reasoning) cannot optimise the
thinking level per model.

Add an optional `thinkingDefault` field to `AgentModelEntryConfig` so
each entry under `agents.defaults.models` can declare its own default.
Resolution priority: per-model → global → catalog auto-detect.

Example config:

    "models": {
      "anthropic/claude-sonnet-4-20250514": { "thinkingDefault": "high" },
      "openai/gpt-4o":                      { "thinkingDefault": "off" }
    }

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
wu-tian807
2026-02-16 23:04:37 +08:00
committed by Peter Steinberger
parent e368c36503
commit 671f913123
3 changed files with 32 additions and 0 deletions

View File

@@ -425,10 +425,29 @@ export function resolveThinkingDefault(params: {
model: string;
catalog?: ModelCatalogEntry[];
}): ThinkLevel {
// 1. Per-model thinkingDefault (highest priority)
// Normalize config keys via parseModelRef (consistent with buildModelAliasIndex,
// buildAllowedModelSet, etc.) so aliases like "anthropic/opus-4.6" resolve correctly.
const configModels = params.cfg.agents?.defaults?.models ?? {};
for (const [rawKey, entry] of Object.entries(configModels)) {
const parsed = parseModelRef(rawKey, params.provider);
if (
parsed &&
parsed.provider === params.provider &&
parsed.model === params.model &&
entry?.thinkingDefault
) {
return entry.thinkingDefault as ThinkLevel;
}
}
// 2. Global thinkingDefault
const configured = params.cfg.agents?.defaults?.thinkingDefault;
if (configured) {
return configured;
}
// 3. Auto-detect from model catalog (reasoning-capable → "low")
const candidate = params.catalog?.find(
(entry) => entry.provider === params.provider && entry.id === params.model,
);

View File

@@ -18,6 +18,8 @@ export type AgentModelEntryConfig = {
params?: Record<string, unknown>;
/** Enable streaming for this model (default: true, false for Ollama to avoid SDK issue #1205). */
streaming?: boolean;
/** Per-model default thinking level (overrides global thinkingDefault). */
thinkingDefault?: "off" | "minimal" | "low" | "medium" | "high" | "xhigh";
};
export type AgentModelListConfig = {

View File

@@ -38,6 +38,17 @@ export const AgentDefaultsSchema = z
params: z.record(z.string(), z.unknown()).optional(),
/** Enable streaming for this model (default: true, false for Ollama to avoid SDK issue #1205). */
streaming: z.boolean().optional(),
/** Per-model default thinking level (overrides global thinkingDefault). */
thinkingDefault: z
.union([
z.literal("off"),
z.literal("minimal"),
z.literal("low"),
z.literal("medium"),
z.literal("high"),
z.literal("xhigh"),
])
.optional(),
})
.strict(),
)