fix: register custom user agents in delegate-task resolver (#2689)
agent-config-handler.ts now registers custom agents from ~/.config/opencode/agents/ into the task subagent registry. 5005 tests pass, tsc clean. Closes #2689
This commit is contained in:
@@ -293,6 +293,81 @@ describe("applyAgentConfig builtin override protection", () => {
|
||||
expect(createSisyphusJuniorAgentSpy).toHaveBeenCalledWith(undefined, "openai/gpt-5.4", false)
|
||||
})
|
||||
|
||||
test("defaults mode to subagent for configAgent entries missing mode", async () => {
|
||||
// given
|
||||
const config = createBaseConfig()
|
||||
;(config as Record<string, unknown>).agent = {
|
||||
"custom-reviewer": {
|
||||
name: "custom-reviewer",
|
||||
prompt: "Review code for security issues",
|
||||
description: "Custom code reviewer",
|
||||
},
|
||||
}
|
||||
|
||||
// when
|
||||
const result = await applyAgentConfig({
|
||||
config,
|
||||
pluginConfig: createPluginConfig(),
|
||||
ctx: { directory: "/tmp" },
|
||||
pluginComponents: createPluginComponents(),
|
||||
})
|
||||
|
||||
// then
|
||||
const customAgent = result["custom-reviewer"] as Record<string, unknown>
|
||||
expect(customAgent).toBeDefined()
|
||||
expect(customAgent.mode).toBe("subagent")
|
||||
})
|
||||
|
||||
test("preserves explicit mode on configAgent entries", async () => {
|
||||
// given
|
||||
const config = createBaseConfig()
|
||||
;(config as Record<string, unknown>).agent = {
|
||||
"custom-primary": {
|
||||
name: "custom-primary",
|
||||
prompt: "Primary agent",
|
||||
mode: "primary",
|
||||
},
|
||||
}
|
||||
|
||||
// when
|
||||
const result = await applyAgentConfig({
|
||||
config,
|
||||
pluginConfig: createPluginConfig(),
|
||||
ctx: { directory: "/tmp" },
|
||||
pluginComponents: createPluginComponents(),
|
||||
})
|
||||
|
||||
// then
|
||||
const customAgent = result["custom-primary"] as Record<string, unknown>
|
||||
expect(customAgent).toBeDefined()
|
||||
expect(customAgent.mode).toBe("primary")
|
||||
})
|
||||
|
||||
test("defaults mode to subagent for plugin agents missing mode", async () => {
|
||||
// given
|
||||
const pluginComponents = createPluginComponents()
|
||||
pluginComponents.agents = {
|
||||
"plugin-worker": {
|
||||
name: "plugin-worker",
|
||||
prompt: "Do work",
|
||||
description: "Plugin worker agent",
|
||||
} as Record<string, unknown>,
|
||||
}
|
||||
|
||||
// when
|
||||
const result = await applyAgentConfig({
|
||||
config: createBaseConfig(),
|
||||
pluginConfig: createPluginConfig(),
|
||||
ctx: { directory: "/tmp" },
|
||||
pluginComponents,
|
||||
})
|
||||
|
||||
// then
|
||||
const pluginAgent = result["plugin-worker"] as Record<string, unknown>
|
||||
expect(pluginAgent).toBeDefined()
|
||||
expect(pluginAgent.mode).toBe("subagent")
|
||||
})
|
||||
|
||||
test("includes project and global .agents skills in builtin agent awareness", async () => {
|
||||
// given
|
||||
const projectAgentsSkill = {
|
||||
|
||||
@@ -99,10 +99,12 @@ export async function applyAgentConfig(params: {
|
||||
const rawPluginAgents = params.pluginComponents.agents;
|
||||
|
||||
const pluginAgents = Object.fromEntries(
|
||||
Object.entries(rawPluginAgents).map(([key, value]) => [
|
||||
key,
|
||||
value ? migrateAgentConfig(value as Record<string, unknown>) : value,
|
||||
]),
|
||||
Object.entries(rawPluginAgents).map(([key, value]) => {
|
||||
if (!value) return [key, value];
|
||||
const migrated = migrateAgentConfig(value as Record<string, unknown>);
|
||||
if (!migrated.mode) migrated.mode = "subagent";
|
||||
return [key, migrated];
|
||||
}),
|
||||
);
|
||||
|
||||
const configAgent = params.config.agent as AgentConfigRecord | undefined;
|
||||
@@ -219,10 +221,12 @@ export async function applyAgentConfig(params: {
|
||||
if (key in builtinAgents) return false;
|
||||
return true;
|
||||
})
|
||||
.map(([key, value]) => [
|
||||
key,
|
||||
value ? migrateAgentConfig(value as Record<string, unknown>) : value,
|
||||
]),
|
||||
.map(([key, value]) => {
|
||||
if (!value) return [key, value];
|
||||
const migrated = migrateAgentConfig(value as Record<string, unknown>);
|
||||
if (!migrated.mode) migrated.mode = "subagent";
|
||||
return [key, migrated];
|
||||
}),
|
||||
)
|
||||
: {};
|
||||
|
||||
@@ -285,12 +289,23 @@ export async function applyAgentConfig(params: {
|
||||
protectedBuiltinAgentNames,
|
||||
);
|
||||
|
||||
const defaultedConfigAgents = configAgent
|
||||
? Object.fromEntries(
|
||||
Object.entries(configAgent).map(([key, value]) => {
|
||||
if (!value) return [key, value];
|
||||
const migrated = migrateAgentConfig(value as Record<string, unknown>);
|
||||
if (!migrated.mode) migrated.mode = "subagent";
|
||||
return [key, migrated];
|
||||
}),
|
||||
)
|
||||
: {};
|
||||
|
||||
params.config.agent = {
|
||||
...builtinAgents,
|
||||
...filterDisabledAgents(filteredUserAgents),
|
||||
...filterDisabledAgents(filteredProjectAgents),
|
||||
...filterDisabledAgents(filteredPluginAgents),
|
||||
...configAgent,
|
||||
...defaultedConfigAgents,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user