diff --git a/src/plugin-handlers/agent-config-handler.test.ts b/src/plugin-handlers/agent-config-handler.test.ts index 6cb7514ed..b17d02faa 100644 --- a/src/plugin-handlers/agent-config-handler.test.ts +++ b/src/plugin-handlers/agent-config-handler.test.ts @@ -9,11 +9,11 @@ import type { OhMyOpenCodeConfig } from "../config" import * as agentLoader from "../features/claude-code-agent-loader" import * as skillLoader from "../features/opencode-skill-loader" import type { LoadedSkill } from "../features/opencode-skill-loader" -import { getAgentDisplayName } from "../shared/agent-display-names" +import { getAgentDisplayName, getAgentListDisplayName } from "../shared/agent-display-names" import { applyAgentConfig } from "./agent-config-handler" import type { PluginComponents } from "./plugin-components-loader" -const BUILTIN_SISYPHUS_DISPLAY_NAME = getAgentDisplayName("sisyphus") +const BUILTIN_SISYPHUS_DISPLAY_NAME = getAgentListDisplayName("sisyphus") const BUILTIN_SISYPHUS_JUNIOR_DISPLAY_NAME = getAgentDisplayName("sisyphus-junior") const BUILTIN_MULTIMODAL_LOOKER_DISPLAY_NAME = getAgentDisplayName("multimodal-looker") diff --git a/src/plugin-handlers/agent-key-remapper.test.ts b/src/plugin-handlers/agent-key-remapper.test.ts index fea227ea3..81d41c69e 100644 --- a/src/plugin-handlers/agent-key-remapper.test.ts +++ b/src/plugin-handlers/agent-key-remapper.test.ts @@ -1,5 +1,6 @@ import { describe, it, expect } from "bun:test" import { remapAgentKeysToDisplayNames } from "./agent-key-remapper" +import { getAgentListDisplayName } from "../shared/agent-display-names" describe("remapAgentKeysToDisplayNames", () => { it("remaps known agent keys to display names", () => { @@ -13,7 +14,7 @@ describe("remapAgentKeysToDisplayNames", () => { const result = remapAgentKeysToDisplayNames(agents) // then known agents get display name keys only - expect(result["Sisyphus (Ultraworker)"]).toBeDefined() + expect(result[getAgentListDisplayName("sisyphus")]).toBeDefined() expect(result["oracle"]).toBeDefined() expect(result["sisyphus"]).toBeUndefined() }) @@ -48,21 +49,21 @@ describe("remapAgentKeysToDisplayNames", () => { const result = remapAgentKeysToDisplayNames(agents) // then all get display name keys - expect(result["Sisyphus (Ultraworker)"]).toBeDefined() + expect(result[getAgentListDisplayName("sisyphus")]).toBeDefined() expect(result["sisyphus"]).toBeUndefined() - expect(result["Hephaestus (Deep Agent)"]).toBeDefined() + expect(result[getAgentListDisplayName("hephaestus")]).toBeDefined() expect(result["hephaestus"]).toBeUndefined() - expect(result["Prometheus (Plan Builder)"]).toBeDefined() + expect(result[getAgentListDisplayName("prometheus")]).toBeDefined() expect(result["prometheus"]).toBeUndefined() - expect(result["Atlas (Plan Executor)"]).toBeDefined() + expect(result[getAgentListDisplayName("atlas")]).toBeDefined() expect(result["atlas"]).toBeUndefined() - expect(result["Athena (Council)"]).toBeDefined() + expect(result[getAgentListDisplayName("athena")]).toBeDefined() expect(result["athena"]).toBeUndefined() - expect(result["Metis (Plan Consultant)"]).toBeDefined() + expect(result[getAgentListDisplayName("metis")]).toBeDefined() expect(result["metis"]).toBeUndefined() - expect(result["Momus (Plan Critic)"]).toBeDefined() + expect(result[getAgentListDisplayName("momus")]).toBeDefined() expect(result["momus"]).toBeUndefined() - expect(result["Sisyphus-Junior"]).toBeDefined() + expect(result[getAgentListDisplayName("sisyphus-junior")]).toBeDefined() expect(result["sisyphus-junior"]).toBeUndefined() }) @@ -76,8 +77,8 @@ describe("remapAgentKeysToDisplayNames", () => { const result = remapAgentKeysToDisplayNames(agents) // then only display key is emitted - expect(Object.keys(result)).toEqual(["Sisyphus (Ultraworker)"]) - expect(result["Sisyphus (Ultraworker)"]).toBeDefined() + expect(Object.keys(result)).toEqual([getAgentListDisplayName("sisyphus")]) + expect(result[getAgentListDisplayName("sisyphus")]).toBeDefined() expect(result["sisyphus"]).toBeUndefined() }) }) diff --git a/src/plugin-handlers/config-handler.test.ts b/src/plugin-handlers/config-handler.test.ts index 9c6cc5a34..2257c45b9 100644 --- a/src/plugin-handlers/config-handler.test.ts +++ b/src/plugin-handlers/config-handler.test.ts @@ -336,7 +336,7 @@ describe("Plan agent demote behavior", () => { expect(agents.plan).toBeDefined() expect(agents.plan.mode).toBe("subagent") expect(agents.plan.prompt).toBeUndefined() - expect(agents[getAgentDisplayName("prometheus")]?.prompt).toBeDefined() + expect(agents[getAgentListDisplayName("prometheus")]?.prompt).toBeDefined() }) test("plan agent remains unchanged when planner is disabled", async () => { @@ -370,7 +370,7 @@ describe("Plan agent demote behavior", () => { // #then - plan is not touched, prometheus is not created const agents = config.agent as Record - expect(agents[getAgentDisplayName("prometheus")]).toBeUndefined() + expect(agents[getAgentListDisplayName("prometheus")]).toBeUndefined() expect(agents.plan).toBeDefined() expect(agents.plan.mode).toBe("primary") expect(agents.plan.prompt).toBe("original plan prompt") @@ -401,7 +401,7 @@ describe("Plan agent demote behavior", () => { // then const agents = config.agent as Record - const prometheusKey = getAgentDisplayName("prometheus") + const prometheusKey = getAgentListDisplayName("prometheus") expect(agents[prometheusKey]).toBeDefined() expect(agents[prometheusKey].mode).toBe("all") }) @@ -437,7 +437,7 @@ describe("Agent permission defaults", () => { // #then const agentConfig = config.agent as Record }> - const hephaestusKey = getAgentDisplayName("hephaestus") + const hephaestusKey = getAgentListDisplayName("hephaestus") expect(agentConfig[hephaestusKey]).toBeDefined() expect(agentConfig[hephaestusKey].permission?.task).toBe("allow") }) @@ -779,7 +779,7 @@ describe("Prometheus direct override priority over category", () => { // then - direct override's reasoningEffort wins const agents = config.agent as Record - const pKey = getAgentDisplayName("prometheus") + const pKey = getAgentListDisplayName("prometheus") expect(agents[pKey]).toBeDefined() expect(agents[pKey].reasoningEffort).toBe("low") }) @@ -820,7 +820,7 @@ describe("Prometheus direct override priority over category", () => { // then - category's reasoningEffort is applied const agents = config.agent as Record - const pKey = getAgentDisplayName("prometheus") + const pKey = getAgentListDisplayName("prometheus") expect(agents[pKey]).toBeDefined() expect(agents[pKey].reasoningEffort).toBe("high") }) @@ -862,7 +862,7 @@ describe("Prometheus direct override priority over category", () => { // then - direct temperature wins over category const agents = config.agent as Record - const pKey = getAgentDisplayName("prometheus") + const pKey = getAgentListDisplayName("prometheus") expect(agents[pKey]).toBeDefined() expect(agents[pKey].temperature).toBe(0.1) }) @@ -898,7 +898,7 @@ describe("Prometheus direct override priority over category", () => { // #then - prompt_append is appended to base prompt, not overwriting it const agents = config.agent as Record - const pKey = getAgentDisplayName("prometheus") + const pKey = getAgentListDisplayName("prometheus") expect(agents[pKey]).toBeDefined() expect(agents[pKey].prompt).toContain("Prometheus") expect(agents[pKey].prompt).toContain(customInstructions) @@ -1336,10 +1336,10 @@ describe("per-agent todowrite/todoread deny when task_system enabled", () => { expect(lastCall?.[11]).toBe(false) const agentResult = config.agent as Record }> - expect(agentResult[getAgentDisplayName("sisyphus")]?.permission?.todowrite).toBeUndefined() - expect(agentResult[getAgentDisplayName("sisyphus")]?.permission?.todoread).toBeUndefined() - expect(agentResult[getAgentDisplayName("hephaestus")]?.permission?.todowrite).toBeUndefined() - expect(agentResult[getAgentDisplayName("hephaestus")]?.permission?.todoread).toBeUndefined() + expect(agentResult[getAgentListDisplayName("sisyphus")]?.permission?.todowrite).toBeUndefined() + expect(agentResult[getAgentListDisplayName("sisyphus")]?.permission?.todoread).toBeUndefined() + expect(agentResult[getAgentListDisplayName("hephaestus")]?.permission?.todowrite).toBeUndefined() + expect(agentResult[getAgentListDisplayName("hephaestus")]?.permission?.todoread).toBeUndefined() }) test("does not deny todowrite/todoread when task_system is undefined", async () => { @@ -1375,8 +1375,8 @@ describe("per-agent todowrite/todoread deny when task_system enabled", () => { expect(lastCall?.[11]).toBe(false) const agentResult = config.agent as Record }> - expect(agentResult[getAgentDisplayName("sisyphus")]?.permission?.todowrite).toBeUndefined() - expect(agentResult[getAgentDisplayName("sisyphus")]?.permission?.todoread).toBeUndefined() + expect(agentResult[getAgentListDisplayName("sisyphus")]?.permission?.todowrite).toBeUndefined() + expect(agentResult[getAgentListDisplayName("sisyphus")]?.permission?.todoread).toBeUndefined() }) }) diff --git a/src/shared/agent-display-names.test.ts b/src/shared/agent-display-names.test.ts index 238b49da2..538c16174 100644 --- a/src/shared/agent-display-names.test.ts +++ b/src/shared/agent-display-names.test.ts @@ -181,17 +181,23 @@ describe("getAgentConfigKey", () => { }) describe("getAgentListDisplayName", () => { - it("keeps sisyphus unchanged for list display", () => { - expect(getAgentListDisplayName("sisyphus")).toBe("Sisyphus (Ultraworker)") + it("applies invisible stable-sort prefixes to the core agent list", () => { + expect(getAgentListDisplayName("sisyphus")).toBe("\u200BSisyphus (Ultraworker)") + expect(getAgentListDisplayName("hephaestus")).toBe("\u200B\u200BHephaestus (Deep Agent)") + expect(getAgentListDisplayName("prometheus")).toBe("\u200B\u200B\u200BPrometheus (Plan Builder)") + expect(getAgentListDisplayName("atlas")).toBe("\u200B\u200B\u200B\u200BAtlas (Plan Executor)") }) - it("returns atlas display name without sort prefix", () => { - expect(getAgentListDisplayName("atlas")).toBe("Atlas (Plan Executor)") + it("keeps non-core agents unprefixed for list display", () => { + expect(getAgentListDisplayName("oracle")).toBe("oracle") }) }) describe("normalizeAgentForPrompt", () => { - it("strips atlas UI ordering prefix back to canonical display name", () => { + it("strips core UI ordering prefixes back to canonical display names", () => { + expect(normalizeAgentForPrompt(getAgentListDisplayName("sisyphus"))).toBe("Sisyphus (Ultraworker)") + expect(normalizeAgentForPrompt(getAgentListDisplayName("hephaestus"))).toBe("Hephaestus (Deep Agent)") + expect(normalizeAgentForPrompt(getAgentListDisplayName("prometheus"))).toBe("Prometheus (Plan Builder)") expect(normalizeAgentForPrompt(getAgentListDisplayName("atlas"))).toBe("Atlas (Plan Executor)") }) }) diff --git a/src/shared/agent-display-names.ts b/src/shared/agent-display-names.ts index 172977b64..532155ccc 100644 --- a/src/shared/agent-display-names.ts +++ b/src/shared/agent-display-names.ts @@ -20,7 +20,12 @@ export const AGENT_DISPLAY_NAMES: Record = { "council-member": "council-member", } -const AGENT_LIST_SORT_PREFIXES: Record = {} +const AGENT_LIST_SORT_PREFIXES: Record = { + sisyphus: "\u200B", + hephaestus: "\u200B\u200B", + prometheus: "\u200B\u200B\u200B", + atlas: "\u200B\u200B\u200B\u200B", +} function stripAgentListSortPrefix(agentName: string): string { return agentName.replace(/^\u200B+/, "")