comate-cli 0.7.0a10__tar.gz → 0.7.1__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 (199) hide show
  1. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/.gitignore +3 -0
  2. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/PKG-INFO +1 -1
  3. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/animations.py +2 -4
  4. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/app.py +5 -0
  5. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/logo.py +4 -1
  6. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/preflight.py +24 -6
  7. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/slash_commands.py +5 -0
  8. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/status_bar.py +210 -26
  9. comate_cli-0.7.1/comate_cli/terminal_agent/statusline/model.py +60 -0
  10. comate_cli-0.7.1/comate_cli/terminal_agent/statusline/picker.py +183 -0
  11. comate_cli-0.7.1/comate_cli/terminal_agent/statusline/picker_state.py +103 -0
  12. comate_cli-0.7.1/comate_cli/terminal_agent/statusline/store.py +90 -0
  13. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/tui.py +37 -3
  14. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/tui_parts/commands.py +51 -1
  15. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/tui_parts/key_bindings.py +39 -3
  16. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/tui_parts/render_panels.py +7 -28
  17. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/tui_parts/ui_mode.py +1 -0
  18. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/pyproject.toml +1 -1
  19. comate_cli-0.7.1/tests/config/__init__.py +0 -0
  20. comate_cli-0.7.1/tests/statusline/__init__.py +0 -0
  21. comate_cli-0.7.1/tests/statusline/test_model.py +43 -0
  22. comate_cli-0.7.1/tests/statusline/test_picker_state.py +114 -0
  23. comate_cli-0.7.1/tests/statusline/test_store.py +72 -0
  24. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_completion_status_panel.py +3 -0
  25. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_event_renderer_streaming.py +2 -4
  26. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_interrupt_exit_semantics.py +52 -1
  27. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_logo.py +5 -0
  28. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_preflight.py +126 -1
  29. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_status_bar.py +60 -1
  30. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_task_panel_key_bindings.py +1 -1
  31. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/uv.lock +8 -8
  32. comate_cli-0.7.0a10/bash-exit-code-green-dot-bug.md +0 -140
  33. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/AGENTS.md +0 -0
  34. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/CHANGELOG.md +0 -0
  35. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/README.md +0 -0
  36. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/__init__.py +0 -0
  37. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/__main__.py +0 -0
  38. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/main.py +0 -0
  39. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/mcp_cli.py +0 -0
  40. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/__init__.py +0 -0
  41. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/assistant_render.py +0 -0
  42. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/codenames.py +0 -0
  43. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/config/__init__.py +0 -0
  44. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/config/model.py +0 -0
  45. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/config/picker.py +0 -0
  46. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/config/picker_state.py +0 -0
  47. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/config/store.py +0 -0
  48. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/custom_slash_commands.py +0 -0
  49. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/env_utils.py +0 -0
  50. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/error_display.py +0 -0
  51. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/event_renderer.py +0 -0
  52. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/figures.py +0 -0
  53. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/fragment_utils.py +0 -0
  54. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/history_printer.py +0 -0
  55. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/input_geometry.py +0 -0
  56. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/layout_coordinator.py +0 -0
  57. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/logging_adapter.py +0 -0
  58. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/markdown_render.py +0 -0
  59. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/mention_completer.py +0 -0
  60. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/message_style.py +0 -0
  61. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/models.py +0 -0
  62. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/path_context_hint.py +0 -0
  63. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/plugins/__init__.py +0 -0
  64. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/plugins/components/__init__.py +0 -0
  65. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/plugins/components/detail_view.py +0 -0
  66. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/plugins/components/plugin_list.py +0 -0
  67. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/plugins/components/search_box.py +0 -0
  68. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/plugins/components/tab_bar.py +0 -0
  69. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/plugins/marketplace_install_view.py +0 -0
  70. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/plugins/plugin_picker.py +0 -0
  71. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/plugins/tabs/__init__.py +0 -0
  72. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/plugins/tabs/discover_tab.py +0 -0
  73. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/plugins/tabs/errors_tab.py +0 -0
  74. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/plugins/tabs/installed_tab.py +0 -0
  75. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/plugins/tabs/marketplaces_tab.py +0 -0
  76. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/question_view.py +0 -0
  77. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/resume_picker.py +0 -0
  78. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/resume_preview.py +0 -0
  79. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/resume_selector.py +0 -0
  80. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/rpc_protocol.py +0 -0
  81. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/rpc_stdio.py +0 -0
  82. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/selection_menu.py +0 -0
  83. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/startup.py +0 -0
  84. {comate_cli-0.7.0a10/tests/config → comate_cli-0.7.1/comate_cli/terminal_agent/statusline}/__init__.py +0 -0
  85. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/text_effects.py +0 -0
  86. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/tips.py +0 -0
  87. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/tool_fold.py +0 -0
  88. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/tool_result_formatters.py +0 -0
  89. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/tool_result_store.py +0 -0
  90. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/tool_result_viewer.py +0 -0
  91. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/tool_view.py +0 -0
  92. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/transcript_viewer.py +0 -0
  93. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/tui_parts/__init__.py +0 -0
  94. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/tui_parts/btw_view.py +0 -0
  95. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/tui_parts/history_sync.py +0 -0
  96. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/tui_parts/input_behavior.py +0 -0
  97. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/tui_parts/mcp_connecting_view.py +0 -0
  98. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/comate_cli/terminal_agent/tui_parts/slash_command_registry.py +0 -0
  99. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/docs/hooks.md +0 -0
  100. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/docs/superpowers/plans/2026-04-03-phrase-shuffle.md +0 -0
  101. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/docs/superpowers/plans/2026-05-22-log-style-implementation-plan.md +0 -0
  102. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/docs/superpowers/specs/2026-04-01-conditional-diff-subtitle-design.md +0 -0
  103. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/docs/superpowers/specs/2026-04-03-phrase-shuffle-design.md +0 -0
  104. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/docs/superpowers/specs/2026-05-22-comate-cli-log-styling-design.md +0 -0
  105. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/docs/superpowers/specs/2026-05-22-log-style-optimization-design.md +0 -0
  106. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/report.md +0 -0
  107. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/config/test_model.py +0 -0
  108. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/config/test_picker_state.py +0 -0
  109. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/config/test_picker_ui.py +0 -0
  110. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/config/test_roundtrip.py +0 -0
  111. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/config/test_store_load.py +0 -0
  112. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/config/test_store_save.py +0 -0
  113. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/conftest.py +0 -0
  114. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/fixtures/fake_mcp_misbehaving_stdout.py +0 -0
  115. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_animator_shuffle.py +0 -0
  116. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_app_mcp_preload.py +0 -0
  117. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_app_preflight_gate.py +0 -0
  118. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_app_print_mode.py +0 -0
  119. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_app_shutdown.py +0 -0
  120. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_app_usage_line.py +0 -0
  121. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_btw_slash_command.py +0 -0
  122. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_cli_project_root.py +0 -0
  123. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_compact_command_semantics.py +0 -0
  124. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_completion_context_activation.py +0 -0
  125. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_context_command.py +0 -0
  126. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_custom_slash_commands.py +0 -0
  127. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_discover_tab.py +0 -0
  128. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_errors_tab.py +0 -0
  129. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_event_renderer.py +0 -0
  130. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_event_renderer_boundary.py +0 -0
  131. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_event_renderer_e2e.py +0 -0
  132. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_event_renderer_log_boundary.py +0 -0
  133. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_event_renderer_log_queue.py +0 -0
  134. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_event_renderer_tool_fold.py +0 -0
  135. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_format_error.py +0 -0
  136. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_handle_error.py +0 -0
  137. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_history_printer.py +0 -0
  138. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_history_printer_log.py +0 -0
  139. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_history_printer_subtitle_position.py +0 -0
  140. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_history_printer_tool_fold.py +0 -0
  141. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_history_sync.py +0 -0
  142. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_history_sync_tool_fold.py +0 -0
  143. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_input_behavior.py +0 -0
  144. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_input_history.py +0 -0
  145. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_installed_tab.py +0 -0
  146. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_layout_coordinator.py +0 -0
  147. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_logging_adapter.py +0 -0
  148. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_main_args.py +0 -0
  149. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_markdown_render.py +0 -0
  150. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_marketplaces_tab.py +0 -0
  151. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_mcp_cli.py +0 -0
  152. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_mcp_slash_command.py +0 -0
  153. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_mention_completer.py +0 -0
  154. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_path_context_hint.py +0 -0
  155. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_plugin_slash_commands.py +0 -0
  156. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_plugin_tui_components.py +0 -0
  157. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_preflight_copilot.py +0 -0
  158. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_question_key_bindings.py +0 -0
  159. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_question_view.py +0 -0
  160. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_resume_picker.py +0 -0
  161. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_resume_preview.py +0 -0
  162. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_resume_selector.py +0 -0
  163. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_rewind_command_semantics.py +0 -0
  164. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_rpc_protocol.py +0 -0
  165. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_rpc_stdio_bridge.py +0 -0
  166. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_selection_menu.py +0 -0
  167. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_session_query_token_summary.py +0 -0
  168. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_shutdown_noise_guard.py +0 -0
  169. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_shutdown_noise_integration.py +0 -0
  170. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_skills_slash_command.py +0 -0
  171. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_slash_argument_hint.py +0 -0
  172. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_slash_clear.py +0 -0
  173. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_slash_completer.py +0 -0
  174. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_slash_registry.py +0 -0
  175. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_status_bar_transient.py +0 -0
  176. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_task_panel_format.py +0 -0
  177. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_task_panel_rendering.py +0 -0
  178. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_task_poll.py +0 -0
  179. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_tool_fold.py +0 -0
  180. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_tool_fold_panel.py +0 -0
  181. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_tool_result_formatters.py +0 -0
  182. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_tool_result_store.py +0 -0
  183. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_tool_result_viewer.py +0 -0
  184. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_tool_result_viewer_key_bindings.py +0 -0
  185. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_tool_view.py +0 -0
  186. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_transcript_viewer.py +0 -0
  187. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_transcript_viewer_tool_fold.py +0 -0
  188. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_tui_elapsed_status.py +0 -0
  189. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_tui_esc_queue.py +0 -0
  190. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_tui_mcp_init_gate.py +0 -0
  191. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_tui_paste_newline_guard.py +0 -0
  192. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_tui_paste_placeholder.py +0 -0
  193. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_tui_queue_preview.py +0 -0
  194. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_tui_queue_sdk_source.py +0 -0
  195. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_tui_split_invariance.py +0 -0
  196. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_tui_team_messages.py +0 -0
  197. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_tui_thinking_display.py +0 -0
  198. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_tui_tool_result_registry_lifecycle.py +0 -0
  199. {comate_cli-0.7.0a10 → comate_cli-0.7.1}/tests/test_update_check.py +0 -0
@@ -230,3 +230,6 @@ __marimo__/
230
230
  .DS_Store.worktrees/
231
231
  .superpowers/
232
232
  .codex/
233
+
234
+ # pnpm
235
+ .pnpm-store/
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: comate-cli
3
- Version: 0.7.0a10
3
+ Version: 0.7.1
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
@@ -253,10 +253,8 @@ LOADING_SPINNER_FRAMES: tuple[str, ...] = (
253
253
 
254
254
  HIDDEN_THINKING_BADGES: tuple[str, ...] = (
255
255
  "ultra thinking",
256
- "deep reasoning",
257
- "thinking deeper",
258
- "extended thinking",
259
- "working through it",
256
+ "deep thinking",
257
+ "extended thinking"
260
258
  )
261
259
 
262
260
 
@@ -394,6 +394,11 @@ async def run(
394
394
 
395
395
  status_bar = StatusBar(session)
396
396
  status_bar.set_mode(session.get_mode())
397
+ try:
398
+ from comate_cli.terminal_agent.statusline import store as statusline_store
399
+ status_bar.apply_config(statusline_store.load())
400
+ except Exception:
401
+ pass
397
402
  if mode == "resume":
398
403
  await status_bar.refresh()
399
404
 
@@ -48,7 +48,10 @@ def _format_directory_for_display(project_root: Path) -> str:
48
48
  home = Path.home().expanduser().resolve()
49
49
  if resolved_root == home:
50
50
  return "~/"
51
- return str(resolved_root)
51
+ try:
52
+ return f"~/{resolved_root.relative_to(home)}"
53
+ except ValueError:
54
+ return str(resolved_root)
52
55
 
53
56
 
54
57
  def print_logo(console: Console, *, project_root: PathInput | None = None) -> None:
@@ -5,7 +5,7 @@ import logging
5
5
  import os
6
6
  from dataclasses import dataclass
7
7
  from pathlib import Path
8
- from typing import Any, Callable, Literal, Mapping
8
+ from typing import Any, Callable, Literal, Mapping, Sequence
9
9
 
10
10
  from prompt_toolkit.application import Application
11
11
  from prompt_toolkit.filters import Condition
@@ -33,6 +33,7 @@ from comate_agent_sdk.facade.config.providers import (
33
33
  build_preview_payload,
34
34
  evaluate_preflight_state,
35
35
  merge_user_settings,
36
+ resolve_provider_presets,
36
37
  )
37
38
 
38
39
  from comate_cli.terminal_agent.figures import BULLET_OPERATOR
@@ -107,6 +108,7 @@ async def run_preflight_if_needed(
107
108
  console: Console,
108
109
  project_root: Path,
109
110
  interactive: bool,
111
+ provider_presets: Sequence[ProviderPreset] | None = None,
110
112
  ) -> PreflightResult:
111
113
  check = evaluate_preflight_state(project_root=project_root)
112
114
  if not check.needs_preflight:
@@ -116,7 +118,11 @@ async def run_preflight_if_needed(
116
118
  _print_preflight_block_message(console=console, check=check)
117
119
  return PreflightResult(status="blocked_non_interactive", detail="missing_llm_config")
118
120
 
119
- flow = await _run_preflight_wizard(check=check, project_root=project_root)
121
+ flow = await _run_preflight_wizard(
122
+ check=check,
123
+ project_root=project_root,
124
+ provider_presets=provider_presets,
125
+ )
120
126
  if flow.cancel_detail is not None:
121
127
  console.print("[yellow]Setup cancelled. Session was not started.[/]")
122
128
  return PreflightResult(status="cancelled", detail=flow.cancel_detail)
@@ -216,9 +222,16 @@ class _PreflightWizardFlowResult:
216
222
 
217
223
 
218
224
  class _PreflightWizard:
219
- def __init__(self, *, check: PreflightCheckResult, project_root: Path) -> None:
225
+ def __init__(
226
+ self,
227
+ *,
228
+ check: PreflightCheckResult,
229
+ project_root: Path,
230
+ provider_presets: Sequence[ProviderPreset] | None = None,
231
+ ) -> None:
220
232
  self._check = check
221
233
  self._project_root = project_root
234
+ self._provider_presets = resolve_provider_presets(provider_presets)
222
235
  self._app: Application | None = None
223
236
 
224
237
  self._mode: Literal["selection", "input"] = "selection"
@@ -449,7 +462,7 @@ class _PreflightWizard:
449
462
  def _open_provider_menu(self) -> None:
450
463
  self._back_fn = self._open_entry_menu
451
464
  ranked_presets = sorted(
452
- enumerate(PROVIDER_PRESETS),
465
+ enumerate(self._provider_presets),
453
466
  key=lambda pair: (_PROVIDER_MENU_PRIORITY.get(pair[1].preset_id, 100), pair[0]),
454
467
  )
455
468
  options = [
@@ -472,7 +485,7 @@ class _PreflightWizard:
472
485
  )
473
486
 
474
487
  def _on_provider_selected(self, value: str) -> None:
475
- selected = next((preset for preset in PROVIDER_PRESETS if preset.preset_id == value), None)
488
+ selected = next((preset for preset in self._provider_presets if preset.preset_id == value), None)
476
489
  if selected is None:
477
490
  self._cancel_with_detail("provider_cancelled")
478
491
  return
@@ -748,6 +761,11 @@ async def _run_preflight_wizard(
748
761
  *,
749
762
  check: PreflightCheckResult,
750
763
  project_root: Path,
764
+ provider_presets: Sequence[ProviderPreset] | None = None,
751
765
  ) -> _PreflightWizardFlowResult:
752
- wizard = _PreflightWizard(check=check, project_root=project_root)
766
+ wizard = _PreflightWizard(
767
+ check=check,
768
+ project_root=project_root,
769
+ provider_presets=provider_presets,
770
+ )
753
771
  return await wizard.run()
@@ -137,6 +137,11 @@ SLASH_COMMAND_SPECS: tuple[SlashCommandSpec, ...] = (
137
137
  description="Configure CLI preferences (thinking, model, compaction, memory)",
138
138
  execution_kind="local",
139
139
  ),
140
+ SlashCommandSpec(
141
+ name="statusline",
142
+ description="Customize status bar display items",
143
+ execution_kind="local",
144
+ ),
140
145
  )
141
146
  SLASH_COMMANDS: tuple[str, ...] = tuple(f"/{cmd.name}" for cmd in SLASH_COMMAND_SPECS)
142
147
 
@@ -1,13 +1,19 @@
1
1
  from __future__ import annotations
2
2
 
3
+ import logging
3
4
  import subprocess
4
5
  import time
6
+ from pathlib import Path
5
7
  from typing import NamedTuple
6
8
 
7
9
  from prompt_toolkit.application.current import get_app_or_none
8
10
 
9
11
  from comate_agent_sdk.agent import ChatSession
10
12
 
13
+ from comate_cli.terminal_agent.statusline.model import StatuslineConfig
14
+
15
+ logger = logging.getLogger(__name__)
16
+
11
17
 
12
18
  class GitDiffStats(NamedTuple):
13
19
  added: int
@@ -19,6 +25,14 @@ class StatusBar:
19
25
  _MIN_TERMINAL_WIDTH: int = 40
20
26
  _GIT_DIFF_CACHE_SECONDS: float = 5.0
21
27
  _GIT_CMD_TIMEOUT_SECONDS: float = 0.2
28
+ _SEPARATOR: str = " \u00b7 " # " · "
29
+
30
+ # 分组颜色
31
+ _COLOR_MODEL: str = "#E17B7D"
32
+ _COLOR_CONTEXT: str = "#DF8E5F"
33
+ _COLOR_PROJECT: str = "#9BC69B"
34
+ _COLOR_GIT: str = "#6B97C1"
35
+ _COLOR_SEPARATOR: str = "#6B7280"
22
36
 
23
37
  def __init__(self, session: ChatSession):
24
38
  self._session = session
@@ -32,7 +46,57 @@ class StatusBar:
32
46
  self._transient_message: str | None = None
33
47
  self._transient_severity: str = "info"
34
48
  self._transient_until: float | None = None
49
+ self._config: StatuslineConfig = StatuslineConfig.default()
50
+
51
+ # Cached token data (updated during refresh)
52
+ self._cached_total_tokens: int | None = None
53
+ self._cached_prompt_tokens: int | None = None
54
+ self._cached_completion_tokens: int | None = None
55
+ self._cached_total_cost: float | None = None
56
+
57
+ # ---- config ---------------------------------------------------------
58
+ def apply_config(self, config: StatuslineConfig) -> None:
59
+ self._config = config
60
+
61
+ @property
62
+ def config(self) -> StatuslineConfig:
63
+ return self._config
64
+
65
+ def live_preview_data(self) -> list[tuple[str, str]]:
66
+ """为 /statusline UI 提供实时预览数据。"""
67
+ from comate_agent_sdk.agent import ChatSession as _CS
68
+
69
+ agent = getattr(self._session, "_agent", None)
70
+ parts: list[tuple[str, str]] = []
35
71
 
72
+ parts.append(("show_model_name", self._model_name))
73
+ parts.append(("show_git_branch", f"~{self._git_branch}"))
74
+ parts.append(("show_context_left", self.context_left_text()))
75
+ parts.append(("show_git_diff", self._git_diff_preview()))
76
+ parts.append(("show_llm_level", self._resolve_llm_level()))
77
+ parts.append(("show_turn_number", self._resolve_turn_number()))
78
+ parts.append(("show_project_cwd", self._resolve_project_cwd()))
79
+
80
+ if self._cached_total_tokens is not None:
81
+ parts.append(("show_token_usage", f"{self._format_token_count(self._cached_total_tokens)} tok"))
82
+ else:
83
+ parts.append(("show_token_usage", "-"))
84
+ if self._cached_prompt_tokens is not None:
85
+ parts.append(("show_token_input", f"{self._format_token_count(self._cached_prompt_tokens)} in"))
86
+ else:
87
+ parts.append(("show_token_input", "-"))
88
+ if self._cached_completion_tokens is not None:
89
+ parts.append(("show_token_output", f"{self._format_token_count(self._cached_completion_tokens)} out"))
90
+ else:
91
+ parts.append(("show_token_output", "-"))
92
+ if self._cached_total_cost is not None:
93
+ parts.append(("show_session_cost", f"${self._cached_total_cost:.4f}"))
94
+ else:
95
+ parts.append(("show_session_cost", "-"))
96
+
97
+ return parts
98
+
99
+ # ---- data resolvers -------------------------------------------------
36
100
  @staticmethod
37
101
  def _resolve_model_name(session: ChatSession) -> str:
38
102
  agent = getattr(session, "_agent", None)
@@ -101,17 +165,13 @@ class StatusBar:
101
165
  if not output:
102
166
  return None
103
167
 
104
- # Parse output like "3 files changed, 12 insertions(+), 5 deletions(-)"
105
- # or just "12 insertions(+), 5 deletions(-)"
106
168
  added, removed = 0, 0
107
169
  for part in output.split(","):
108
170
  part = part.strip()
109
171
  if "+" in part and "insertion" in part:
110
- # e.g., "12 insertions(+)"
111
172
  num_str = part.split()[0]
112
173
  added = int(num_str)
113
174
  elif "-" in part and "deletion" in part:
114
- # e.g., "5 deletions(-)"
115
175
  num_str = part.split()[0]
116
176
  removed = int(num_str)
117
177
 
@@ -127,6 +187,41 @@ class StatusBar:
127
187
  self._git_diff_stats = self._resolve_git_diff_stats()
128
188
  self._git_diff_cache_time = now
129
189
 
190
+ def _resolve_llm_level(self) -> str:
191
+ agent = getattr(self._session, "_agent", None)
192
+ level = getattr(agent, "level", None)
193
+ return str(level) if level else "-"
194
+
195
+ def _resolve_turn_number(self) -> str:
196
+ agent = getattr(self._session, "_agent", None)
197
+ turn = getattr(agent, "_turn_number", None)
198
+ return f"#{turn}" if turn is not None else "-"
199
+
200
+ def _resolve_project_cwd(self) -> str:
201
+ cwd = getattr(self._session, "_cwd", None)
202
+ if cwd is None:
203
+ return "-"
204
+ p = Path(cwd)
205
+ home = Path.home()
206
+ try:
207
+ rel = p.relative_to(home)
208
+ return "~/" if rel == Path(".") else f"~/{rel}"
209
+ except ValueError:
210
+ return str(p)
211
+
212
+ def _git_diff_preview(self) -> str:
213
+ if self._git_diff_stats is None:
214
+ return "-"
215
+ a, r = self._git_diff_stats
216
+ if a == 0 and r == 0:
217
+ return "-"
218
+ parts: list[str] = []
219
+ if a > 0:
220
+ parts.append(f"+{a}")
221
+ if r > 0:
222
+ parts.append(f"-{r}")
223
+ return " ".join(parts) if parts else "-"
224
+
130
225
  async def refresh(self) -> None:
131
226
  try:
132
227
  ctx_info = await self._session.get_context_info()
@@ -143,9 +238,21 @@ class StatusBar:
143
238
  self._context_used_pct = normalized
144
239
  self._context_left_pct = max(0.0, 100.0 - normalized)
145
240
 
146
- # Refresh git diff stats off the render path; UI reads only the cache.
147
241
  self._ensure_git_diff_stats()
148
242
 
243
+ # Refresh token usage cache if any token-related items are enabled
244
+ cfg = self._config
245
+ if cfg.show_token_usage or cfg.show_token_input or cfg.show_token_output or cfg.show_session_cost:
246
+ try:
247
+ usage = await self._session.get_usage()
248
+ self._cached_total_tokens = usage.total_tokens
249
+ self._cached_prompt_tokens = usage.total_prompt_tokens
250
+ self._cached_completion_tokens = usage.total_completion_tokens
251
+ self._cached_total_cost = usage.total_cost
252
+ except Exception:
253
+ pass
254
+
255
+ # ---- terminal width / truncation ------------------------------------
149
256
  @classmethod
150
257
  def _resolve_terminal_width(cls) -> int:
151
258
  app = get_app_or_none()
@@ -192,18 +299,102 @@ class StatusBar:
192
299
  def get_mode(self) -> str:
193
300
  return self._mode
194
301
 
302
+ # ---- dynamic info_status_text ---------------------------------------
303
+ @staticmethod
304
+ def _format_token_count(n: int) -> str:
305
+ if n >= 1_000_000:
306
+ return f"{n / 1_000_000:.1f}M"
307
+ if n >= 1_000:
308
+ return f"{n / 1_000:.1f}k"
309
+ return str(n)
310
+
311
+ def _build_info_items(self) -> list[tuple[str, str]]:
312
+ """按 config 开关和固定顺序构建带颜色的展示项列表。
313
+
314
+ 返回 (style, text) 列表,style 是 prompt_toolkit fragment style 字符串。
315
+ """
316
+ cfg = self._config
317
+ items: list[tuple[str, str]] = []
318
+
319
+ if cfg.show_model_name:
320
+ items.append((f"fg:{self._COLOR_MODEL}", self._model_name))
321
+ if cfg.show_llm_level:
322
+ items.append((f"fg:{self._COLOR_MODEL}", self._resolve_llm_level()))
323
+ if cfg.show_turn_number:
324
+ items.append((f"fg:{self._COLOR_CONTEXT}", self._resolve_turn_number()))
325
+ if cfg.show_project_cwd:
326
+ items.append((f"fg:{self._COLOR_PROJECT}", self._resolve_project_cwd()))
327
+ if cfg.show_git_branch:
328
+ items.append((f"fg:{self._COLOR_GIT}", f"~{self._git_branch}"))
329
+ if cfg.show_git_diff:
330
+ diff = self._git_diff_preview()
331
+ if diff != "-":
332
+ items.append((f"fg:{self._COLOR_GIT}", diff))
333
+ if cfg.show_context_left:
334
+ items.append((f"fg:{self._COLOR_CONTEXT}", self.context_left_text()))
335
+ if cfg.show_token_usage and self._cached_total_tokens is not None:
336
+ items.append((f"fg:{self._COLOR_CONTEXT}", f"{self._format_token_count(self._cached_total_tokens)} tok"))
337
+ if cfg.show_token_input and self._cached_prompt_tokens is not None:
338
+ items.append((f"fg:{self._COLOR_CONTEXT}", f"{self._format_token_count(self._cached_prompt_tokens)} in"))
339
+ if cfg.show_token_output and self._cached_completion_tokens is not None:
340
+ items.append((f"fg:{self._COLOR_CONTEXT}", f"{self._format_token_count(self._cached_completion_tokens)} out"))
341
+ if cfg.show_session_cost and self._cached_total_cost is not None:
342
+ items.append((f"fg:{self._COLOR_CONTEXT}", f"${self._cached_total_cost:.3f}"))
343
+
344
+ return items
345
+
346
+ def info_status_fragments(self) -> list[tuple[str, str]]:
347
+ """带分组颜色的 statusline fragments,超宽时从尾部整项移除。"""
348
+ items = self._build_info_items()
349
+ if not items:
350
+ return []
351
+
352
+ sep_text = self._SEPARATOR
353
+ sep_style = f"fg:{self._COLOR_SEPARATOR}"
354
+
355
+ # 交替插入分隔符:item0, sep, item1, sep, item2, ...
356
+ fragments: list[tuple[str, str]] = []
357
+ for i, (style, text) in enumerate(items):
358
+ if i > 0:
359
+ fragments.append((sep_style, sep_text))
360
+ fragments.append((style, text))
361
+
362
+ width = self._resolve_terminal_width()
363
+ budget = max(0, width - 2)
364
+ total_len = sum(len(text) for _, text in fragments)
365
+ if total_len <= budget:
366
+ return fragments
367
+
368
+ # 从尾部移除整项(含前缀分隔符)直到 fits
369
+ while items and total_len > budget:
370
+ removed_style, removed_text = items.pop()
371
+ total_len -= len(removed_text)
372
+ # 同时移除前一个分隔符
373
+ if items:
374
+ total_len -= len(sep_text)
375
+ if not items:
376
+ return []
377
+
378
+ # 重建 fragments
379
+ fragments = []
380
+ for i, (style, text) in enumerate(items):
381
+ if i > 0:
382
+ fragments.append((sep_style, sep_text))
383
+ fragments.append((style, text))
384
+ return fragments
385
+
195
386
  def info_status_text(self) -> str:
196
- """仅返回 model | ~branch / X% context left(不含 mode 前缀)."""
197
- branch_text = f"~{self._git_branch}"
198
- context_text = self.context_left_text()
199
- full_text = f"{self._model_name} | {branch_text} / {context_text}"
387
+ """ config 动态组装纯文本展示项(用于 picker 预览等无颜色场景),用 · 分隔。"""
388
+ items = self._build_info_items()
389
+ if not items:
390
+ return ""
391
+ parts = [text for _, text in items]
392
+ full_text = self._SEPARATOR.join(parts)
200
393
  width = self._resolve_terminal_width()
201
- budget = max(len(context_text), width - 2)
394
+ budget = max(0, width - 2)
202
395
  if len(full_text) <= budget:
203
396
  return full_text
204
- prefix = f"{self._model_name} | {branch_text} / "
205
- prefix_budget = max(0, budget - len(context_text))
206
- return f"{self._truncate_text(prefix, prefix_budget)}{context_text}"
397
+ return self._truncate_text(full_text, budget)
207
398
 
208
399
  def right_prompt_text(self) -> str:
209
400
  return self._status_text_for_width(self._right_prompt_budget())
@@ -217,6 +408,8 @@ class StatusBar:
217
408
  return self._status_text_for_width(content_budget)
218
409
 
219
410
  def _git_diff_fragments(self) -> list[tuple[str, str]]:
411
+ if not self._config.show_git_diff:
412
+ return []
220
413
  if self._git_diff_stats is None or (
221
414
  self._git_diff_stats.added == 0 and self._git_diff_stats.removed == 0
222
415
  ):
@@ -230,10 +423,7 @@ class StatusBar:
230
423
  return parts
231
424
 
232
425
  def git_diff_fragments(self) -> list[tuple[str, str]]:
233
- """Prompt-toolkit fragments for git diff stats.
234
-
235
- Working tree only (unstaged): `git diff --shortstat`.
236
- """
426
+ """Prompt-toolkit fragments for git diff stats."""
237
427
  return self._git_diff_fragments()
238
428
 
239
429
  def footer_toolbar(self) -> list[tuple[str, str]]:
@@ -241,8 +431,7 @@ class StatusBar:
241
431
  status_text = self.footer_status_text()
242
432
  git_fragments = self._git_diff_fragments()
243
433
 
244
- # Calculate total length: status_text + git diff parts
245
- git_len = sum(len(text) + 1 for _, text in git_fragments) # +1 for space
434
+ git_len = sum(len(text) + 1 for _, text in git_fragments)
246
435
  left_padding = max(0, width - len(status_text) - git_len - 1)
247
436
 
248
437
  fragments: list[tuple[str, str]] = [
@@ -250,9 +439,8 @@ class StatusBar:
250
439
  ("", status_text),
251
440
  ]
252
441
 
253
- # Add git diff stats with colors
254
442
  if git_fragments:
255
- fragments.append(("", " ")) # Separator
443
+ fragments.append(("", " "))
256
444
  for class_name, text in git_fragments:
257
445
  fragments.append((class_name, text))
258
446
 
@@ -267,11 +455,7 @@ class StatusBar:
267
455
  self._transient_until = time.monotonic() + duration_s
268
456
 
269
457
  def clear_transient_if_expired(self) -> bool:
270
- """Check and clear expired transient message.
271
-
272
- Returns True if the message was just cleared (state changed, needs repaint).
273
- Returns False otherwise (no message, or message still active).
274
- """
458
+ """Check and clear expired transient message."""
275
459
  if self._transient_until is not None and time.monotonic() >= self._transient_until:
276
460
  self._transient_message = None
277
461
  self._transient_severity = "info"
@@ -0,0 +1,60 @@
1
+ """StatuslineConfig:statusline 展示项开关的不可变快照。"""
2
+ from __future__ import annotations
3
+
4
+ from dataclasses import dataclass, replace
5
+
6
+
7
+ @dataclass(frozen=True, slots=True)
8
+ class StatuslineConfig:
9
+ """11 项 statusline 展示项开关。"""
10
+
11
+ show_model_name: bool = True
12
+ show_git_branch: bool = True
13
+ show_context_left: bool = True
14
+ show_token_usage: bool = False
15
+ show_token_input: bool = False
16
+ show_token_output: bool = False
17
+ show_project_cwd: bool = False
18
+ show_llm_level: bool = False
19
+ show_turn_number: bool = False
20
+ show_git_diff: bool = False
21
+ show_session_cost: bool = False
22
+
23
+ @classmethod
24
+ def default(cls) -> StatuslineConfig:
25
+ return cls()
26
+
27
+ # ---- with_* mutators (返回新实例) ----
28
+
29
+ def with_show_model_name(self, v: bool) -> StatuslineConfig:
30
+ return replace(self, show_model_name=v)
31
+
32
+ def with_show_git_branch(self, v: bool) -> StatuslineConfig:
33
+ return replace(self, show_git_branch=v)
34
+
35
+ def with_show_context_left(self, v: bool) -> StatuslineConfig:
36
+ return replace(self, show_context_left=v)
37
+
38
+ def with_show_token_usage(self, v: bool) -> StatuslineConfig:
39
+ return replace(self, show_token_usage=v)
40
+
41
+ def with_show_token_input(self, v: bool) -> StatuslineConfig:
42
+ return replace(self, show_token_input=v)
43
+
44
+ def with_show_token_output(self, v: bool) -> StatuslineConfig:
45
+ return replace(self, show_token_output=v)
46
+
47
+ def with_show_project_cwd(self, v: bool) -> StatuslineConfig:
48
+ return replace(self, show_project_cwd=v)
49
+
50
+ def with_show_llm_level(self, v: bool) -> StatuslineConfig:
51
+ return replace(self, show_llm_level=v)
52
+
53
+ def with_show_turn_number(self, v: bool) -> StatuslineConfig:
54
+ return replace(self, show_turn_number=v)
55
+
56
+ def with_show_git_diff(self, v: bool) -> StatuslineConfig:
57
+ return replace(self, show_git_diff=v)
58
+
59
+ def with_show_session_cost(self, v: bool) -> StatuslineConfig:
60
+ return replace(self, show_session_cost=v)