AGENT_LIST_SORT_PREFIXES prepended U+200B Zero Width Space characters
to the four core agent display names so they would sort ahead of user
agents in the Tab cycle. Two problems with that approach surfaced:
1. Some terminal emulators (Ghostty, certain Windows Terminal
builds) render ZWSP as a visible box or extra space, producing a
visible black gap in the status bar before "Sisyphus" and
misaligning the layout (#3259).
2. The prefixes leaked into the plugin API surface via config.agent
keys, breaking prompt_async consumers that received
ZWSP-contaminated agent names (#3238).
#3242 already removed every call site of getAgentListDisplayName() in
production code. That made the sort prefixes dead code: the constant
table was still defined but nothing read it. This PR finishes the
cleanup by:
- Deleting the AGENT_LIST_SORT_PREFIXES constant entirely
- Turning getAgentListDisplayName() into a thin alias over
getAgentDisplayName() for BC with external importers
- Keeping stripAgentListSortPrefix() as a legacy data migration for
users upgrading from v3.14.0-v3.16.0 whose config.agent keys may
still have ZWSP baked in from the old code path
- Documenting the history on stripAgentListSortPrefix() so future
maintainers understand why the stripper has to stay even after
the injector is gone
Sort ordering is preserved via JS object insertion order in
reorderAgentsByPriority() plus the `order` field it injects on the
four core agents. Both mechanisms are already in place and both
pre-date this PR; the ZWSP prefix was an older third layer that was
only meant to work around alphabetical sorting in legacy OpenCode
before the `order` field landed upstream.
Tests: 4445 pass, 0 fail. Added 3 new assertions to
agent-display-names.test.ts verifying that getAgentListDisplayName
returns plain names containing no zero-width characters. Updated
chat-message.test.ts to use a literal ZWSP string instead of the
helper so the defensive-strip path still has coverage.
Closes#3259
Test expected legacy parenthesized names but display names now use
dash format (Sisyphus - Ultraworker, not Sisyphus (Ultraworker)).
This was the flaky CI failure on dev.
Display names with parentheses like 'Atlas (Plan Executor)' cause HTTP
header validation errors in x-opencode-agent-name. This was blocking
Atlas/Prometheus from working via /start-work and auto-retry.
Changes:
- Display names: parens -> dashes ('Atlas - Plan Executor')
- Hooks (start-work, no-hephaestus-non-gpt, no-sisyphus-gpt): use
config keys ('atlas', 'sisyphus', 'hephaestus') for agent API fields
- auto-retry: use config key instead of display name for promptAsync
- agent-override-protection: handle dash-suffix normalization
- Updated all test expectations to match new format
Closes#3138
Populate AGENT_LIST_SORT_PREFIXES for sisyphus/hephaestus/prometheus/atlas
so the TUI agent list renders in canonical order. Update dependent tests
to use getAgentListDisplayName() instead of hardcoded display strings.
🤖 Generated with [OhMyOpenCode](https://github.com/code-yeongyu/oh-my-opencode) assistance
The todo-continuation-enforcer was passing raw agent names (which could be
display names like 'Sisyphus (Ultraworker)') to promptAsync. These names
contain spaces/parentheses that violate HTTP header specs, causing the
x-opencode-agent-name header validation to fail with 'unknown error' toast.
Added normalizeAgentForPromptKey() that converts display names to config keys
(e.g., 'Sisyphus (Ultraworker)' -> 'sisyphus') before API calls.
TDD: Added regression test that verifies config key is sent to promptAsync.
The \u200B (zero-width space) in AGENT_LIST_SORT_PREFIXES leaked into
the x-opencode-agent-name HTTP header, causing invalid header errors.
Agent ordering is handled by agent-priority-order.ts via numeric order
fields and insertion order — the ZWSP prefix was redundant.
Remove crash-causing name fields from 6 agent configs (sisyphus, hephaestus,
atlas, metis, momus, prometheus). The name field approach breaks opencode
because Agent.get(agent.name) uses name as lookup key.
Add getAgentConfigKey() to agent-display-names.ts for resolving display names
back to lowercase config keys (e.g. 'Atlas (Plan Executor)' -> 'atlas').