comate-cli 0.7.0a8__tar.gz → 0.7.0a9__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (175) hide show
  1. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/PKG-INFO +1 -1
  2. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/terminal_agent/animations.py +29 -5
  3. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/terminal_agent/event_renderer.py +17 -5
  4. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/terminal_agent/tui.py +1 -1
  5. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/terminal_agent/tui_parts/render_panels.py +45 -10
  6. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/pyproject.toml +1 -1
  7. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_completion_status_panel.py +43 -0
  8. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_event_renderer_streaming.py +32 -1
  9. comate_cli-0.7.0a9/tests/test_tui_thinking_display.py +71 -0
  10. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/.gitignore +0 -0
  11. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/AGENTS.md +0 -0
  12. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/CHANGELOG.md +0 -0
  13. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/README.md +0 -0
  14. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/bash-exit-code-green-dot-bug.md +0 -0
  15. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/__init__.py +0 -0
  16. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/__main__.py +0 -0
  17. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/main.py +0 -0
  18. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/mcp_cli.py +0 -0
  19. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/terminal_agent/__init__.py +0 -0
  20. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/terminal_agent/app.py +0 -0
  21. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/terminal_agent/assistant_render.py +0 -0
  22. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/terminal_agent/codenames.py +0 -0
  23. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/terminal_agent/custom_slash_commands.py +0 -0
  24. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/terminal_agent/env_utils.py +0 -0
  25. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/terminal_agent/error_display.py +0 -0
  26. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/terminal_agent/figures.py +0 -0
  27. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/terminal_agent/fragment_utils.py +0 -0
  28. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/terminal_agent/history_printer.py +0 -0
  29. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/terminal_agent/input_geometry.py +0 -0
  30. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/terminal_agent/layout_coordinator.py +0 -0
  31. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/terminal_agent/logging_adapter.py +0 -0
  32. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/terminal_agent/logo.py +0 -0
  33. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/terminal_agent/markdown_render.py +0 -0
  34. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/terminal_agent/mention_completer.py +0 -0
  35. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/terminal_agent/message_style.py +0 -0
  36. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/terminal_agent/models.py +0 -0
  37. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/terminal_agent/path_context_hint.py +0 -0
  38. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/terminal_agent/plugins/__init__.py +0 -0
  39. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/terminal_agent/plugins/components/__init__.py +0 -0
  40. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/terminal_agent/plugins/components/detail_view.py +0 -0
  41. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/terminal_agent/plugins/components/plugin_list.py +0 -0
  42. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/terminal_agent/plugins/components/search_box.py +0 -0
  43. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/terminal_agent/plugins/components/tab_bar.py +0 -0
  44. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/terminal_agent/plugins/marketplace_install_view.py +0 -0
  45. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/terminal_agent/plugins/plugin_picker.py +0 -0
  46. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/terminal_agent/plugins/tabs/__init__.py +0 -0
  47. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/terminal_agent/plugins/tabs/discover_tab.py +0 -0
  48. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/terminal_agent/plugins/tabs/errors_tab.py +0 -0
  49. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/terminal_agent/plugins/tabs/installed_tab.py +0 -0
  50. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/terminal_agent/plugins/tabs/marketplaces_tab.py +0 -0
  51. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/terminal_agent/preflight.py +0 -0
  52. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/terminal_agent/question_view.py +0 -0
  53. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/terminal_agent/resume_picker.py +0 -0
  54. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/terminal_agent/resume_preview.py +0 -0
  55. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/terminal_agent/resume_selector.py +0 -0
  56. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/terminal_agent/rpc_protocol.py +0 -0
  57. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/terminal_agent/rpc_stdio.py +0 -0
  58. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/terminal_agent/selection_menu.py +0 -0
  59. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/terminal_agent/slash_commands.py +0 -0
  60. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/terminal_agent/startup.py +0 -0
  61. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/terminal_agent/status_bar.py +0 -0
  62. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/terminal_agent/text_effects.py +0 -0
  63. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/terminal_agent/tips.py +0 -0
  64. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/terminal_agent/tool_fold.py +0 -0
  65. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/terminal_agent/tool_result_formatters.py +0 -0
  66. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/terminal_agent/tool_result_store.py +0 -0
  67. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/terminal_agent/tool_result_viewer.py +0 -0
  68. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/terminal_agent/tool_view.py +0 -0
  69. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/terminal_agent/transcript_viewer.py +0 -0
  70. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/terminal_agent/tui_parts/__init__.py +0 -0
  71. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/terminal_agent/tui_parts/btw_view.py +0 -0
  72. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/terminal_agent/tui_parts/commands.py +0 -0
  73. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/terminal_agent/tui_parts/history_sync.py +0 -0
  74. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/terminal_agent/tui_parts/input_behavior.py +0 -0
  75. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/terminal_agent/tui_parts/key_bindings.py +0 -0
  76. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/terminal_agent/tui_parts/mcp_connecting_view.py +0 -0
  77. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/terminal_agent/tui_parts/slash_command_registry.py +0 -0
  78. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/comate_cli/terminal_agent/tui_parts/ui_mode.py +0 -0
  79. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/docs/hooks.md +0 -0
  80. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/docs/superpowers/plans/2026-04-03-phrase-shuffle.md +0 -0
  81. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/docs/superpowers/specs/2026-04-01-conditional-diff-subtitle-design.md +0 -0
  82. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/docs/superpowers/specs/2026-04-03-phrase-shuffle-design.md +0 -0
  83. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/report.md +0 -0
  84. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/conftest.py +0 -0
  85. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/fixtures/fake_mcp_misbehaving_stdout.py +0 -0
  86. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_animator_shuffle.py +0 -0
  87. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_app_mcp_preload.py +0 -0
  88. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_app_preflight_gate.py +0 -0
  89. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_app_print_mode.py +0 -0
  90. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_app_shutdown.py +0 -0
  91. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_app_usage_line.py +0 -0
  92. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_btw_slash_command.py +0 -0
  93. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_cli_project_root.py +0 -0
  94. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_compact_command_semantics.py +0 -0
  95. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_completion_context_activation.py +0 -0
  96. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_context_command.py +0 -0
  97. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_custom_slash_commands.py +0 -0
  98. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_discover_tab.py +0 -0
  99. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_errors_tab.py +0 -0
  100. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_event_renderer.py +0 -0
  101. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_event_renderer_boundary.py +0 -0
  102. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_event_renderer_e2e.py +0 -0
  103. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_event_renderer_log_boundary.py +0 -0
  104. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_event_renderer_log_queue.py +0 -0
  105. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_event_renderer_tool_fold.py +0 -0
  106. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_format_error.py +0 -0
  107. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_handle_error.py +0 -0
  108. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_history_printer.py +0 -0
  109. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_history_printer_log.py +0 -0
  110. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_history_printer_subtitle_position.py +0 -0
  111. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_history_printer_tool_fold.py +0 -0
  112. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_history_sync.py +0 -0
  113. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_history_sync_tool_fold.py +0 -0
  114. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_input_behavior.py +0 -0
  115. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_input_history.py +0 -0
  116. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_installed_tab.py +0 -0
  117. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_interrupt_exit_semantics.py +0 -0
  118. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_layout_coordinator.py +0 -0
  119. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_logging_adapter.py +0 -0
  120. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_logo.py +0 -0
  121. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_main_args.py +0 -0
  122. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_markdown_render.py +0 -0
  123. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_marketplaces_tab.py +0 -0
  124. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_mcp_cli.py +0 -0
  125. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_mcp_slash_command.py +0 -0
  126. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_mention_completer.py +0 -0
  127. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_path_context_hint.py +0 -0
  128. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_plugin_slash_commands.py +0 -0
  129. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_plugin_tui_components.py +0 -0
  130. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_preflight.py +0 -0
  131. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_preflight_copilot.py +0 -0
  132. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_question_key_bindings.py +0 -0
  133. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_question_view.py +0 -0
  134. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_resume_picker.py +0 -0
  135. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_resume_preview.py +0 -0
  136. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_resume_selector.py +0 -0
  137. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_rewind_command_semantics.py +0 -0
  138. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_rpc_protocol.py +0 -0
  139. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_rpc_stdio_bridge.py +0 -0
  140. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_selection_menu.py +0 -0
  141. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_session_query_token_summary.py +0 -0
  142. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_shutdown_noise_guard.py +0 -0
  143. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_shutdown_noise_integration.py +0 -0
  144. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_skills_slash_command.py +0 -0
  145. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_slash_argument_hint.py +0 -0
  146. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_slash_clear.py +0 -0
  147. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_slash_completer.py +0 -0
  148. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_slash_registry.py +0 -0
  149. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_status_bar.py +0 -0
  150. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_status_bar_transient.py +0 -0
  151. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_task_panel_format.py +0 -0
  152. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_task_panel_key_bindings.py +0 -0
  153. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_task_panel_rendering.py +0 -0
  154. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_task_poll.py +0 -0
  155. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_tool_fold.py +0 -0
  156. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_tool_fold_panel.py +0 -0
  157. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_tool_result_formatters.py +0 -0
  158. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_tool_result_store.py +0 -0
  159. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_tool_result_viewer.py +0 -0
  160. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_tool_result_viewer_key_bindings.py +0 -0
  161. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_tool_view.py +0 -0
  162. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_transcript_viewer.py +0 -0
  163. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_transcript_viewer_tool_fold.py +0 -0
  164. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_tui_elapsed_status.py +0 -0
  165. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_tui_esc_queue.py +0 -0
  166. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_tui_mcp_init_gate.py +0 -0
  167. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_tui_paste_newline_guard.py +0 -0
  168. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_tui_paste_placeholder.py +0 -0
  169. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_tui_queue_preview.py +0 -0
  170. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_tui_queue_sdk_source.py +0 -0
  171. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_tui_split_invariance.py +0 -0
  172. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_tui_team_messages.py +0 -0
  173. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_tui_tool_result_registry_lifecycle.py +0 -0
  174. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/tests/test_update_check.py +0 -0
  175. {comate_cli-0.7.0a8 → comate_cli-0.7.0a9}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: comate-cli
3
- Version: 0.7.0a8
3
+ Version: 0.7.0a9
4
4
  Summary: Comate terminal CLI built on comate-agent-sdk
5
5
  Project-URL: Homepage, https://github.com/AndyLee1024/agent-sdk
6
6
  Project-URL: Repository, https://github.com/AndyLee1024/agent-sdk
@@ -9,7 +9,7 @@ from enum import Enum
9
9
  from rich.console import RenderableType
10
10
  from rich.text import Text
11
11
 
12
- from comate_agent_sdk.agent.events import StopEvent, TextEvent, ToolCallEvent, ToolResultEvent, UserQuestionEvent
12
+ from comate_agent_sdk.agent.events import StopEvent, ToolCallEvent, ToolResultEvent, UserQuestionEvent
13
13
 
14
14
  from comate_cli.terminal_agent.figures import (
15
15
  BREATH_DOT_GLYPHS as _FIGURES_BREATH_DOT_GLYPHS,
@@ -238,6 +238,27 @@ BREATH_DOT_COLORS: tuple[str, ...] = (
238
238
  )
239
239
  BREATH_DOT_GLYPHS: tuple[str, ...] = _FIGURES_BREATH_DOT_GLYPHS
240
240
 
241
+ LOADING_SPINNER_FRAMES: tuple[str, ...] = (
242
+ "⠋",
243
+ "⠙",
244
+ "⠹",
245
+ "⠸",
246
+ "⠼",
247
+ "⠴",
248
+ "⠦",
249
+ "⠧",
250
+ "⠇",
251
+ "⠏",
252
+ )
253
+
254
+ HIDDEN_THINKING_BADGES: tuple[str, ...] = (
255
+ "ultra thinking",
256
+ "deep reasoning",
257
+ "thinking deeper",
258
+ "extended thinking",
259
+ "working through it",
260
+ )
261
+
241
262
 
242
263
  def breathing_dot_color(frame: int) -> str:
243
264
  """Return the breathing dot color for a given animation frame."""
@@ -252,6 +273,11 @@ def breathing_dot_glyph(now_monotonic: float | None = None) -> str:
252
273
  return BREATH_DOT_GLYPHS[phase]
253
274
 
254
275
 
276
+ def loading_spinner_glyph(frame: int) -> str:
277
+ """Return the compact spinner glyph for the main loading line."""
278
+ return LOADING_SPINNER_FRAMES[frame % len(LOADING_SPINNER_FRAMES)]
279
+
280
+
255
281
  def _lerp_rgb(
256
282
  start_rgb: tuple[int, int, int],
257
283
  end_rgb: tuple[int, int, int],
@@ -385,11 +411,9 @@ class SubmissionAnimator:
385
411
  return Text("")
386
412
 
387
413
  phrase = self._status_hint if self._status_hint else (self._shuffled[self._phrase_idx] + ELLIPSIS)
388
- dot_color = breathing_dot_color(self._frame)
389
- now_monotonic = time.monotonic()
390
414
  dot = Text(
391
- f"{breathing_dot_glyph(now_monotonic)} ",
392
- style=f"bold {dot_color}",
415
+ f"{loading_spinner_glyph(self._frame)} ",
416
+ style="bold #9CA3AF",
393
417
  )
394
418
  sweep = _cyan_sweep_text(phrase, frame=self._frame)
395
419
  return Text.assemble(dot, sweep)
@@ -1,6 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import logging
4
+ import random
4
5
  import re
5
6
  import threading
6
7
  import time
@@ -37,6 +38,7 @@ from comate_agent_sdk.agent.events import (
37
38
  from rich.console import RenderableType
38
39
  from rich.text import Text
39
40
 
41
+ from comate_cli.terminal_agent.animations import HIDDEN_THINKING_BADGES
40
42
  from comate_cli.terminal_agent.figures import (
41
43
  BOTTOM_LEFT_CROP,
42
44
  BULLET_OPERATOR,
@@ -292,6 +294,7 @@ class EventRenderer:
292
294
  self._show_thinking_cb: Callable[[], bool] = lambda: True
293
295
  self._turn_received_text_delta: bool = False
294
296
  self._turn_received_thinking_delta: bool = False
297
+ self._hidden_thinking_badge_text: str = ""
295
298
  self._text_delta_started: bool = False
296
299
  self._active_text_message_id: str | None = None
297
300
  # ━━━━━ spec §4.1 新管道状态字段(Phase 1.2 引入,Phase 4-6 接入) ━━━━━
@@ -473,6 +476,10 @@ class EventRenderer:
473
476
  """
474
477
  if not delta:
475
478
  return
479
+ if self._show_thinking_cb():
480
+ self._hidden_thinking_badge_text = ""
481
+ elif not self._hidden_thinking_badge_text:
482
+ self._hidden_thinking_badge_text = random.choice(HIDDEN_THINKING_BADGES)
476
483
  self._thinking_batch += delta
477
484
  while "\n" in self._thinking_batch:
478
485
  line, self._thinking_batch = self._thinking_batch.split("\n", 1)
@@ -564,6 +571,7 @@ class EventRenderer:
564
571
  """
565
572
  if not delta:
566
573
  return
574
+ self._hidden_thinking_badge_text = ""
567
575
  if self._thinking_batch:
568
576
  self._flush_thinking_batch()
569
577
  self._text_pending += delta
@@ -604,6 +612,7 @@ class EventRenderer:
604
612
  self._flush_thinking_batch()
605
613
  # ⑤ aux
606
614
  self._loading_aux_text = ""
615
+ self._hidden_thinking_badge_text = ""
607
616
 
608
617
  def _drop_all_pending(self) -> None:
609
618
  """spec §6.4:interrupt_turn 调用。
@@ -614,6 +623,7 @@ class EventRenderer:
614
623
  self._container = None
615
624
  self._thinking_batch = ""
616
625
  self._loading_aux_text = ""
626
+ self._hidden_thinking_badge_text = ""
617
627
  self._text_delta_started = False
618
628
  self._active_text_message_id = None
619
629
 
@@ -657,6 +667,7 @@ class EventRenderer:
657
667
  self._container = None
658
668
  self._thinking_batch = ""
659
669
  self._loading_aux_text = ""
670
+ self._hidden_thinking_badge_text = ""
660
671
  self._rebuild_loading_line()
661
672
 
662
673
  def seed_user_message(
@@ -775,6 +786,7 @@ class EventRenderer:
775
786
  self._thinking_batch = ""
776
787
  self._loading_aux_text = ""
777
788
  self._loading_state = LoadingState.idle()
789
+ self._hidden_thinking_badge_text = ""
778
790
  self._current_tasks = []
779
791
  self._current_task_title = None
780
792
  self._task_started_at_monotonic = None
@@ -830,6 +842,10 @@ class EventRenderer:
830
842
  拼接到 spinner phrase。无容器时返回 ""。"""
831
843
  return self._loading_aux_text
832
844
 
845
+ def hidden_thinking_badge_text(self) -> str:
846
+ """Return the loading-line badge shown while hidden thinking streams."""
847
+ return self._hidden_thinking_badge_text
848
+
833
849
  def append_subtitle(
834
850
  self,
835
851
  text: str,
@@ -1210,11 +1226,6 @@ class EventRenderer:
1210
1226
  if state.is_task:
1211
1227
  subagent_name = state.subagent_name or "Agent"
1212
1228
  description = state.subagent_description or state.title
1213
- if description and description != subagent_name:
1214
- task_title = f"{subagent_name}({description})"
1215
- else:
1216
- task_title = subagent_name
1217
-
1218
1229
  model_name = ""
1219
1230
  if metadata and isinstance(metadata, dict):
1220
1231
  model_name = metadata.get("model_name", "")
@@ -1617,6 +1628,7 @@ class EventRenderer:
1617
1628
  self._pending_tool_starts.clear()
1618
1629
  # Safety net: if any running tool rows remain, stop event means this turn is ending.
1619
1630
  self._running_tools.clear()
1631
+ self._hidden_thinking_badge_text = ""
1620
1632
  self._rebuild_loading_line()
1621
1633
  if reason == "waiting_for_input":
1622
1634
  return (True, None)
@@ -189,7 +189,7 @@ class TerminalAgentTUI(
189
189
  self._pending_questions: list[dict[str, Any]] | None = None
190
190
  self._pending_plan_approval: dict[str, str] | None = None
191
191
  self._ui_mode = UIMode.NORMAL
192
- self._show_thinking = True # Ctrl+T 开关,默认打开
192
+ self._show_thinking = False # Ctrl+T 开关,默认关闭
193
193
  self._renderer._show_thinking_cb = lambda: self._show_thinking
194
194
 
195
195
  self._custom_slash_commands: dict[str, CustomSlashCommand] = {}
@@ -9,7 +9,12 @@ from rich.console import Console
9
9
 
10
10
  from comate_agent_sdk.agent.queue_types import MessageOrigin, QueuedMessage
11
11
 
12
- from comate_cli.terminal_agent.animations import _cyan_sweep_text, breathing_dot_color, breathing_dot_glyph
12
+ from comate_cli.terminal_agent.animations import (
13
+ _cyan_sweep_text,
14
+ breathing_dot_color,
15
+ breathing_dot_glyph,
16
+ loading_spinner_glyph,
17
+ )
13
18
  from comate_cli.terminal_agent.figures import (
14
19
  BOTTOM_LEFT_CROP,
15
20
  BULLET,
@@ -18,7 +23,6 @@ from comate_cli.terminal_agent.figures import (
18
23
  DOWN_ARROW,
19
24
  ELLIPSIS,
20
25
  FAST_PLAY_ICON,
21
- HEAVY_HORIZONTAL,
22
26
  PAUSE_ICON,
23
27
  TASK_IN_PROGRESS,
24
28
  TASK_PENDING,
@@ -480,6 +484,7 @@ class RenderPanelsMixin:
480
484
  if self._animator.is_active:
481
485
  renderable = self._animator.renderable()
482
486
  frags = self._rich_text_to_pt_fragments(renderable)
487
+ frags = self._append_hidden_thinking_badge_fragment(frags)
483
488
  return self._append_loading_tip_fragment(
484
489
  self._append_run_elapsed_fragment(frags)
485
490
  )
@@ -500,9 +505,31 @@ class RenderPanelsMixin:
500
505
  phrase = f"{phrase} {BULLET_OPERATOR} {aux}"
501
506
 
502
507
  return self._append_loading_tip_fragment(
503
- self._animated_loading_fragments(phrase)
508
+ self._animated_loading_fragments(
509
+ phrase,
510
+ badge=self._hidden_thinking_badge_text(),
511
+ )
504
512
  )
505
513
 
514
+ def _hidden_thinking_badge_text(self) -> str:
515
+ badge_fn = getattr(self._renderer, "hidden_thinking_badge_text", None)
516
+ if not callable(badge_fn):
517
+ return ""
518
+ return str(badge_fn() or "").strip()
519
+
520
+ def _append_hidden_thinking_badge_fragment(
521
+ self,
522
+ frags: list[tuple[str, str]],
523
+ ) -> list[tuple[str, str]]:
524
+ badge = self._hidden_thinking_badge_text()
525
+ if not badge:
526
+ return frags
527
+ tail: list[tuple[str, str]] = []
528
+ trimmed = list(frags)
529
+ while trimmed and trimmed[-1][1] == "\n":
530
+ tail.insert(0, trimmed.pop())
531
+ return trimmed + [("", " "), ("fg:#FBBF24 bold", badge)] + tail
532
+
506
533
  def _visible_loading_tip(self) -> str:
507
534
  tip = str(getattr(self, "_loading_tip_text", "") or "").strip()
508
535
  if not tip:
@@ -534,9 +561,15 @@ class RenderPanelsMixin:
534
561
  def _loading_height_with_tip(self) -> int:
535
562
  return 2 if self._visible_loading_tip() else 1
536
563
 
537
- def _animated_loading_fragments(self, phrase: str) -> list[tuple[str, str]]:
538
- """用与工具调用一致的呼吸圆点 + 流光走字渲染 loading 文案."""
564
+ def _animated_loading_fragments(
565
+ self,
566
+ phrase: str,
567
+ *,
568
+ badge: str = "",
569
+ ) -> list[tuple[str, str]]:
570
+ """用低噪音 spinner + 流光走字渲染 loading 文案."""
539
571
  width = self._terminal_width()
572
+ badge = badge.strip()
540
573
 
541
574
  # 若正在计时,预先计算时间后缀宽度,给 phrase 预留空间
542
575
  run_start: float | None = getattr(self, "_run_start_time", None)
@@ -547,21 +580,23 @@ class RenderPanelsMixin:
547
580
  f" ({self._format_run_elapsed(elapsed)} • ctrl+c to interrupt)"
548
581
  )
549
582
 
550
- # glyph(1) + space(1) = 2,再减去时间后缀宽度
551
- phrase_budget = width - 4 - get_cwidth(elapsed_suffix)
583
+ badge_suffix = f" {badge}" if badge else ""
584
+
585
+ # glyph(1) + space(1) = 2,再减去 badge / 时间后缀宽度
586
+ phrase_budget = width - 2 - get_cwidth(badge_suffix) - get_cwidth(elapsed_suffix)
552
587
  clipped = fit_single_line(phrase, max(phrase_budget, 8))
553
588
 
554
589
  frame = self._loading_frame
555
- dot_color = breathing_dot_color(frame)
556
- now_monotonic = time.monotonic()
557
590
 
558
591
  # 构建 Rich Text(与 SubmissionAnimator.renderable 相同结构)
559
592
  from rich.text import Text as RichText
560
593
 
561
- dot = RichText(f"{breathing_dot_glyph(now_monotonic)} ", style=f"bold {dot_color}")
594
+ dot = RichText(f"{loading_spinner_glyph(frame)} ", style="bold #9CA3AF")
562
595
  sweep = _cyan_sweep_text(clipped, frame=frame)
563
596
  combined = RichText.assemble(dot, sweep)
564
597
  frags = self._rich_text_to_pt_fragments(combined)
598
+ if badge:
599
+ frags = frags + [("", " "), ("fg:#FBBF24 bold", badge)]
565
600
  if elapsed_suffix:
566
601
  frags = frags + [("fg:#6B7280", elapsed_suffix)]
567
602
  return frags
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "comate-cli"
7
- version = "0.7.0a8"
7
+ version = "0.7.0a9"
8
8
  description = "Comate terminal CLI built on comate-agent-sdk"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -56,6 +56,7 @@ class _FakeRenderer:
56
56
  self.running_subagents = False
57
57
  self.running_tools = False
58
58
  self.auto_compacting = False
59
+ self.hidden_thinking_badge = ""
59
60
  self.todo_lines: list[str] = []
60
61
  self.tool_entries: list[tuple[int, str]] = [(0, "Agent(task) · 1s · +1 tool uses")]
61
62
 
@@ -77,6 +78,9 @@ class _FakeRenderer:
77
78
  def loading_aux_text(self) -> str:
78
79
  return ""
79
80
 
81
+ def hidden_thinking_badge_text(self) -> str:
82
+ return self.hidden_thinking_badge
83
+
80
84
  def compute_required_tool_panel_lines(self) -> int:
81
85
  return len(self.tool_entries)
82
86
 
@@ -291,6 +295,45 @@ class TestCompletionStatusPanel(unittest.TestCase):
291
295
  self.assertNotIn("Tip:", text)
292
296
  self.assertEqual(tui._loading_height(), 1)
293
297
 
298
+ def test_loading_text_uses_braille_spinner(self) -> None:
299
+ tui = _FakeTUI(None, width=80)
300
+ tui._busy = True
301
+ tui._loading_frame = 0
302
+
303
+ text = _join_fragments(tui._loading_text())
304
+
305
+ self.assertTrue(text.startswith("⠋ Thinking"))
306
+ self.assertNotIn("○ Thinking", text)
307
+
308
+ def test_loading_text_appends_hidden_thinking_badge_after_phrase(self) -> None:
309
+ tui = _FakeTUI(None, width=80)
310
+ tui._busy = True
311
+ tui._renderer.hidden_thinking_badge = "ultra thinking"
312
+
313
+ fragments = tui._loading_text()
314
+ text = _join_fragments(fragments)
315
+
316
+ self.assertIn("Thinking ultra thinking", text)
317
+ self.assertTrue(
318
+ any(
319
+ style == "fg:#FBBF24 bold" and badge == "ultra thinking"
320
+ for style, badge in fragments
321
+ )
322
+ )
323
+
324
+ def test_loading_text_appends_hidden_thinking_badge_to_active_animator(self) -> None:
325
+ tui = _FakeTUI(None, width=80)
326
+ tui._busy = True
327
+ tui._renderer.hidden_thinking_badge = "deep reasoning"
328
+ tui._animator = SimpleNamespace(
329
+ is_active=True,
330
+ renderable=lambda: Text("Generating..."),
331
+ )
332
+
333
+ text = _join_fragments(tui._loading_text())
334
+
335
+ self.assertIn("Generating... deep reasoning", text)
336
+
294
337
  def test_loading_tip_renders_as_temporary_subtitle_line(self) -> None:
295
338
  tui = _FakeTUI(None, width=80)
296
339
  tui._busy = True
@@ -12,7 +12,6 @@ from comate_agent_sdk.agent.events import (
12
12
  from comate_cli.terminal_agent.event_renderer import (
13
13
  ContainerState,
14
14
  EventRenderer,
15
- FenceMatch,
16
15
  )
17
16
 
18
17
 
@@ -61,6 +60,38 @@ class TestQ11Fallback(unittest.TestCase):
61
60
  # delta 路径仍待 batch flush,TextEvent 不补 thinking entry
62
61
  self.assertEqual(thinking_entries, [])
63
62
 
63
+ def test_hidden_thinking_delta_exposes_loading_badge_without_history(self) -> None:
64
+ renderer = EventRenderer()
65
+ renderer._show_thinking_cb = lambda: False
66
+ renderer.start_turn()
67
+
68
+ renderer.handle_event(ThinkingDeltaEvent(delta="hidden reasoning\n", message_id="m1"))
69
+
70
+ thinking_entries = [
71
+ entry for entry in renderer.history_entries() if entry.entry_type == "thinking"
72
+ ]
73
+ self.assertEqual(thinking_entries, [])
74
+ self.assertIn(
75
+ renderer.hidden_thinking_badge_text(),
76
+ {
77
+ "ultra thinking",
78
+ "deep reasoning",
79
+ "thinking deeper",
80
+ "extended thinking",
81
+ "working through it",
82
+ },
83
+ )
84
+
85
+ def test_hidden_thinking_badge_clears_when_text_stream_starts(self) -> None:
86
+ renderer = EventRenderer()
87
+ renderer._show_thinking_cb = lambda: False
88
+ renderer.start_turn()
89
+ renderer.handle_event(ThinkingDeltaEvent(delta="hidden reasoning", message_id="m1"))
90
+
91
+ renderer.handle_event(TextDeltaEvent(delta="answer", message_id="m1"))
92
+
93
+ self.assertEqual(renderer.hidden_thinking_badge_text(), "")
94
+
64
95
  def test_thinking_event_legacy_fallback_when_no_delta(self) -> None:
65
96
  renderer = EventRenderer()
66
97
  renderer.start_turn()
@@ -0,0 +1,71 @@
1
+ from __future__ import annotations
2
+
3
+ import unittest
4
+ from pathlib import Path
5
+ from types import SimpleNamespace
6
+ from unittest.mock import patch
7
+
8
+ from prompt_toolkit.history import InMemoryHistory
9
+
10
+ from comate_cli.terminal_agent.tui import TerminalAgentTUI
11
+
12
+
13
+ class _FakeStatusBar:
14
+ def set_mode(self, _mode: str) -> None:
15
+ return None
16
+
17
+
18
+ class _FakeRenderer:
19
+ def __init__(self) -> None:
20
+ self._show_thinking_cb = lambda: True
21
+
22
+ def set_tool_result_registry(self, _registry: object) -> None:
23
+ return None
24
+
25
+ def append_system_message(self, *_args, **_kwargs) -> None:
26
+ return None
27
+
28
+ def has_active_todos(self) -> bool:
29
+ return False
30
+
31
+ def has_running_tools(self) -> bool:
32
+ return False
33
+
34
+
35
+ class _FakeSession:
36
+ session_id = "session-1"
37
+ _cwd = Path.cwd()
38
+
39
+ def __init__(self) -> None:
40
+ self._agent = SimpleNamespace(
41
+ _team=SimpleNamespace(team_message_event_callback=None),
42
+ _runtime_state=SimpleNamespace(skills=[]),
43
+ )
44
+
45
+ def get_mode(self) -> str:
46
+ return "act"
47
+
48
+
49
+ class TestTuiThinkingDisplay(unittest.TestCase):
50
+ def test_thinking_display_defaults_to_hidden(self) -> None:
51
+ renderer = _FakeRenderer()
52
+
53
+ with (
54
+ patch(
55
+ "comate_cli.terminal_agent.tui.discover_custom_slash_commands",
56
+ return_value=SimpleNamespace(warnings=(), commands=()),
57
+ ),
58
+ patch.object(
59
+ TerminalAgentTUI,
60
+ "_create_input_history",
61
+ return_value=InMemoryHistory(),
62
+ ),
63
+ ):
64
+ tui = TerminalAgentTUI(_FakeSession(), _FakeStatusBar(), renderer) # type: ignore[arg-type]
65
+
66
+ self.assertFalse(tui._show_thinking)
67
+ self.assertFalse(renderer._show_thinking_cb())
68
+
69
+
70
+ if __name__ == "__main__":
71
+ unittest.main()
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes