fix(agents): prevent user/project .md agents from overriding builtin agent modes
When users have .md agent files in ~/.claude/agents/ with the same names
as builtin agents (e.g. sisyphus.md, hephaestus.md, atlas.md),
loadAgentsFromDir() hardcodes mode: "subagent" for all loaded agents.
Because the config assembly spreads userAgents after builtinAgents:
config.agent = {
...builtinAgents, // sisyphus: mode="primary"
...userAgents, // sisyphus: mode="subagent" ← overrides
}
this causes all primary agents to become subagents. The TUI filters out
subagents, so only non-plugin agents (like "docs") appear in the agent
selector.
Fix:
- Filter out user/project agents that share names with builtin agents
before spreading into config.agent (both sisyphus-enabled and fallback
branches)
- Respect frontmatter `mode` field in .md agent files instead of
hardcoding "subagent"
- Add `mode` to AgentFrontmatter type
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -44,7 +44,7 @@ function loadAgentsFromDir(agentsDir: string, scope: AgentScope): LoadedAgent[]
|
|||||||
|
|
||||||
const config: AgentConfig = {
|
const config: AgentConfig = {
|
||||||
description: formattedDescription,
|
description: formattedDescription,
|
||||||
mode: "subagent",
|
mode: data.mode || "subagent",
|
||||||
prompt: body.trim(),
|
prompt: body.trim(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ export interface AgentFrontmatter {
|
|||||||
description?: string
|
description?: string
|
||||||
model?: string
|
model?: string
|
||||||
tools?: string
|
tools?: string
|
||||||
|
mode?: "subagent" | "primary" | "all"
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LoadedAgent {
|
export interface LoadedAgent {
|
||||||
|
|||||||
@@ -198,23 +198,47 @@ export async function applyAgentConfig(params: {
|
|||||||
)
|
)
|
||||||
: undefined;
|
: undefined;
|
||||||
|
|
||||||
|
// Collect all builtin agent names to prevent user/project .md files from overriding them
|
||||||
|
const builtinAgentNames = new Set([
|
||||||
|
...Object.keys(agentConfig),
|
||||||
|
...Object.keys(builtinAgents),
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Filter user/project agents that duplicate builtin agents (they have mode: "subagent" hardcoded
|
||||||
|
// in loadAgentsFromDir which would incorrectly override the builtin mode: "primary")
|
||||||
|
const filteredUserAgents = Object.fromEntries(
|
||||||
|
Object.entries(userAgents).filter(([key]) => !builtinAgentNames.has(key)),
|
||||||
|
);
|
||||||
|
const filteredProjectAgents = Object.fromEntries(
|
||||||
|
Object.entries(projectAgents).filter(([key]) => !builtinAgentNames.has(key)),
|
||||||
|
);
|
||||||
|
|
||||||
params.config.agent = {
|
params.config.agent = {
|
||||||
...agentConfig,
|
...agentConfig,
|
||||||
...Object.fromEntries(
|
...Object.fromEntries(
|
||||||
Object.entries(builtinAgents).filter(([key]) => key !== "sisyphus"),
|
Object.entries(builtinAgents).filter(([key]) => key !== "sisyphus"),
|
||||||
),
|
),
|
||||||
...filterDisabledAgents(userAgents),
|
...filterDisabledAgents(filteredUserAgents),
|
||||||
...filterDisabledAgents(projectAgents),
|
...filterDisabledAgents(filteredProjectAgents),
|
||||||
...filterDisabledAgents(pluginAgents),
|
...filterDisabledAgents(pluginAgents),
|
||||||
...filteredConfigAgents,
|
...filteredConfigAgents,
|
||||||
build: { ...migratedBuild, mode: "subagent", hidden: true },
|
build: { ...migratedBuild, mode: "subagent", hidden: true },
|
||||||
...(planDemoteConfig ? { plan: planDemoteConfig } : {}),
|
...(planDemoteConfig ? { plan: planDemoteConfig } : {}),
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
|
// Filter user/project agents that duplicate builtin agents
|
||||||
|
const builtinAgentNames = new Set(Object.keys(builtinAgents));
|
||||||
|
const filteredUserAgents = Object.fromEntries(
|
||||||
|
Object.entries(userAgents).filter(([key]) => !builtinAgentNames.has(key)),
|
||||||
|
);
|
||||||
|
const filteredProjectAgents = Object.fromEntries(
|
||||||
|
Object.entries(projectAgents).filter(([key]) => !builtinAgentNames.has(key)),
|
||||||
|
);
|
||||||
|
|
||||||
params.config.agent = {
|
params.config.agent = {
|
||||||
...builtinAgents,
|
...builtinAgents,
|
||||||
...filterDisabledAgents(userAgents),
|
...filterDisabledAgents(filteredUserAgents),
|
||||||
...filterDisabledAgents(projectAgents),
|
...filterDisabledAgents(filteredProjectAgents),
|
||||||
...filterDisabledAgents(pluginAgents),
|
...filterDisabledAgents(pluginAgents),
|
||||||
...configAgent,
|
...configAgent,
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user