feat(coding-agent): added slow model role for comprehensive reasoning

- Added pi/smol alias for explore agent (fast/cheap model)
- Added pi/slow alias for reviewer agent (reasoning/codex model)
- Added L key binding in model selector to set slow model
- Added 🧠 marker for slow model in selector
- Slow model priority chain: gpt-5.2-codex > codex > gpt > opus > pro
This commit is contained in:
can1357
2026-01-03 03:36:51 +01:00
parent 003a19bdaa
commit 4b73cb6a54
5 changed files with 72 additions and 8 deletions
+5 -4
View File
@@ -12,11 +12,12 @@
### Added
- Model roles: Configure different models for different purposes (default, small, etc.) via `/model` selector
- Model selector dual-key binding: Enter sets default model, S sets small model, Escape closes
- Model selector shows role markers: checkmark for default, lightning bolt for small
- `pi/<role>` model aliases in Task tool agent definitions (e.g., `model: pi/small, haiku, flash, mini`)
- Model roles: Configure different models for different purposes (default, small, slow) via `/model` selector
- Model selector key bindings: Enter sets default, S sets small, L sets slow, Escape closes
- Model selector shows role markers: ✓ for default, ⚡ for small, 🧠 for slow
- `pi/<role>` model aliases in Task tool agent definitions (e.g., `model: pi/smol, haiku, flash, mini`)
- Small model auto-discovery using priority chain: haiku > flash > mini
- Slow model auto-discovery using priority chain: gpt-5.2-codex > codex > gpt > opus > pro
- Title generation now uses configured small model from settings
- LSP diagnostics on edit: Edit tool can now return LSP diagnostics after editing code files. Disabled by default to avoid noise during multi-edit sequences. Enable via `lsp.diagnosticsOnEdit` setting.
@@ -33,6 +33,9 @@ export interface ScopedModel {
/** Priority chain for auto-discovering small/fast models */
export const SMALL_MODEL_PRIORITY = ["claude-haiku-4-5", "haiku", "flash", "mini"];
/** Priority chain for auto-discovering slow/comprehensive models (reasoning, codex) */
export const SLOW_MODEL_PRIORITY = ["gpt-5.2-codex", "gpt-5.2", "codex", "gpt", "opus", "pro"];
/**
* Parse a model string in "provider/modelId" format.
* Returns undefined if the format is invalid.
@@ -450,3 +453,42 @@ export async function findSmallModel(
// 3. Fallback to first available (same as default)
return availableModels[0];
}
/**
* Find a slow/comprehensive model using the priority chain.
* Prioritizes reasoning and codex models for thorough analysis.
*
* @param modelRegistry The model registry to search
* @param savedModel Optional saved model string from settings (provider/modelId)
* @returns The best available slow model, or undefined if none found
*/
export async function findSlowModel(
modelRegistry: ModelRegistry,
savedModel?: string,
): Promise<Model<Api> | undefined> {
const availableModels = await modelRegistry.getAvailable();
if (availableModels.length === 0) return undefined;
// 1. Try saved model from settings
if (savedModel) {
const parsed = parseModelString(savedModel);
if (parsed) {
const match = availableModels.find((m) => m.provider === parsed.provider && m.id === parsed.id);
if (match) return match;
}
}
// 2. Try priority chain
for (const pattern of SLOW_MODEL_PRIORITY) {
// Try exact match first
const exactMatch = availableModels.find((m) => m.id.toLowerCase() === pattern.toLowerCase());
if (exactMatch) return exactMatch;
// Try fuzzy match (substring)
const fuzzyMatch = availableModels.find((m) => m.id.toLowerCase().includes(pattern.toLowerCase()));
if (fuzzyMatch) return fuzzyMatch;
}
// 3. Fallback to first available (same as default)
return availableModels[0];
}
@@ -2,7 +2,7 @@
name: explore
description: Fast read-only codebase scout that returns compressed context for handoff
tools: read, grep, glob, ls, bash
model: pi/small, haiku, flash, mini
model: pi/smol, haiku, flash, mini
---
You are a file search specialist and codebase scout. Quickly investigate a codebase and return structured findings that another agent can use without re-reading everything.
@@ -2,7 +2,7 @@
name: reviewer
description: Expert code reviewer for PRs and implementation changes
tools: read, grep, glob, ls, bash
model: gpt-5.2-codex, gpt-5.2, codex, gpt
model: pi/slow, gpt-5.2-codex, gpt-5.2, codex, gpt
---
You are an expert code reviewer. Analyze code changes and provide thorough reviews.
@@ -33,6 +33,7 @@ export class ModelSelectorComponent extends Container {
private currentModel?: Model<any>;
private defaultModel?: Model<any>;
private smallModel?: Model<any>;
private slowModel?: Model<any>;
private settingsManager: SettingsManager;
private modelRegistry: ModelRegistry;
private onSelectCallback: (model: Model<any>, role: string) => void;
@@ -73,7 +74,7 @@ export class ModelSelectorComponent extends Container {
? "Showing models from --models scope"
: "Only showing models with configured API keys (see README for details)";
this.addChild(new Text(theme.fg("warning", hintText), 0, 0));
this.addChild(new Text(theme.fg("muted", "Enter: set default S: set small Esc: close"), 0, 0));
this.addChild(new Text(theme.fg("muted", "Enter: default S: small L: slow Esc: close"), 0, 0));
this.addChild(new Spacer(1));
// Create search input
@@ -126,6 +127,15 @@ export class ModelSelectorComponent extends Container {
this.smallModel = allModels.find((m) => m.provider === parsed.provider && m.id === parsed.id);
}
}
// Load slow model
const slowStr = roles.slow;
if (slowStr) {
const parsed = parseModelString(slowStr);
if (parsed) {
this.slowModel = allModels.find((m) => m.provider === parsed.provider && m.id === parsed.id);
}
}
}
private async loadModels(): Promise<void> {
@@ -202,11 +212,13 @@ export class ModelSelectorComponent extends Container {
const isSelected = i === this.selectedIndex;
const isDefault = modelsAreEqual(this.defaultModel, item.model);
const isSmall = modelsAreEqual(this.smallModel, item.model);
const isSlow = modelsAreEqual(this.slowModel, item.model);
// Build role markers: ✓ for default, ⚡ for small
// Build role markers: ✓ for default, ⚡ for small, 🧠 for slow
let markers = "";
if (isDefault) markers += theme.fg("success", " ✓");
if (isSmall) markers += theme.fg("warning", " ⚡");
if (isSlow) markers += theme.fg("accent", " 🧠");
let line = "";
if (isSelected) {
@@ -268,6 +280,13 @@ export class ModelSelectorComponent extends Container {
this.handleSelect(selectedModel.model, "small");
}
}
// L key - set as slow model (don't close)
else if (keyData === "l" || keyData === "L") {
const selectedModel = this.filteredModels[this.selectedIndex];
if (selectedModel) {
this.handleSelect(selectedModel.model, "slow");
}
}
// Escape - close
else if (isEscape(keyData)) {
this.onCancelCallback();
@@ -288,6 +307,8 @@ export class ModelSelectorComponent extends Container {
this.defaultModel = model;
} else if (role === "small") {
this.smallModel = model;
} else if (role === "slow") {
this.slowModel = model;
}
// Notify caller (for updating agent state if needed)