hermes-agent-features/tests/cli
Teknium 80a676658c fix(cli): surface self-improvement review summaries from bg thread
When the self-improvement background review fires after a turn, it runs
in a bg thread and emits a '  💾 <summary>' line to announce what it
saved to memory or skills. Two problems made this invisible to users
even when the review successfully modified a skill:

1. The print went through `_cprint` (prompt_toolkit's print_formatted_text)
   on a bg thread while the CLI's PromptSession was live. Direct
   print_formatted_text races with the input-area redraw and the line
   can land behind/above the prompt, scrolled off without the user
   seeing it.

2. The message said only '💾 Skill created.' / '💾 Memory updated'
   with no indication that the self-improvement loop was the one doing
   this. Users who did catch the line couldn't tell the background
   review from some other agent action.

Fixes:

- `_cprint` now detects when it's called from a non-app thread with a
  running prompt_toolkit Application, and routes through
  `run_in_terminal` via `loop.call_soon_threadsafe`. That pauses the
  input, prints the line above the prompt, and redraws — the normal
  prompt_toolkit contract for bg-thread output. Direct-print fallback
  preserved for the no-app / same-thread / import-error paths. Affects
  every bg-thread emission, not just the review summary (curator
  summaries and auxiliary failure prints benefit too).

- The summary now reads '  💾 Self-improvement review: <summary>' in
  both the CLI and the gateway `background_review_callback` path, so
  the origin is unambiguous.

Tests:
- New `tests/cli/test_cprint_bg_thread.py` covers all five routing
  branches (no app, app-not-running, cross-thread schedule, same-thread
  direct, app-loop-attribute-error, import-error).
- New case in `tests/run_agent/test_background_review.py` asserts the
  attributed prefix shows up in both `_safe_print` and
  `background_review_callback`.

Live E2E: exercised _cprint from a bg thread inside a real Application
event loop; confirmed get_app_or_none() sees the app, call_soon_threadsafe
schedules run_in_terminal, and the inner _pt_print runs.
2026-04-30 14:07:22 -07:00
..
__init__.py
test_branch_command.py
test_busy_input_mode_command.py
test_cli_approval_ui.py
test_cli_background_tui_refresh.py
test_cli_bracketed_paste_sanitizer.py
test_cli_browser_connect.py
test_cli_context_warning.py
test_cli_copy_command.py
test_cli_extension_hooks.py
test_cli_external_editor.py
test_cli_file_drop.py
test_cli_force_redraw.py
test_cli_image_command.py
test_cli_init.py
test_cli_interrupt_subagent.py
test_cli_loading_indicator.py
test_cli_markdown_rendering.py
test_cli_mcp_config_watch.py
test_cli_new_session.py
test_cli_prefix_matching.py
test_cli_preloaded_skills.py
test_cli_provider_resolution.py
test_cli_reload_skills.py
test_cli_retry.py
test_cli_save_config_value.py
test_cli_secret_capture.py
test_cli_shutdown_memory_messages.py
test_cli_skin_integration.py
test_cli_status_bar.py
test_cli_status_command.py
test_cli_steer_busy_path.py
test_cli_terminal_response_sanitizer.py
test_cli_tools_command.py
test_cli_user_message_preview.py
test_compress_focus.py
test_cprint_bg_thread.py fix(cli): surface self-improvement review summaries from bg thread 2026-04-30 14:07:22 -07:00
test_cwd_env_respect.py
test_fast_command.py
test_gquota_command.py
test_manual_compress.py
test_personality_none.py
test_quick_commands.py
test_reasoning_command.py
test_resume_display.py
test_save_conversation_location.py
test_session_boundary_hooks.py
test_stream_delta_think_tag.py
test_surrogate_sanitization.py
test_tool_progress_scrollback.py
test_worktree_security.py
test_worktree.py