refactor(agents): drop ZWSP prefixes from agent display names
The sort shim from the previous commit enforces canonical core ordering at runtime, so ZWSP prefixes are no longer needed. Removing them eliminates the Bun.stringWidth vs terminal-width drift that broke the TUI status bar (#3259). Drop AGENT_LIST_SORT_PREFIXES and getAgentRuntimeName from agent-display-names; switch all call sites to getAgentDisplayName. getAgentListDisplayName stays as a thin alias for external importers. Keep stripInvisibleAgentCharacters and the ZWSP regex paths so legacy session state and configs from v3.14.0-v3.16.0 still resolve. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { describe, it, expect } from "bun:test"
|
||||
import { AGENT_DISPLAY_NAMES, getAgentConfigKey, getAgentDisplayName, getAgentListDisplayName, normalizeAgentForPrompt, normalizeAgentForPromptKey } from "./agent-display-names"
|
||||
import { AGENT_DISPLAY_NAMES, getAgentConfigKey, getAgentDisplayName, getAgentListDisplayName, normalizeAgentForPrompt, normalizeAgentForPromptKey, stripAgentListSortPrefix } from "./agent-display-names"
|
||||
|
||||
describe("getAgentDisplayName", () => {
|
||||
it("returns display name for lowercase config key (new format)", () => {
|
||||
@@ -194,16 +194,26 @@ describe("getAgentConfigKey", () => {
|
||||
})
|
||||
|
||||
describe("getAgentListDisplayName", () => {
|
||||
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 the canonical display name for the core agent list", () => {
|
||||
expect(getAgentListDisplayName("sisyphus")).toBe("Sisyphus - Ultraworker")
|
||||
expect(getAgentListDisplayName("hephaestus")).toBe("Hephaestus - Deep Agent")
|
||||
expect(getAgentListDisplayName("prometheus")).toBe("Prometheus - Plan Builder")
|
||||
expect(getAgentListDisplayName("atlas")).toBe("Atlas - Plan Executor")
|
||||
})
|
||||
|
||||
it("keeps non-core agents unprefixed for list display", () => {
|
||||
it("keeps non-core agents unchanged for list display", () => {
|
||||
expect(getAgentListDisplayName("oracle")).toBe("oracle")
|
||||
})
|
||||
|
||||
it("is a thin alias for getAgentDisplayName", () => {
|
||||
expect(getAgentListDisplayName("sisyphus")).toBe(getAgentDisplayName("sisyphus"))
|
||||
})
|
||||
})
|
||||
|
||||
describe("stripAgentListSortPrefix", () => {
|
||||
it("strips legacy zero-width sort prefixes baked into v3.14.0–v3.16.0 sessions", () => {
|
||||
expect(stripAgentListSortPrefix("\u200B\u200BHephaestus - Deep Agent")).toBe("Hephaestus - Deep Agent")
|
||||
})
|
||||
})
|
||||
|
||||
describe("normalizeAgentForPrompt", () => {
|
||||
|
||||
@@ -26,13 +26,6 @@ export const AGENT_DISPLAY_NAMES: Record<string, string> = {
|
||||
"council-member": "council-member",
|
||||
}
|
||||
|
||||
const AGENT_LIST_SORT_PREFIXES: Record<string, string> = {
|
||||
sisyphus: "\u200B",
|
||||
hephaestus: "\u200B\u200B",
|
||||
prometheus: "\u200B\u200B\u200B",
|
||||
atlas: "\u200B\u200B\u200B\u200B",
|
||||
}
|
||||
|
||||
const INVISIBLE_AGENT_CHARACTERS_REGEX = /[\u200B\u200C\u200D\uFEFF]/g
|
||||
|
||||
export function stripInvisibleAgentCharacters(agentName: string): string {
|
||||
@@ -43,13 +36,6 @@ export function stripAgentListSortPrefix(agentName: string): string {
|
||||
return stripInvisibleAgentCharacters(agentName)
|
||||
}
|
||||
|
||||
export function getAgentRuntimeName(configKey: string): string {
|
||||
const displayName = getAgentDisplayName(configKey)
|
||||
const prefix = AGENT_LIST_SORT_PREFIXES[configKey.toLowerCase()]
|
||||
|
||||
return prefix ? `${prefix}${displayName}` : displayName
|
||||
}
|
||||
|
||||
/**
|
||||
* Get display name for an agent config key.
|
||||
* Uses case-insensitive lookup for backward compatibility.
|
||||
@@ -59,22 +45,28 @@ export function getAgentDisplayName(configKey: string): string {
|
||||
// Try exact match first
|
||||
const exactMatch = AGENT_DISPLAY_NAMES[configKey]
|
||||
if (exactMatch !== undefined) return exactMatch
|
||||
|
||||
|
||||
// Fall back to case-insensitive search
|
||||
const lowerKey = configKey.toLowerCase()
|
||||
for (const [k, v] of Object.entries(AGENT_DISPLAY_NAMES)) {
|
||||
if (k.toLowerCase() === lowerKey) return v
|
||||
}
|
||||
|
||||
|
||||
// Unknown agent: return original key
|
||||
return configKey
|
||||
}
|
||||
|
||||
/**
|
||||
* Runtime-facing agent name used for OpenCode list ordering.
|
||||
* Thin alias for `getAgentDisplayName` preserved for external imports.
|
||||
*
|
||||
* Earlier versions injected zero-width prefixes here to bias OpenCode's
|
||||
* `agent.name` sort. Sort ordering is now enforced by
|
||||
* `src/shared/agent-sort-shim.ts`, so this function emits the canonical
|
||||
* display name verbatim. Kept exported because downstream modules still
|
||||
* import this symbol; do not collapse the call sites without coordinating.
|
||||
*/
|
||||
export function getAgentListDisplayName(configKey: string): string {
|
||||
return getAgentRuntimeName(configKey)
|
||||
return getAgentDisplayName(configKey)
|
||||
}
|
||||
|
||||
const REVERSE_DISPLAY_NAMES: Record<string, string> = Object.fromEntries(
|
||||
|
||||
Reference in New Issue
Block a user