hermes-agent/tests/cli
ethernet a4bc1ca502
fix(timeline): persist typed display events (#69771)
* fix(desktop): hide persisted agent-only history scaffolding

Filter verification-stop nudges and context-compaction handoffs at the
stored-history mapper boundary. Preserve a real reply when a compaction
handoff shares its stored message.

* test(desktop): build persisted E2E sessions through the real agent

Drive tui_gateway.entry over its stdio JSON-RPC transport against the mock
provider, wait for real completion events, and persist normal session history
through AIAgent and SessionDB. Migrate resume and hidden-history coverage,
including real compression and live verify-on-stop scaffolding, then remove
the unused direct SessionDB import scripts.

* fix(desktop): use the provisioned Python for real-session E2Es

Run the stdio gateway through uv's synced project environment outside the
Nix dev shell, while retaining the fully provisioned Nix Python when the
shell advertises HERMES_PYTHON_SRC_ROOT.

* fix(nix): expose the provisioned Python environment to uv

Mark the Nix-built Python environment active in the dev shell so the shared
E2E session builder can always run through `uv run --active --no-sync`.

* fix(timeline): persist typed display events

* fix(timeline): strip display-only fields from provider payloads, preserve through rewrites, fix /resume display history

Three review findings from PR #69771:

1. Provider payload leak: display_kind and display_metadata were forwarded
   to the provider API as unknown message fields. Strict OpenAI-compatible
   backends can reject the next request after a model switch or resumed
   typed event. Strip both from the per-request api_msg copy in
   conversation_loop alongside the existing api_content pop.

2. Rewrite/import data loss: _insert_message_rows preserved display_kind
   but silently dropped display_metadata. After replace_messages,
   archive_and_compact, or session import, async-delegation completion
   events lost their task counts and fell back to generic display text.
   Add display_metadata to the INSERT columns and bind tuple.

3. CLI /resume stale recap: startup --resume A set _resume_display_history
   from A's lineage. A subsequent in-session /resume B loaded B only into
   conversation_history via get_messages_as_conversation, leaving the stale
   A display projection. _display_resumed_history preferentially read the
   stale attribute, showing A's recap for B. Switch /resume to
   get_resume_conversations and update _resume_display_history alongside
   conversation_history.

Tests: 890 Python (5 files), 35 desktop TS — all green.

* feat(tui): render typed display events as ◈ markers in the Ink TUI

The TUI was not handling display_kind at all — model switch markers and
async delegation completions rendered as opaque user messages with the
full [System: ...] text, and hidden compaction handoffs were visible.

Wire display_kind through the full TUI chain:

- _history_to_messages (tui_gateway/server.py) forwards display_kind
  and display_metadata to the gateway transcript payload.
- GatewayTranscriptMessage (gatewayTypes.ts) gains both fields.
- Msg.kind (types.ts) gains 'event' value.
- toTranscriptMessages (domain/messages.ts) maps:
  - hidden → skip entirely
  - model_switch → event "model changed"
  - async_delegation_complete → event "N background agents finished"
    (or "background agent work finished" without metadata)
- messageGroup (blockLayout.ts) routes event to its own group, with
  SELF_SPACED + PAINTS_TRAILING_GAP so it owns its margins.
- messageLine.tsx renders event-kind as a dim ◈ marker with no gutter,
  matching the CLI's ◈ event rendering.
- 4 new TUI tests for hidden/model_switch/async_delegation mapping.

TUI typecheck: clean. TUI lint: 0 errors (2 pre-existing warnings).
TUI tests: 9 passed (1 pre-existing failure on main, unrelated).
2026-07-23 14:46:24 -04:00
..
__init__.py
test_bracketed_paste_timeout.py fix(cli): bracketed-paste timeout prevents permanent input freeze (#16263) 2026-05-25 05:07:11 -07:00
test_branch_command.py test: update mock assertions for conversation_history kwarg 2026-07-22 10:00:39 +05:30
test_busy_input_mode_command.py feat(busy): add 'steer' as a third display.busy_input_mode option (#16279) 2026-04-26 18:21:29 -07:00
test_chat_q_exit_clear.py fix(cli): preserve chat -q answer by gating exit-summary screen clear (#53009) 2026-07-08 07:59:24 -07:00
test_cli_active_agent_ref_wiring.py fix(cli): publish agent ref to cli module so memory on_session_end fires on exit 2026-06-19 16:59:43 -07:00
test_cli_approval_ui.py fix(approval): scope smart deny owner overrides to one operation 2026-07-13 04:31:55 -07:00
test_cli_async_delegation_delivery.py fix(cli): scope async delegation delivery to session 2026-07-14 22:14:10 -07:00
test_cli_background_status_indicator.py feat(cli): track background subagents in the status bar (#51441) 2026-06-23 11:09:08 -07:00
test_cli_background_tui_refresh.py chore: prune unused imports and duplicate import redefinitions 2026-05-28 22:26:25 -07:00
test_cli_bracketed_paste_sanitizer.py fix(cli): strip leaked bracketed-paste wrappers 2026-04-26 21:47:40 -07:00
test_cli_browser_connect.py test: stub discover_local_cdp_url in CLI connect context-note test 2026-07-18 02:49:28 -07:00
test_cli_codex_context_reference.py fix(context): scope Codex catalogue cache by credential 2026-07-21 04:29:34 -07:00
test_cli_context_warning.py fix(context): align guidance with 64k minimum 2026-05-24 23:23:12 -07:00
test_cli_copy_command.py feat: add /copy and /agents 2026-04-09 17:19:36 -05:00
test_cli_delegate_background_notice.py feat(cli): note background delegate_task dispatch in _on_tool_complete 2026-06-25 19:57:58 -05:00
test_cli_extension_hooks.py
test_cli_external_editor.py fix(cli,tui): recall real paste content on up-arrow 2026-07-20 23:23:40 -05:00
test_cli_file_drop.py chore: prune unused imports and duplicate import redefinitions 2026-05-28 22:26:25 -07:00
test_cli_force_redraw.py fix(cli): clear viewport on width-change resize so the status bar can't duplicate (#49120) 2026-06-19 08:43:42 -07:00
test_cli_goal_interrupt.py fix: migrate CLI kanban gate + remaining mocks to 5-value judge contract 2026-07-20 05:38:25 -07:00
test_cli_image_command.py fix(termux): harden execute_code and mobile browser/audio UX 2026-04-09 16:24:53 -07:00
test_cli_init.py refactor: drop platform kwarg, fix PTY test cleanup 2026-07-21 11:18:28 +05:30
test_cli_insights_command.py fix(cli): parse positional insights days 2026-05-12 14:56:47 -07:00
test_cli_interrupt_ack_race.py test(cli): cover noted multimodal persistence handoff 2026-07-14 03:32:46 +05:30
test_cli_interrupt_drain_regression.py fix(cli): re-land interrupt_queue drain so finished turns flush stray input 2026-07-01 00:12:32 -07:00
test_cli_interrupt_subagent.py fix(ci): make tests, workflows, and attribution reliable under load (#66373) 2026-07-17 20:55:24 +00:00
test_cli_light_mode.py fix(cli): stop OSC 11 bg probe from trapping users in a stray editor (#35441) 2026-05-30 11:55:12 -05:00
test_cli_loading_indicator.py fix: clean up defensive shims and finish CI stabilization from #17660 (#17801) 2026-04-29 23:53:17 -07:00
test_cli_markdown_rendering.py fix(cli): preserve cron asterisks in strip mode 2026-05-18 20:08:36 -07:00
test_cli_mcp_config_watch.py fix(mcp): move auto-reload opt-out to top-level mcp: section + regression tests 2026-07-20 00:41:05 -07:00
test_cli_new_session.py refactor: address Phase-2 review findings on /new boundary handoff 2026-07-09 03:21:54 +05:30
test_cli_pet_pane.py feat(pets): CLI pet pane + /pet command 2026-06-20 14:18:33 -05:00
test_cli_prefix_matching.py
test_cli_preloaded_skills.py
test_cli_provider_resolution.py fix(ci): rip out some xdist legacy stuff... how did these ever work?? 2026-06-26 19:15:18 -07:00
test_cli_reload_skills.py refactor(reload-skills): queue note for next turn, drop cache invalidation + agent tool 2026-04-29 21:07:47 -07:00
test_cli_resume_command.py fix(timeline): persist typed display events (#69771) 2026-07-23 14:46:24 -04:00
test_cli_retry.py
test_cli_save_config_value.py fix(cli): preserve config comments on setting writes 2026-05-09 17:55:12 -07:00
test_cli_secret_capture.py fix(cli): show masked feedback for secret prompts 2026-05-25 01:20:33 -07:00
test_cli_shift_enter_newline.py feat(cli): recognise Shift+Enter as a newline key 2026-05-08 16:26:51 -07:00
test_cli_shutdown_memory_messages.py fix(session): preserve clean shortened close snapshots 2026-07-14 03:32:46 +05:30
test_cli_skin_integration.py fix(tui): restore macOS copy behavior and theme polish (#17131) 2026-04-28 18:47:14 -05:00
test_cli_status_bar.py fix(test): pin monotonic clock in spinner-elapsed test to fix CI flake (#54203) 2026-06-28 04:16:25 -07:00
test_cli_status_command.py Revert "Merge pull request #30179 from NousResearch/feat/iron-proxy" 2026-07-04 13:38:59 -07:00
test_cli_steer_busy_path.py fix(cli): dispatch /steer inline while agent is running (#13354) 2026-04-20 23:05:38 -07:00
test_cli_terminal_response_sanitizer.py fix(cli): tighten mouse leak sanitizer 2026-04-29 22:10:18 -05:00
test_cli_terminal_shortcuts.py fix(cli): ignore terminal focus reports (salvage of #16780) 2026-05-29 00:31:44 -07:00
test_cli_tools_command.py chore: prune unused imports and duplicate import redefinitions 2026-05-28 22:26:25 -07:00
test_cli_user_message_preview.py feat(cli): improve multiline previews 2026-04-20 02:53:40 -07:00
test_cli_yolo_toggle.py fix(cli): /yolo in chat must enable session bypass, not just set env var 2026-05-28 12:10:21 -07:00
test_compress_flags.py feat(commands): /compact alias + --preview/--dry-run flags for /compress (#3243 salvage) 2026-07-02 05:10:31 -07:00
test_compress_focus.py feat: /compress <focus> — guided compression with focus topic (#8017) 2026-04-11 19:23:29 -07:00
test_compress_here.py fix: prevent stale lock-skip signal leaking between compress_context calls 2026-07-23 08:19:14 -07:00
test_compress_type_ahead.py test(cli): prove /compress type-ahead queue-drain; map contributor email 2026-07-23 07:24:46 -07:00
test_cpr_local_leak.py refactor: drop platform kwarg, fix PTY test cleanup 2026-07-21 11:18:28 +05:30
test_cprint_bg_thread.py fix: preserve ansi output history on resize replay 2026-05-14 15:14:29 -07:00
test_ctrl_enter_newline.py fix: preserve Ctrl+J newlines in Ghostty 2026-05-28 23:30:39 -07:00
test_cwd_env_respect.py chore: prune unused imports and duplicate import redefinitions 2026-05-28 22:26:25 -07:00
test_destructive_slash_confirm.py fix(cli): add inline --yes/now skip for destructive slash commands (#30768) 2026-05-24 16:13:03 -07:00
test_destructive_slash_inline_skip_e2e.py fix(cli): add inline --yes/now skip for destructive slash commands (#30768) 2026-05-24 16:13:03 -07:00
test_exit_delete_session.py feat(cli): add /exit --delete flag to remove session on quit (#27101) 2026-05-16 12:51:08 -07:00
test_exit_summary_resume_hint.py test(cli): cover exit resume hint -p flag across profiles 2026-05-25 01:41:54 -07:00
test_exit_watchdog_signal_arm.py fix(cli): arm exit watchdog on shutdown signal, not at chat startup (#66278) 2026-07-17 06:49:04 -07:00
test_fast_command.py fix: session-scoped /fast + full /new reset to config defaults (#67979) 2026-07-20 03:27:22 -07:00
test_manual_compress.py fix(compress): classify unconfirmed lock-acquire failures and cover all manual-compress surfaces 2026-07-23 08:19:14 -07:00
test_moa_command.py feat(moa): make /moa one-shot only; route preset switching through the model picker 2026-06-27 03:09:09 -07:00
test_partial_compress.py Inspired by Claude Code: /compress here [N] — boundary-aware 'summarize up to here' (#35048) 2026-05-29 17:49:15 -07:00
test_personality_none.py chore: prune unused imports and duplicate import redefinitions 2026-05-28 22:26:25 -07:00
test_prefill_config.py fix(config): align prefill messages key handling 2026-06-03 23:51:44 -06:00
test_prepend_note_to_message.py refactor(cli): normalize note and avoid blank lines in prepend helper 2026-06-01 20:30:08 -07:00
test_prompt_text_input_thread_safety.py feat(billing): /billing terminal billing — interactive TUI + CLI client (#45449) 2026-06-19 01:53:32 +05:30
test_quick_commands.py fix(ci): rip out some xdist legacy stuff... how did these ever work?? 2026-06-26 19:15:18 -07:00
test_reasoning_command.py fix: session-scoped /fast + full /new reset to config defaults (#67979) 2026-07-20 03:27:22 -07:00
test_resume_display.py fix(timeline): persist typed display events (#69771) 2026-07-23 14:46:24 -04:00
test_resume_quiet_stderr.py chore: prune unused imports and duplicate import redefinitions 2026-05-28 22:26:25 -07:00
test_save_conversation_location.py chore: prune unused imports and duplicate import redefinitions 2026-05-28 22:26:25 -07:00
test_session_boundary_hooks.py feat(observability): observer-grade telemetry hooks + NeMo-Relay plugin 2026-06-03 06:36:46 -07:00
test_single_query_session_finalize.py test(cli): update FakeCLI._print_exit_summary for new clear_screen kwarg 2026-07-08 07:59:24 -07:00
test_slash_command_interrupt.py chore: prune unused imports and duplicate import redefinitions 2026-05-28 22:26:25 -07:00
test_slash_confirm_windows.py test(cli): exercise real _prompt_text_input for native-Windows confirm deadlock 2026-06-08 15:53:28 -07:00
test_steer_inline_repaint_34569.py fix(cli): repaint input area after inline /steer and /model submit (#34839) 2026-05-29 19:04:40 -07:00
test_stream_delta_think_tag.py fix: make streaming reasoning-tag filter case-insensitive 2026-07-01 03:25:02 -07:00
test_stream_partial_line_flush.py perf(cli): TTFT round 2 — live reasoning by default, partial-line streaming, prompt-build cache, stale budget-warning docs (#59389) 2026-07-06 00:16:38 -07:00
test_surrogate_sanitization.py chore: prune unused imports and duplicate import redefinitions 2026-05-28 22:26:25 -07:00
test_terminal_interrupt_recovery.py refactor(cli): extract interrupt recovery to a testable helper 2026-06-28 01:08:09 -07:00
test_tool_progress_scrollback.py feat(moa): show each reference model's output as a labelled block before the aggregator (#53793) 2026-06-27 12:45:23 -07:00
test_tui_terminal_reset_on_exit.py fix(cli): reset terminal input modes on TUI exit to stop focus/mouse leaks 2026-06-01 23:27:44 +08:00
test_update_command.py rip out brew + pip/PyPI wheel support (#68217) 2026-07-22 16:51:01 -04:00
test_version_command.py Add /version slash command across CLI, gateway, TUI, and desktop. 2026-06-05 18:05:05 -07:00
test_worktree.py fix(cli): widen startup worktree pruning to all .worktrees/ trees and detect squash-merged work (#69831) 2026-07-23 07:33:07 -07:00
test_worktree_security.py
test_worktree_sync_base.py fix(cli): branch new worktrees from the fresh remote tip, not stale local HEAD (#50355) 2026-06-21 12:42:11 -07:00