fix(opencode): trust discovered modes, don't inject hardcoded defaults (#1366)

* fix(opencode): trust discovered modes instead of always injecting defaults

When OpenCode reports its available agents, respect that list exactly
rather than seeding from DEFAULT_MODES first. This means users who have
intentionally disabled modes (e.g. Plan) in their OpenCode config will
no longer see those modes surfaced in Paseo.

DEFAULT_MODES is still used as a fallback when discovery returns nothing
(e.g. OpenCode unreachable or no agents configured).

* test(opencode): update mode discovery expectations

* test(opencode): expect discovered custom modes only
This commit is contained in:
Matt Cowger
2026-06-19 11:20:26 +08:00
committed by GitHub
parent b90baaff71
commit ccb8714a71
3 changed files with 21 additions and 11 deletions
@@ -63,7 +63,7 @@ function questionEvent(questionOverrides: Record<string, unknown> = {}): unknown
} }
describe("OpenCode auto_accept feature", () => { describe("OpenCode auto_accept feature", () => {
test("lists OpenCode modes without the legacy virtual full-access mode", async () => { test("lists discovered OpenCode modes without injecting defaults", async () => {
const { runtime } = mockOpenCodeClient({ const { runtime } = mockOpenCodeClient({
agents: [ agents: [
{ name: "build", mode: "primary", hidden: false, description: "Build agent" }, { name: "build", mode: "primary", hidden: false, description: "Build agent" },
@@ -74,7 +74,16 @@ describe("OpenCode auto_accept feature", () => {
const client = new OpenCodeAgentClient(createTestLogger(), undefined, { runtime }); const client = new OpenCodeAgentClient(createTestLogger(), undefined, { runtime });
const modes = await client.listModes({ cwd: "/tmp/project", force: false }); const modes = await client.listModes({ cwd: "/tmp/project", force: false });
expect(modes.map((mode) => mode.id)).toEqual(["build", "plan", "paseo-custom"]); expect(modes.map((mode) => mode.id)).toEqual(["build", "paseo-custom"]);
});
test("falls back to default OpenCode modes when discovery returns no modes", async () => {
const { runtime } = mockOpenCodeClient({ agents: [] });
const client = new OpenCodeAgentClient(createTestLogger(), undefined, { runtime });
const modes = await client.listModes({ cwd: "/tmp/project", force: false });
expect(modes.map((mode) => mode.id)).toEqual(["build", "plan"]);
}); });
test("lists auto accept as a provider feature", async () => { test("lists auto accept as a provider feature", async () => {
@@ -404,8 +404,7 @@ describe("OpenCodeAgentClient adapter smoke tests", () => {
const modes = await session.getAvailableModes(); const modes = await session.getAvailableModes();
expect(modes.some((mode) => mode.id === "build")).toBe(true); expect(modes.map((mode) => mode.id)).toEqual(["paseo-test-custom"]);
expect(modes.some((mode) => mode.id === "plan")).toBe(true);
const custom = modes.find((mode) => mode.id === "paseo-test-custom"); const custom = modes.find((mode) => mode.id === "paseo-test-custom");
expect(custom).toBeDefined(); expect(custom).toBeDefined();
@@ -591,14 +591,16 @@ function mapOpenCodeAgentToMode(agent: {
} }
function mergeOpenCodeModes(discoveredModes: AgentMode[]): AgentMode[] { function mergeOpenCodeModes(discoveredModes: AgentMode[]): AgentMode[] {
const modesById = new Map(DEFAULT_MODES.map((mode) => [mode.id, mode])); const filtered = discoveredModes.filter(
for (const mode of discoveredModes) { (mode) => mode.id !== OPENCODE_LEGACY_FULL_ACCESS_MODE_ID,
if (mode.id === OPENCODE_LEGACY_FULL_ACCESS_MODE_ID) { );
continue; // When discovery returns results, trust them exactly — don't inject hardcoded
} // defaults that the user may have intentionally disabled in their OpenCode config.
modesById.set(mode.id, mode); // Fall back to DEFAULT_MODES only when discovery produced nothing.
if (filtered.length > 0) {
return sortOpenCodeModes(filtered);
} }
return sortOpenCodeModes(Array.from(modesById.values())); return sortOpenCodeModes([...DEFAULT_MODES]);
} }
function sortOpenCodeModes(modes: AgentMode[]): AgentMode[] { function sortOpenCodeModes(modes: AgentMode[]): AgentMode[] {