From ec7168eb6c32fef18beb84800feab711bb45b87f Mon Sep 17 00:00:00 2001 From: Alan She <2948507+scw1109@users.noreply.github.com> Date: Thu, 14 May 2026 20:45:52 +0800 Subject: [PATCH 1/2] fix: respect default_agent in sort shim ordering (#3900) The sort shim always placed core agents (sisyphus, hephaestus, prometheus, atlas) before any custom agent, ignoring the user's configured default_agent in opencode.json. This caused the TUI to always show Sisyphus as the selected agent on startup regardless of default_agent. Add setDefaultAgentForSort() which inserts the configured default_agent at rank 0 in the sort shim's rank map. Called from applyAgentConfig after resolving the effective default_agent value. Fixes #3900 --- src/plugin-handlers/agent-config-handler.ts | 6 +++ src/shared/agent-sort-shim.test.ts | 43 ++++++++++++++++++++- src/shared/agent-sort-shim.ts | 11 ++++++ 3 files changed, 59 insertions(+), 1 deletion(-) diff --git a/src/plugin-handlers/agent-config-handler.ts b/src/plugin-handlers/agent-config-handler.ts index 9d5c3b2ca..16fcda22f 100644 --- a/src/plugin-handlers/agent-config-handler.ts +++ b/src/plugin-handlers/agent-config-handler.ts @@ -8,6 +8,7 @@ import { normalizeAgentForPromptKey, } from "../shared/agent-display-names"; import { AGENT_NAME_MAP } from "../shared/migration"; +import { setDefaultAgentForSort } from "../shared/agent-sort-shim"; import { registerAgentName } from "../features/claude-code-session-state"; import { discoverConfigSourceSkills, @@ -399,6 +400,11 @@ export async function applyAgentConfig(params: { ); } + const resolvedDefault = (params.config as { default_agent?: string }).default_agent; + if (resolvedDefault) { + setDefaultAgentForSort(resolvedDefault); + } + const agentResult = params.config.agent as Record; for (const name of Object.keys(agentResult)) { registerAgentName(name); diff --git a/src/shared/agent-sort-shim.test.ts b/src/shared/agent-sort-shim.test.ts index 47145924a..233ce19d7 100644 --- a/src/shared/agent-sort-shim.test.ts +++ b/src/shared/agent-sort-shim.test.ts @@ -2,7 +2,7 @@ import { afterEach, beforeAll, describe, expect, test } from "bun:test" -import { installAgentSortShim, setAgentSortOrder } from "./agent-sort-shim" +import { installAgentSortShim, setAgentSortOrder, setDefaultAgentForSort } from "./agent-sort-shim" import { AGENT_DISPLAY_NAMES } from "./agent-display-names" type AgentListItem = { @@ -224,4 +224,45 @@ describe("agent-sort-shim", () => { }) }) }) + + describe("#given a custom default_agent configured via setDefaultAgentForSort", () => { + describe("#when toSorted is called on core agents mixed with the custom default agent", () => { + test("#then the custom default agent sorts first, followed by core agents in canonical order", () => { + // given + setAgentSortOrder(undefined) + setDefaultAgentForSort("crystal") + const sisyphus = { name: "Sisyphus - Ultraworker" } + const hephaestus = { name: "Hephaestus - Deep Agent" } + const prometheus = { name: "Prometheus - Plan Builder" } + const atlas = { name: "Atlas - Plan Executor" } + const crystal = { name: "crystal" } + const input = [atlas, crystal, prometheus, hephaestus, sisyphus] + + // when + const result = input.toSorted((a, b) => a.name.localeCompare(b.name)) + + // then + expect(result).toEqual([crystal, sisyphus, hephaestus, prometheus, atlas]) + }) + }) + + describe("#when setDefaultAgentForSort is called with a core agent name", () => { + test("#then that core agent sorts first, others follow in remaining canonical order", () => { + // given + setAgentSortOrder(undefined) + setDefaultAgentForSort("Hephaestus - Deep Agent") + const sisyphus = { name: "Sisyphus - Ultraworker" } + const hephaestus = { name: "Hephaestus - Deep Agent" } + const prometheus = { name: "Prometheus - Plan Builder" } + const atlas = { name: "Atlas - Plan Executor" } + const input = [atlas, prometheus, hephaestus, sisyphus] + + // when + const result = input.toSorted((a, b) => a.name.localeCompare(b.name)) + + // then + expect(result).toEqual([hephaestus, sisyphus, prometheus, atlas]) + }) + }) + }) }) diff --git a/src/shared/agent-sort-shim.ts b/src/shared/agent-sort-shim.ts index 479a20719..d23b1315e 100644 --- a/src/shared/agent-sort-shim.ts +++ b/src/shared/agent-sort-shim.ts @@ -82,6 +82,17 @@ export function setAgentSortOrder(agentOrder: readonly string[] | undefined): vo agentRank = createAgentRank(agentOrder) } +export function setDefaultAgentForSort(agentName: string | undefined): void { + if (!agentName) return + if (agentRank.get(agentName) === 0) return + const updated = new Map() + updated.set(agentName, 0) + for (const [key, rank] of agentRank) { + if (key !== agentName) updated.set(key, rank + 1) + } + agentRank = updated +} + export function installAgentSortShim(): void { if (installed) return From f5e063b00a7966367fcd74e2daaeb150e58e903d Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Mon, 18 May 2026 13:42:59 +0900 Subject: [PATCH 2/2] fix: only call setDefaultAgentForSort when user explicitly sets default_agent The previous code read params.config.default_agent which is always populated to "Sisyphus - Ultraworker" by existing logic (lines 196-204) even when the user never configured default_agent. This silently overrode any custom agent_order. Now we gate on configuredDefaultAgent (the user's explicit value) so the sort shim rank map is only mutated when the user actually set default_agent. Add regression test: agent_order without default_agent must preserve order. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus --- src/plugin-handlers/agent-config-handler.ts | 7 ++++--- src/shared/agent-sort-shim.test.ts | 21 +++++++++++++++++++++ 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/plugin-handlers/agent-config-handler.ts b/src/plugin-handlers/agent-config-handler.ts index 16fcda22f..026afdad2 100644 --- a/src/plugin-handlers/agent-config-handler.ts +++ b/src/plugin-handlers/agent-config-handler.ts @@ -400,9 +400,10 @@ export async function applyAgentConfig(params: { ); } - const resolvedDefault = (params.config as { default_agent?: string }).default_agent; - if (resolvedDefault) { - setDefaultAgentForSort(resolvedDefault); + if (configuredDefaultAgent) { + setDefaultAgentForSort( + (params.config as { default_agent?: string }).default_agent ?? configuredDefaultAgent, + ); } const agentResult = params.config.agent as Record; diff --git a/src/shared/agent-sort-shim.test.ts b/src/shared/agent-sort-shim.test.ts index 233ce19d7..4b26609c4 100644 --- a/src/shared/agent-sort-shim.test.ts +++ b/src/shared/agent-sort-shim.test.ts @@ -265,4 +265,25 @@ describe("agent-sort-shim", () => { }) }) }) + + describe("#given agent_order configured without default_agent", () => { + describe("#when setAgentSortOrder sets a non-canonical order and setDefaultAgentForSort is NOT called", () => { + test("#then the custom agent_order is preserved without implicit override", () => { + // given + setAgentSortOrder(["hephaestus", "sisyphus", "prometheus", "atlas"]) + // setDefaultAgentForSort is intentionally NOT called (user did not set default_agent) + const sisyphus = { name: "Sisyphus - Ultraworker" } + const hephaestus = { name: "Hephaestus - Deep Agent" } + const prometheus = { name: "Prometheus - Plan Builder" } + const atlas = { name: "Atlas - Plan Executor" } + const input = [atlas, sisyphus, prometheus, hephaestus] + + // when + const result = input.toSorted((a, b) => a.name.localeCompare(b.name)) + + // then — Hephaestus must remain first per the user's agent_order + expect(result).toEqual([hephaestus, sisyphus, prometheus, atlas]) + }) + }) + }) })