feat(coding-agent): introduced fine grained per agent advisor configuration

- Replaced blanket subagent advisor global settings with fine-grained per-agent configuration and frontmatter support.
- Added dashboard keybindings and inline override editors for managing agent advisor patterns.
- Implemented settings migration logic to convert legacy global options into per-agent settings.
- Updated session persistence and execution layers to restore and enforce per-agent advisor behaviors.
This commit is contained in:
can1357
2026-08-13 04:59:50 +02:00
parent 1132c3e31c
commit e8eed95130
27 changed files with 586 additions and 91 deletions
@@ -15,6 +15,7 @@ import { ModelRegistry } from "../config/model-registry";
import {
formatModelSelectorValue,
formatModelStringWithRouting,
resolveAgentAdvisorSelection,
resolveAgentPrewalkPattern,
resolveConfiguredModelPatterns,
resolveExplicitModelRole,
@@ -894,6 +895,9 @@ export function createSubagentSettings(
// the parent task approval is the authorization boundary. Use yolo mode
// to preserve unattended subagent execution. User `tools.approval` policies still apply.
"tools.approvalMode": "yolo",
// Subagents run unadvised by default; runSubprocess opts a spawn back in
// per agent (frontmatter `advisor` / `task.agentAdvisor`) via overrides.
"advisor.enabled": false,
...overrides,
},
{ storage: baseSettings.getStorage() },
@@ -2690,12 +2694,26 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
}
const settings = options.settings ?? Settings.isolated();
// Per-agent advisor: the agent definition's `advisor` frontmatter or the
// `task.agentAdvisor` settings override (agent name → "on"/"off"/model
// pattern) pairs the spawned session with an advisor. Subagents default to
// no advisor (createSubagentSettings forces `advisor.enabled` off); an
// explicit model pattern lands on the child's `modelRoles.advisor` so role
// aliases and `:level` suffixes resolve inside the spawned session.
const advisorSelection = resolveAgentAdvisorSelection({
settingsOverride: settings.get("task.agentAdvisor")[agent.name],
agentAdvisor: agent.advisor,
});
const subagentSettings = createSubagentSettings(
settings,
{
...(agent.readSummarize === false ? { "read.summarize.enabled": false } : undefined),
// Isolated runs must not expose roots outside the worktree.
...(worktree !== undefined ? { "workspace.additionalDirectories": [] } : undefined),
...(advisorSelection ? { "advisor.enabled": true } : undefined),
...(advisorSelection?.model
? { modelRoles: { ...settings.getModelRoles(), advisor: advisorSelection.model } }
: undefined),
},
options.parentServiceTier,
);
@@ -3197,6 +3215,7 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
readOnly: isReadOnlyAgent(agent),
spawns: spawnsEnv,
readSummarize: agent.readSummarize,
advisor: advisorSelection ? (advisorSelection.model ?? "on") : undefined,
outputSchema,
outputSchemaMode: options.outputSchemaMode,
restrictToolNames: restrictToolNames || undefined,