Skip to content

Commit e6a6e61

Browse files
committed
core: show clear errors when default_agent config is invalid
Users now see specific error messages explaining why their configured default_agent cannot be used (not found, is subagent, or is hidden) instead of silently falling back to a different agent. Signed-off-by: assagman <[email protected]>
1 parent d558873 commit e6a6e61

2 files changed

Lines changed: 23 additions & 20 deletions

File tree

packages/opencode/src/agent/agent.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -255,9 +255,20 @@ export namespace Agent {
255255
}
256256

257257
export async function defaultAgent() {
258-
const agents = await list()
259-
const primaryVisible = agents.find((a) => a.mode !== "subagent" && a.hidden !== true)
260-
return primaryVisible?.name || "build"
258+
const cfg = await Config.get()
259+
const agents = await state()
260+
261+
if (cfg.default_agent) {
262+
const agent = agents[cfg.default_agent]
263+
if (!agent) throw new Error(`default agent "${cfg.default_agent}" not found`)
264+
if (agent.mode === "subagent") throw new Error(`default agent "${cfg.default_agent}" is a subagent`)
265+
if (agent.hidden === true) throw new Error(`default agent "${cfg.default_agent}" is hidden`)
266+
return agent.name
267+
}
268+
269+
const primaryVisible = Object.values(agents).find((a) => a.mode !== "subagent" && a.hidden !== true)
270+
if (!primaryVisible) throw new Error("no primary visible agent found")
271+
return primaryVisible.name
261272
}
262273

263274
export async function generate(input: { description: string; model?: { providerID: string; modelID: string } }) {

packages/opencode/test/agent/agent.test.ts

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -559,7 +559,7 @@ test("defaultAgent respects default_agent config set to custom agent with mode a
559559
})
560560
})
561561

562-
test("defaultAgent falls back when default_agent points to subagent", async () => {
562+
test("defaultAgent throws when default_agent points to subagent", async () => {
563563
await using tmp = await tmpdir({
564564
config: {
565565
default_agent: "explore",
@@ -568,15 +568,12 @@ test("defaultAgent falls back when default_agent points to subagent", async () =
568568
await Instance.provide({
569569
directory: tmp.path,
570570
fn: async () => {
571-
const agent = await Agent.defaultAgent()
572-
// explore is a subagent, so it should fall back to first primary-capable agent
573-
expect(agent).not.toBe("explore")
574-
expect(agent).toBe("build")
571+
await expect(Agent.defaultAgent()).rejects.toThrow('default agent "explore" is a subagent')
575572
},
576573
})
577574
})
578575

579-
test("defaultAgent falls back when default_agent points to hidden agent", async () => {
576+
test("defaultAgent throws when default_agent points to hidden agent", async () => {
580577
await using tmp = await tmpdir({
581578
config: {
582579
default_agent: "compaction",
@@ -585,15 +582,12 @@ test("defaultAgent falls back when default_agent points to hidden agent", async
585582
await Instance.provide({
586583
directory: tmp.path,
587584
fn: async () => {
588-
const agent = await Agent.defaultAgent()
589-
// compaction is hidden, so it should fall back to first primary-capable agent
590-
expect(agent).not.toBe("compaction")
591-
expect(agent).toBe("build")
585+
await expect(Agent.defaultAgent()).rejects.toThrow('default agent "compaction" is hidden')
592586
},
593587
})
594588
})
595589

596-
test("defaultAgent falls back when default_agent points to non-existent agent", async () => {
590+
test("defaultAgent throws when default_agent points to non-existent agent", async () => {
597591
await using tmp = await tmpdir({
598592
config: {
599593
default_agent: "does_not_exist",
@@ -602,8 +596,7 @@ test("defaultAgent falls back when default_agent points to non-existent agent",
602596
await Instance.provide({
603597
directory: tmp.path,
604598
fn: async () => {
605-
const agent = await Agent.defaultAgent()
606-
expect(agent).toBe("build")
599+
await expect(Agent.defaultAgent()).rejects.toThrow('default agent "does_not_exist" not found')
607600
},
608601
})
609602
})
@@ -626,7 +619,7 @@ test("defaultAgent returns plan when build is disabled and default_agent not set
626619
})
627620
})
628621

629-
test("defaultAgent returns first primary-capable agent when all natives are disabled", async () => {
622+
test("defaultAgent throws when all primary agents are disabled", async () => {
630623
await using tmp = await tmpdir({
631624
config: {
632625
agent: {
@@ -638,9 +631,8 @@ test("defaultAgent returns first primary-capable agent when all natives are disa
638631
await Instance.provide({
639632
directory: tmp.path,
640633
fn: async () => {
641-
const agent = await Agent.defaultAgent()
642-
// build and plan are disabled, so it should return general
643-
expect(agent).toBe("build")
634+
// build and plan are disabled, no primary-capable agents remain
635+
await expect(Agent.defaultAgent()).rejects.toThrow("no primary visible agent found")
644636
},
645637
})
646638
})

0 commit comments

Comments
 (0)