refactor(agents): replace broken ZWSP sort prefixes with leading ASCII spaces
The ZWSP-based core agent sort prefixes silently failed to produce the canonical sisyphus -> hephaestus -> prometheus -> atlas order. Empirical testing of OpenCode's Agent.list() sort behavior shows that Unicode collation treats zero-width characters as ignorable at the primary level, so ZWSP-prefixed names sorted alphabetically with non-core agents interleaved (e.g. Sisyphus, athena, Atlas, explore, Hephaestus, ...). This commit replaces the ZWSP prefixes with leading ASCII spaces in descending lengths (sisyphus=4, hephaestus=3, prometheus=2, atlas=1). ASCII spaces sort reliably before alphabetic characters in localeCompare under all locales and render correctly in every terminal. Changes: - AGENT_LIST_SORT_PREFIXES: ZWSP -> leading spaces (4-3-2-1 descending) - stripAgentListSortPrefix: now strips both legacy ZWSP and new leading whitespace, preserving backward compatibility with existing sessions - normalizeStoredAgentName / normalizeRegisteredAgentName: extract a shared stripSortPrefix helper that handles both prefix formats - agent-config-handler: resolve user-provided default_agent display names through getAgentConfigKey before applying the runtime prefix, so configs like default_agent="Hephaestus - Deep Agent" are normalized - agent-runtime-name-sort.test.ts: new regression test simulating OpenCode's exact sortBy logic (default_agent desc + name asc localeCompare) to verify canonical core agent order under randomised input permutations - AGENTS.md: document the empirical finding that ZWSP was broken, why ASCII spaces work, and the descending prefix-length contract Existing strip functions retain ZWSP support so legacy session state and configs continue to resolve correctly without migration.
This commit is contained in:
@@ -18,12 +18,16 @@ const registeredAgentAliases = new Map<string, string>()
|
||||
|
||||
const ZERO_WIDTH_CHARACTERS_REGEX = /[\u200B\u200C\u200D\uFEFF]/g
|
||||
|
||||
function stripSortPrefix(name: string): string {
|
||||
return name.replace(ZERO_WIDTH_CHARACTERS_REGEX, "").replace(/^\s+/, "")
|
||||
}
|
||||
|
||||
function normalizeRegisteredAgentName(name: string): string {
|
||||
return name.replace(ZERO_WIDTH_CHARACTERS_REGEX, "").toLowerCase()
|
||||
return stripSortPrefix(name).toLowerCase()
|
||||
}
|
||||
|
||||
function normalizeStoredAgentName(name: string): string {
|
||||
return name.replace(ZERO_WIDTH_CHARACTERS_REGEX, "")
|
||||
return stripSortPrefix(name)
|
||||
}
|
||||
|
||||
export function registerAgentName(name: string): void {
|
||||
|
||||
Reference in New Issue
Block a user