fix(agent): default agent selection in acp and headless mode (#8678)
Signed-off-by: assagman <ahmetsercansagman@gmail.com>
This commit is contained in:
@@ -731,6 +731,9 @@ export namespace ACP {
|
|||||||
const defaultAgentName = await AgentModule.defaultAgent()
|
const defaultAgentName = await AgentModule.defaultAgent()
|
||||||
const currentModeId = availableModes.find((m) => m.name === defaultAgentName)?.id ?? availableModes[0].id
|
const currentModeId = availableModes.find((m) => m.name === defaultAgentName)?.id ?? availableModes[0].id
|
||||||
|
|
||||||
|
// Persist the default mode so prompt() uses it immediately
|
||||||
|
this.sessionManager.setMode(sessionId, currentModeId)
|
||||||
|
|
||||||
const mcpServers: Record<string, Config.Mcp> = {}
|
const mcpServers: Record<string, Config.Mcp> = {}
|
||||||
for (const server of params.mcpServers) {
|
for (const server of params.mcpServers) {
|
||||||
if ("type" in server) {
|
if ("type" in server) {
|
||||||
|
|||||||
@@ -255,7 +255,20 @@ export namespace Agent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function defaultAgent() {
|
export async function defaultAgent() {
|
||||||
return state().then((x) => Object.keys(x)[0])
|
const cfg = await Config.get()
|
||||||
|
const agents = await state()
|
||||||
|
|
||||||
|
if (cfg.default_agent) {
|
||||||
|
const agent = agents[cfg.default_agent]
|
||||||
|
if (!agent) throw new Error(`default agent "${cfg.default_agent}" not found`)
|
||||||
|
if (agent.mode === "subagent") throw new Error(`default agent "${cfg.default_agent}" is a subagent`)
|
||||||
|
if (agent.hidden === true) throw new Error(`default agent "${cfg.default_agent}" is hidden`)
|
||||||
|
return agent.name
|
||||||
|
}
|
||||||
|
|
||||||
|
const primaryVisible = Object.values(agents).find((a) => a.mode !== "subagent" && a.hidden !== true)
|
||||||
|
if (!primaryVisible) throw new Error("no primary visible agent found")
|
||||||
|
return primaryVisible.name
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function generate(input: { description: string; model?: { providerID: string; modelID: string } }) {
|
export async function generate(input: { description: string; model?: { providerID: string; modelID: string } }) {
|
||||||
|
|||||||
@@ -512,3 +512,127 @@ test("explicit Truncate.DIR deny is respected", async () => {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test("defaultAgent returns build when no default_agent config", async () => {
|
||||||
|
await using tmp = await tmpdir()
|
||||||
|
await Instance.provide({
|
||||||
|
directory: tmp.path,
|
||||||
|
fn: async () => {
|
||||||
|
const agent = await Agent.defaultAgent()
|
||||||
|
expect(agent).toBe("build")
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test("defaultAgent respects default_agent config set to plan", async () => {
|
||||||
|
await using tmp = await tmpdir({
|
||||||
|
config: {
|
||||||
|
default_agent: "plan",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
await Instance.provide({
|
||||||
|
directory: tmp.path,
|
||||||
|
fn: async () => {
|
||||||
|
const agent = await Agent.defaultAgent()
|
||||||
|
expect(agent).toBe("plan")
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test("defaultAgent respects default_agent config set to custom agent with mode all", async () => {
|
||||||
|
await using tmp = await tmpdir({
|
||||||
|
config: {
|
||||||
|
default_agent: "my_custom",
|
||||||
|
agent: {
|
||||||
|
my_custom: {
|
||||||
|
description: "My custom agent",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
await Instance.provide({
|
||||||
|
directory: tmp.path,
|
||||||
|
fn: async () => {
|
||||||
|
const agent = await Agent.defaultAgent()
|
||||||
|
expect(agent).toBe("my_custom")
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test("defaultAgent throws when default_agent points to subagent", async () => {
|
||||||
|
await using tmp = await tmpdir({
|
||||||
|
config: {
|
||||||
|
default_agent: "explore",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
await Instance.provide({
|
||||||
|
directory: tmp.path,
|
||||||
|
fn: async () => {
|
||||||
|
await expect(Agent.defaultAgent()).rejects.toThrow('default agent "explore" is a subagent')
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test("defaultAgent throws when default_agent points to hidden agent", async () => {
|
||||||
|
await using tmp = await tmpdir({
|
||||||
|
config: {
|
||||||
|
default_agent: "compaction",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
await Instance.provide({
|
||||||
|
directory: tmp.path,
|
||||||
|
fn: async () => {
|
||||||
|
await expect(Agent.defaultAgent()).rejects.toThrow('default agent "compaction" is hidden')
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test("defaultAgent throws when default_agent points to non-existent agent", async () => {
|
||||||
|
await using tmp = await tmpdir({
|
||||||
|
config: {
|
||||||
|
default_agent: "does_not_exist",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
await Instance.provide({
|
||||||
|
directory: tmp.path,
|
||||||
|
fn: async () => {
|
||||||
|
await expect(Agent.defaultAgent()).rejects.toThrow('default agent "does_not_exist" not found')
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test("defaultAgent returns plan when build is disabled and default_agent not set", async () => {
|
||||||
|
await using tmp = await tmpdir({
|
||||||
|
config: {
|
||||||
|
agent: {
|
||||||
|
build: { disable: true },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
await Instance.provide({
|
||||||
|
directory: tmp.path,
|
||||||
|
fn: async () => {
|
||||||
|
const agent = await Agent.defaultAgent()
|
||||||
|
// build is disabled, so it should return plan (next primary agent)
|
||||||
|
expect(agent).toBe("plan")
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test("defaultAgent throws when all primary agents are disabled", async () => {
|
||||||
|
await using tmp = await tmpdir({
|
||||||
|
config: {
|
||||||
|
agent: {
|
||||||
|
build: { disable: true },
|
||||||
|
plan: { disable: true },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
await Instance.provide({
|
||||||
|
directory: tmp.path,
|
||||||
|
fn: async () => {
|
||||||
|
// build and plan are disabled, no primary-capable agents remain
|
||||||
|
await expect(Agent.defaultAgent()).rejects.toThrow("no primary visible agent found")
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user