Category-based delegation (task(category='quick')) was broken because
SISYPHUS_JUNIOR_AGENT sent 'sisyphus-junior' to session.prompt but
config.agent keys are now display names ('Sisyphus-Junior').
- Use getAgentDisplayName() for SISYPHUS_JUNIOR_AGENT constant
- Replace hardcoded 'sisyphus-junior' strings in tools.ts with constant
- Update background-output local constants to use display names
- Add remapCommandAgentFields() to translate command agent fields
- Add raw-key fallback in tool-config-handler agentByKey()
Use display names as config.agent keys so opencode shows proper names in UI
(Tab/@ menu). Key remapping happens after all agents are assembled but before
reordering, via remapAgentKeysToDisplayNames().
- agent-config-handler: set default_agent to display name, add key remapping
- agent-key-remapper: new module to transform lowercase keys to display names
- agent-priority-order: CORE_AGENT_ORDER uses display names
- tool-config-handler: look up agents by config key via agentByKey() helper
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').
- getSdkMessages now handles both response.data and direct array
responses from SDK
- Consolidated getMessageDir: storage.ts now re-exports from shared
opencode-message-dir.ts (with path traversal guards)
- Replace all response.data ?? [] with (response.data ?? response)
pattern across 14 files to handle SDK array-shaped responses
- Normalize SDK parts in parts-reader.ts by injecting sessionID/
messageID before validation (P1: SDK parts lack these fields)
- Treat unknown part types as having content in
recover-empty-content-message-sdk.ts to prevent false placeholder
injection on image/file parts
- Replace local isRecord with shared import in parts-reader.ts
- P1: Use compacted timestamp check instead of nonexistent truncated
field in target-token-truncation.ts
- P1: Use defensive (response.data ?? response) pattern in
hook-message-injector/injector.ts to match codebase convention
- P2: Filter by tool type in countTruncatedResultsFromSDK to avoid
counting non-tool compacted parts
- P2: Treat thinking/meta-only messages as empty in both
empty-content-recovery-sdk.ts and message-builder.ts to align
SDK path with file-based logic
- Re-read messages from SDK after injectTextPartAsync to prevent stale
snapshot from causing duplicate placeholder injection (P2)
- Replace local isRecord with shared import from record-type-guard (P3)
- P2: treat unknown part types as non-content in message-builder messageHasContentFromSDK
- P3: reuse shared isRecord from record-type-guard.ts in opencode-http-api