comate-cli 0.12.7b1__tar.gz → 0.12.8__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 (525) hide show
  1. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/CHANGELOG.md +2 -0
  2. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/CONTEXT.md +5 -1
  3. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/PKG-INFO +1 -1
  4. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/main.py +18 -13
  5. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/side_install.py +2 -0
  6. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/update_check.py +160 -9
  7. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/update_messages.py +11 -0
  8. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/update_cli.py +89 -3
  9. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/pyproject.toml +1 -1
  10. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_side_install.py +28 -7
  11. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_update_check.py +59 -39
  12. comate_cli-0.12.8/tests/test_update_mirror.py +338 -0
  13. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/uv.lock +1 -1
  14. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/.agent/scheduled_prompts.json +0 -0
  15. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/.gitignore +0 -0
  16. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/.python-version +0 -0
  17. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/README.md +0 -0
  18. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/bash_settle_diag.log +0 -0
  19. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/__init__.py +0 -0
  20. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/__main__.py +0 -0
  21. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/device_identity.py +0 -0
  22. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/distribution.py +0 -0
  23. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/mcp_cli.py +0 -0
  24. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/__init__.py +0 -0
  25. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/animations.py +0 -0
  26. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/app.py +0 -0
  27. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/approval_bridge.py +0 -0
  28. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/approval_content_preview.py +0 -0
  29. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/assistant_render.py +0 -0
  30. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/backend/__init__.py +0 -0
  31. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/backend/announcements.py +0 -0
  32. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/backend/client.py +0 -0
  33. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/backend/feedback.py +0 -0
  34. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/backend/provider_snapshot.py +0 -0
  35. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/backend/rating.py +0 -0
  36. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/backend/runtime.py +0 -0
  37. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/backend/session_report.py +0 -0
  38. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/backend/session_title.py +0 -0
  39. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/backend/tasks.py +0 -0
  40. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/bash_command_display.py +0 -0
  41. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/browser_open.py +0 -0
  42. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/builtin_commands/.keep +0 -0
  43. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/builtin_commands/commit.md +0 -0
  44. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/builtin_commands/implement-plan.md +0 -0
  45. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/builtin_commands/learn.md +0 -0
  46. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/builtin_commands/open-pr.md +0 -0
  47. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/clipboard_image.py +0 -0
  48. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/clipboard_text.py +0 -0
  49. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/codenames.py +0 -0
  50. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/config/__init__.py +0 -0
  51. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/config/edit_session.py +0 -0
  52. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/config/model.py +0 -0
  53. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/config/picker.py +0 -0
  54. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/config/picker_state.py +0 -0
  55. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/config/store.py +0 -0
  56. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/config_check.py +0 -0
  57. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/console_profile.py +0 -0
  58. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/context_view.py +0 -0
  59. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/custom_slash_commands.py +0 -0
  60. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/effort_menu.py +0 -0
  61. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/effort_ruler.py +0 -0
  62. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/effort_style.py +0 -0
  63. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/env_utils.py +0 -0
  64. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/error_display.py +0 -0
  65. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/event_renderer.py +0 -0
  66. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/exit_confirm_view.py +0 -0
  67. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/exit_watchdog.py +0 -0
  68. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/figures.py +0 -0
  69. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/file_ref_hint.py +0 -0
  70. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/focus_events.py +0 -0
  71. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/fragment_utils.py +0 -0
  72. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/goal_edit_view.py +0 -0
  73. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/goal_resume_view.py +0 -0
  74. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/history_printer.py +0 -0
  75. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/i18n/__init__.py +0 -0
  76. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/i18n/_en.py +0 -0
  77. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/i18n/_ja.py +0 -0
  78. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/i18n/_zh.py +0 -0
  79. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/i18n/message.py +0 -0
  80. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/image_chips.py +0 -0
  81. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/input_geometry.py +0 -0
  82. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/job_activity.py +0 -0
  83. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/job_indicator.py +0 -0
  84. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/jobs_menu.py +0 -0
  85. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/jobs_state.py +0 -0
  86. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/layout_coordinator.py +0 -0
  87. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/locale.py +0 -0
  88. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/logging_adapter.py +0 -0
  89. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/logging_file_handler.py +0 -0
  90. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/logo.py +0 -0
  91. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/loop_freeze_watchdog.py +0 -0
  92. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/markdown_render.py +0 -0
  93. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/mcp_serve.py +0 -0
  94. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/mention_completer.py +0 -0
  95. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/menu_panel.py +0 -0
  96. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/message_style.py +0 -0
  97. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/model_tier_style.py +0 -0
  98. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/models.py +0 -0
  99. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/output_style_menu.py +0 -0
  100. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/plugins/__init__.py +0 -0
  101. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/plugins/auto_update_runner.py +0 -0
  102. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/plugins/auto_update_store.py +0 -0
  103. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/plugins/components/__init__.py +0 -0
  104. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/plugins/components/detail_view.py +0 -0
  105. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/plugins/components/plugin_list.py +0 -0
  106. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/plugins/components/search_box.py +0 -0
  107. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/plugins/components/tab_bar.py +0 -0
  108. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/plugins/marketplace_install_view.py +0 -0
  109. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/plugins/operation_state.py +0 -0
  110. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/plugins/plugin_picker.py +0 -0
  111. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/plugins/tabs/__init__.py +0 -0
  112. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/plugins/tabs/discover_tab.py +0 -0
  113. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/plugins/tabs/errors_tab.py +0 -0
  114. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/plugins/tabs/installed_tab.py +0 -0
  115. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/plugins/tabs/marketplaces_tab.py +0 -0
  116. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/preflight.py +0 -0
  117. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/preflight_wizard.py +0 -0
  118. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/preflight_wizard_ui.py +0 -0
  119. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/print_mode.py +0 -0
  120. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/question_broker.py +0 -0
  121. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/question_view.py +0 -0
  122. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/recap/__init__.py +0 -0
  123. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/recap/controller.py +0 -0
  124. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/resume_picker.py +0 -0
  125. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/resume_preview.py +0 -0
  126. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/resume_selector.py +0 -0
  127. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/rpc_commands.py +0 -0
  128. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/rpc_relay.py +0 -0
  129. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/rpc_stdio.py +0 -0
  130. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/rpc_ws.py +0 -0
  131. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/scm_request_status.py +0 -0
  132. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/selection_menu.py +0 -0
  133. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/sigint_guard.py +0 -0
  134. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/skill_slash_input.py +0 -0
  135. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/skills_menu.py +0 -0
  136. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/slash_commands.py +0 -0
  137. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/startup.py +0 -0
  138. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/startup_profile.py +0 -0
  139. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/status_bar.py +0 -0
  140. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/statusline/__init__.py +0 -0
  141. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/statusline/model.py +0 -0
  142. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/statusline/picker.py +0 -0
  143. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/statusline/picker_state.py +0 -0
  144. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/statusline/store.py +0 -0
  145. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/stream_pacer.py +0 -0
  146. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/suggestion/__init__.py +0 -0
  147. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/suggestion/controller.py +0 -0
  148. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/synchronized_output.py +0 -0
  149. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/text_effects.py +0 -0
  150. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/theme.py +0 -0
  151. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/tip_highlight.py +0 -0
  152. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/tips.py +0 -0
  153. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/tool_approval_view.py +0 -0
  154. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/tool_fold.py +0 -0
  155. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/tool_fold_view.py +0 -0
  156. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/tool_result_formatters.py +0 -0
  157. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/tool_result_state.py +0 -0
  158. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/tool_result_store.py +0 -0
  159. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/tool_result_viewer.py +0 -0
  160. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/tool_view.py +0 -0
  161. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/transcript_viewer.py +0 -0
  162. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/tui.py +0 -0
  163. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/tui_parts/__init__.py +0 -0
  164. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/tui_parts/approval_queue.py +0 -0
  165. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/tui_parts/btw_view.py +0 -0
  166. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/tui_parts/commands.py +0 -0
  167. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/tui_parts/history_sync.py +0 -0
  168. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/tui_parts/input_behavior.py +0 -0
  169. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/tui_parts/key_bindings.py +0 -0
  170. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/tui_parts/mcp_auth_view.py +0 -0
  171. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/tui_parts/mcp_connecting_view.py +0 -0
  172. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/tui_parts/render_panels.py +0 -0
  173. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/tui_parts/resize_guard.py +0 -0
  174. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/tui_parts/run_clock.py +0 -0
  175. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/tui_parts/shell_mode.py +0 -0
  176. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/tui_parts/slash_command_registry.py +0 -0
  177. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/tui_parts/ui_mode.py +0 -0
  178. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/ultracode_keyword.py +0 -0
  179. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/workflows_menu.py +0 -0
  180. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_agent/workflows_panel_model.py +0 -0
  181. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/comate_cli/terminal_title.py +0 -0
  182. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/docs/cli-rpc-stdio-guide.md +0 -0
  183. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/docs/release-notes/0.12.3.md +0 -0
  184. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/docs/startup-performance.md +0 -0
  185. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/docs/superpowers/plans/2026-07-07-tui-first-repaint-before-sdk-submit.md +0 -0
  186. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/docs/superpowers/plans/2026-07-07-windows-update-manual-rollback.md +0 -0
  187. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/_fake_anthropic_server.py +0 -0
  188. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/_rpc_ws_client.py +0 -0
  189. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/config/__init__.py +0 -0
  190. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/config/test_config_exit.py +0 -0
  191. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/config/test_edit_session.py +0 -0
  192. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/config/test_model.py +0 -0
  193. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/config/test_picker_state.py +0 -0
  194. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/config/test_picker_ui.py +0 -0
  195. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/config/test_roundtrip.py +0 -0
  196. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/config/test_runtime_settings.py +0 -0
  197. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/config/test_skills_denylist_migration.py +0 -0
  198. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/config/test_store_load.py +0 -0
  199. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/config/test_store_save.py +0 -0
  200. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/conftest.py +0 -0
  201. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/fixtures/exit_watchdog_child.py +0 -0
  202. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/fixtures/fake_mcp_misbehaving_stdout.py +0 -0
  203. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/fixtures/mcp_stub_stdio_server.py +0 -0
  204. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/recap/test_idle_recap_controller.py +0 -0
  205. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/recap/test_recap_history_rendering.py +0 -0
  206. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/recap/test_tui_idle_recap_integration.py +0 -0
  207. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/statusline/__init__.py +0 -0
  208. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/statusline/test_model.py +0 -0
  209. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/statusline/test_picker_state.py +0 -0
  210. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/statusline/test_store.py +0 -0
  211. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/suggestion/test_next_step_suggestion_controller.py +0 -0
  212. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/suggestion/test_next_step_suggestion_render.py +0 -0
  213. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/suggestion/test_tab_accepts_next_step_suggestion.py +0 -0
  214. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/suggestion/test_tui_next_step_suggestion_integration.py +0 -0
  215. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_animations_styles.py +0 -0
  216. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_animator_shuffle.py +0 -0
  217. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_app_config_check_gate.py +0 -0
  218. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_app_disallowed_tools.py +0 -0
  219. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_app_exit_lifecycle.py +0 -0
  220. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_app_mcp_needs_auth_hint.py +0 -0
  221. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_app_mcp_preload.py +0 -0
  222. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_app_mcp_preload_kick.py +0 -0
  223. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_app_preflight_gate.py +0 -0
  224. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_app_print_mode.py +0 -0
  225. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_app_profile_threading.py +0 -0
  226. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_app_pty_ctrl_b.py +0 -0
  227. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_app_pty_ctrl_c_exit.py +0 -0
  228. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_app_pty_live_tail.py +0 -0
  229. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_app_pty_shell_mode.py +0 -0
  230. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_app_pty_smoke.py +0 -0
  231. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_app_shutdown.py +0 -0
  232. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_app_startup_latency.py +0 -0
  233. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_app_startup_order.py +0 -0
  234. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_app_token_cost_config.py +0 -0
  235. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_app_usage_line.py +0 -0
  236. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_approval_bridge.py +0 -0
  237. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_approval_content_preview.py +0 -0
  238. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_backend_announcements.py +0 -0
  239. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_backend_client.py +0 -0
  240. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_backend_feedback.py +0 -0
  241. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_backend_provider_snapshot.py +0 -0
  242. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_backend_rating.py +0 -0
  243. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_backend_session_report.py +0 -0
  244. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_backend_tasks.py +0 -0
  245. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_btw_slash_command.py +0 -0
  246. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_builtin_marketplaces.py +0 -0
  247. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_busy_slash_gating.py +0 -0
  248. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_cli_project_root.py +0 -0
  249. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_clipboard_chip_restore.py +0 -0
  250. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_clipboard_image_reader.py +0 -0
  251. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_clipboard_text.py +0 -0
  252. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_commands_system_messages.py +0 -0
  253. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_compact_command_semantics.py +0 -0
  254. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_completion_context_activation.py +0 -0
  255. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_completion_status_panel.py +0 -0
  256. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_config_check.py +0 -0
  257. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_console_profile.py +0 -0
  258. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_context_command.py +0 -0
  259. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_context_view.py +0 -0
  260. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_context_view_tool_search.py +0 -0
  261. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_ctrl_b_background.py +0 -0
  262. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_ctrl_c_clear_input.py +0 -0
  263. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_custom_slash_commands.py +0 -0
  264. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_device_identity.py +0 -0
  265. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_discover_tab.py +0 -0
  266. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_distribution_contract.py +0 -0
  267. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_drain_frame_atomicity.py +0 -0
  268. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_effort_menu.py +0 -0
  269. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_effort_menu_frame_rate.py +0 -0
  270. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_effort_ruler.py +0 -0
  271. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_effort_slash_command.py +0 -0
  272. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_effort_style.py +0 -0
  273. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_errors_tab.py +0 -0
  274. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_event_renderer.py +0 -0
  275. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_event_renderer_approval_wait.py +0 -0
  276. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_event_renderer_bash_background.py +0 -0
  277. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_event_renderer_boundary.py +0 -0
  278. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_event_renderer_budget_floor.py +0 -0
  279. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_event_renderer_e2e.py +0 -0
  280. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_event_renderer_fixed_overhead.py +0 -0
  281. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_event_renderer_idle_prune.py +0 -0
  282. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_event_renderer_jobs.py +0 -0
  283. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_event_renderer_log_boundary.py +0 -0
  284. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_event_renderer_log_queue.py +0 -0
  285. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_event_renderer_mcp_background.py +0 -0
  286. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_event_renderer_oversized_tools.py +0 -0
  287. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_event_renderer_provider_overflow.py +0 -0
  288. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_event_renderer_shell.py +0 -0
  289. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_event_renderer_stream_pacing.py +0 -0
  290. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_event_renderer_stream_staging.py +0 -0
  291. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_event_renderer_streaming.py +0 -0
  292. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_event_renderer_tool_args_progress.py +0 -0
  293. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_event_renderer_tool_fold.py +0 -0
  294. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_event_renderer_tool_search_notice.py +0 -0
  295. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_exit_confirm_view.py +0 -0
  296. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_exit_guard.py +0 -0
  297. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_exit_watchdog.py +0 -0
  298. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_exit_watchdog_subprocess.py +0 -0
  299. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_file_ref_hint.py +0 -0
  300. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_focus_events.py +0 -0
  301. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_format_error.py +0 -0
  302. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_goal_edit_handlers.py +0 -0
  303. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_goal_edit_view.py +0 -0
  304. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_goal_paused_hint.py +0 -0
  305. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_goal_resume_tui.py +0 -0
  306. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_goal_resume_view.py +0 -0
  307. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_goal_slash_command.py +0 -0
  308. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_handle_error.py +0 -0
  309. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_history_drain_throttle.py +0 -0
  310. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_history_printer.py +0 -0
  311. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_history_printer_log.py +0 -0
  312. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_history_printer_styles.py +0 -0
  313. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_history_printer_subtitle_position.py +0 -0
  314. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_history_printer_tool_fold.py +0 -0
  315. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_history_sync.py +0 -0
  316. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_history_sync_tool_fold.py +0 -0
  317. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_i18n.py +0 -0
  318. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_image_chip_deletion.py +0 -0
  319. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_image_chips.py +0 -0
  320. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_image_preprocess_offload_lag.py +0 -0
  321. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_import_weight.py +0 -0
  322. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_input_behavior.py +0 -0
  323. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_input_history.py +0 -0
  324. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_input_separator_counter.py +0 -0
  325. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_installed_tab.py +0 -0
  326. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_interrupt_exit_semantics.py +0 -0
  327. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_job_activity.py +0 -0
  328. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_job_indicator.py +0 -0
  329. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_job_indicator_host.py +0 -0
  330. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_job_indicator_pty.py +0 -0
  331. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_jobs_menu.py +0 -0
  332. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_jobs_menu_host.py +0 -0
  333. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_jobs_menu_pty.py +0 -0
  334. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_jobs_state.py +0 -0
  335. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_key_bindings_system_messages.py +0 -0
  336. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_layout_coordinator.py +0 -0
  337. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_live_output_tail.py +0 -0
  338. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_loading_line_fragments.py +0 -0
  339. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_loading_modal_suppression.py +0 -0
  340. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_loading_tip_picker.py +0 -0
  341. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_logging_adapter.py +0 -0
  342. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_logging_file_handler.py +0 -0
  343. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_logo.py +0 -0
  344. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_loop_freeze_watchdog.py +0 -0
  345. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_main_args.py +0 -0
  346. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_main_args_yolo.py +0 -0
  347. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_main_profile_entry.py +0 -0
  348. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_markdown_render.py +0 -0
  349. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_marketplace_add_commands.py +0 -0
  350. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_marketplace_install_view.py +0 -0
  351. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_marketplaces_tab.py +0 -0
  352. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_mcp_auth_panel_pty.py +0 -0
  353. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_mcp_cli.py +0 -0
  354. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_mcp_cli_auth.py +0 -0
  355. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_mcp_cli_scope_defaults.py +0 -0
  356. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_mcp_cli_stdout_encoding.py +0 -0
  357. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_mcp_jobs_pty.py +0 -0
  358. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_mcp_panel_auth.py +0 -0
  359. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_mcp_serve.py +0 -0
  360. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_mcp_slash_command.py +0 -0
  361. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_mention_completer.py +0 -0
  362. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_menu_cursor_unification.py +0 -0
  363. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_menu_panel.py +0 -0
  364. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_menu_panel_pty.py +0 -0
  365. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_message_style.py +0 -0
  366. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_modal_freeze_timing.py +0 -0
  367. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_modal_panel_visibility.py +0 -0
  368. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_model_switch_command.py +0 -0
  369. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_model_tier_style.py +0 -0
  370. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_no_raw_colors.py +0 -0
  371. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_output_style_slash_command.py +0 -0
  372. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_permission_mode_cycle.py +0 -0
  373. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_plugin_auto_update_runner.py +0 -0
  374. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_plugin_auto_update_store.py +0 -0
  375. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_plugin_auto_update_tui.py +0 -0
  376. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_plugin_mcp_keeps_disk_servers.py +0 -0
  377. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_plugin_operation_state.py +0 -0
  378. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_plugin_slash_commands.py +0 -0
  379. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_plugin_tui_components.py +0 -0
  380. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_preflight.py +0 -0
  381. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_preflight_copilot.py +0 -0
  382. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_preflight_wizard_ui.py +0 -0
  383. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_print_mode_monitor_cap.py +0 -0
  384. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_print_mode_stdout_encoding.py +0 -0
  385. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_pty_output_integrity.py +0 -0
  386. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_question_broker.py +0 -0
  387. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_question_key_bindings.py +0 -0
  388. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_question_view.py +0 -0
  389. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_resize_guard.py +0 -0
  390. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_resume_picker.py +0 -0
  391. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_resume_preview.py +0 -0
  392. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_resume_selector.py +0 -0
  393. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_rewind_command_semantics.py +0 -0
  394. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_rpc_mode_logging.py +0 -0
  395. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_rpc_relay_dial_out.py +0 -0
  396. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_rpc_relay_e2e_smoke.py +0 -0
  397. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_rpc_relay_process_smoke.py +0 -0
  398. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_rpc_v4_stdio_smoke.py +0 -0
  399. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_rpc_v4_ws_smoke.py +0 -0
  400. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_rpc_ws_bind_failure.py +0 -0
  401. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_run_clock.py +0 -0
  402. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_running_tool_live_tail.py +0 -0
  403. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_running_tool_status_line.py +0 -0
  404. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_scm_request_status.py +0 -0
  405. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_scrollback_write_encoding.py +0 -0
  406. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_selection_menu.py +0 -0
  407. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_session_auto_title.py +0 -0
  408. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_session_query_token_summary.py +0 -0
  409. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_settings_write_guard.py +0 -0
  410. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_shell_mode.py +0 -0
  411. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_shutdown_noise_guard.py +0 -0
  412. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_shutdown_noise_integration.py +0 -0
  413. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_sigint_guard.py +0 -0
  414. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_sigint_key_binding.py +0 -0
  415. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_skill_slash_input.py +0 -0
  416. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_skills_slash_command.py +0 -0
  417. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_slash_add_dir.py +0 -0
  418. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_slash_argument_hint.py +0 -0
  419. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_slash_clear.py +0 -0
  420. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_slash_completer.py +0 -0
  421. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_slash_registry.py +0 -0
  422. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_startup_import_budget.py +0 -0
  423. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_startup_profile.py +0 -0
  424. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_status_bar.py +0 -0
  425. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_status_bar_mid_turn_refresh.py +0 -0
  426. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_status_bar_request_status.py +0 -0
  427. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_status_bar_transient.py +0 -0
  428. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_stream_pacer.py +0 -0
  429. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_stream_pacing_tick.py +0 -0
  430. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_stream_staging_panel.py +0 -0
  431. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_style_class_coverage.py +0 -0
  432. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_synchronized_output.py +0 -0
  433. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_tab_title.py +0 -0
  434. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_task_panel_format.py +0 -0
  435. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_task_panel_key_bindings.py +0 -0
  436. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_task_panel_rendering.py +0 -0
  437. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_task_poll.py +0 -0
  438. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_terminal_title.py +0 -0
  439. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_theme.py +0 -0
  440. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_tip_highlight.py +0 -0
  441. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_tips.py +0 -0
  442. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_todo_panel_busy_gating.py +0 -0
  443. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_tool_approval_key_bindings.py +0 -0
  444. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_tool_approval_tui.py +0 -0
  445. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_tool_approval_view.py +0 -0
  446. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_tool_approval_view_workflow.py +0 -0
  447. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_tool_call_protection.py +0 -0
  448. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_tool_fold.py +0 -0
  449. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_tool_fold_panel.py +0 -0
  450. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_tool_fold_view.py +0 -0
  451. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_tool_result_formatters.py +0 -0
  452. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_tool_result_state.py +0 -0
  453. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_tool_result_store.py +0 -0
  454. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_tool_result_viewer.py +0 -0
  455. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_tool_result_viewer_key_bindings.py +0 -0
  456. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_tool_view.py +0 -0
  457. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_tool_view_styles.py +0 -0
  458. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_transcript_viewer.py +0 -0
  459. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_transcript_viewer_record_matching.py +0 -0
  460. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_transcript_viewer_tool_fold.py +0 -0
  461. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_tui_builtin_slash_chain.py +0 -0
  462. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_tui_deferred_prewarm.py +0 -0
  463. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_tui_elapsed_status.py +0 -0
  464. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_tui_esc_queue.py +0 -0
  465. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_tui_exit_idempotence.py +0 -0
  466. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_tui_exit_paced_tail.py +0 -0
  467. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_tui_exit_pending_logs.py +0 -0
  468. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_tui_hot_reload.py +0 -0
  469. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_tui_image_chip_retention.py +0 -0
  470. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_tui_image_chip_seed.py +0 -0
  471. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_tui_image_paste.py +0 -0
  472. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_tui_image_path_upgrade.py +0 -0
  473. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_tui_image_restore.py +0 -0
  474. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_tui_image_submit.py +0 -0
  475. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_tui_interrupt_queue_recall.py +0 -0
  476. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_tui_llm_retry_panel.py +0 -0
  477. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_tui_loading_tip_rotation.py +0 -0
  478. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_tui_local_interactive_barrier.py +0 -0
  479. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_tui_mcp_init_gate.py +0 -0
  480. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_tui_paste_history_persistence.py +0 -0
  481. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_tui_paste_newline_guard.py +0 -0
  482. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_tui_paste_placeholder.py +0 -0
  483. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_tui_plugin_load.py +0 -0
  484. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_tui_provider_error_shield.py +0 -0
  485. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_tui_queue_pop_images.py +0 -0
  486. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_tui_queue_preview.py +0 -0
  487. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_tui_queue_sdk_source.py +0 -0
  488. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_tui_replace_session_resume_hint.py +0 -0
  489. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_tui_scheduled_fire_log.py +0 -0
  490. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_tui_scratchpad_fold_wiring.py +0 -0
  491. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_tui_send_undo_window.py +0 -0
  492. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_tui_session_observers.py +0 -0
  493. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_tui_shutdown_cancel_propagation.py +0 -0
  494. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_tui_split_invariance.py +0 -0
  495. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_tui_startup_latency.py +0 -0
  496. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_tui_surrogate_repair.py +0 -0
  497. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_tui_thinking_display.py +0 -0
  498. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_tui_tool_result_registry_lifecycle.py +0 -0
  499. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_tui_window_too_small_fallback.py +0 -0
  500. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_ui_mode_derivation.py +0 -0
  501. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_ui_tick_exception_isolation.py +0 -0
  502. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_ultracode_keyword.py +0 -0
  503. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_ultracode_keyword_frame_rate.py +0 -0
  504. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_ultracode_keyword_submit.py +0 -0
  505. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_ultracode_shimmer_render.py +0 -0
  506. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_update_cli.py +0 -0
  507. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_upstream_surrogate_merge_characterization.py +0 -0
  508. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_usage_command.py +0 -0
  509. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_wellformed_terminal_input.py +0 -0
  510. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_whitelabel_clear_logo.py +0 -0
  511. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_windows_sigint_console.py +0 -0
  512. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_workflows_menu.py +0 -0
  513. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_workflows_menu_host.py +0 -0
  514. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_workflows_menu_pty.py +0 -0
  515. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_workflows_panel_model.py +0 -0
  516. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_wrap_user_text.py +0 -0
  517. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tests/test_zipapp_launcher_path.py +0 -0
  518. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tools/diagnose_windows_shim_rename.py +0 -0
  519. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tools/logo_lab.py +0 -0
  520. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tools/nico_preview.py +0 -0
  521. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tools/probe_conhost_char_width.py +0 -0
  522. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tools/probe_conhost_render_replay.py +0 -0
  523. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tools/startup_bench.py +0 -0
  524. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tools/transcript_viewer_bench.py +0 -0
  525. {comate_cli-0.12.7b1 → comate_cli-0.12.8}/tools/verify_windows_self_update_semantics.py +0 -0
@@ -4,6 +4,7 @@
4
4
 
5
5
  ### Added
6
6
 
7
+ - `update --mirror <tag|url>`:这一次更新改用指定的 PyPI 包索引,查版本和装包都用它,不写入设置。tag 不分大小写:`pypi`、`tuna`、`aliyun`、`tencent`、`huawei`、`ustc`;也可以直接写 `http://` 或 `https://` 开头的 simple 地址(例 `--mirror=https://pypi.corp.example/simple`)。查版本读该索引的 simple 页(PEP 691 JSON 或 PEP 503 HTML),不用 `/pypi/<包名>/json`——阿里云、腾讯云、华为云没有这个接口;yanked 版本和预发布规则与原来一致。装包时 macOS/Linux 重装、Windows 旁装、Windows 手动修复命令都带 `--default-index <地址>`,简中用户的手动命令不再追加清华。输出多一行「使用包索引:<地址>」,四种语言齐全。值缺失、tag 不认识(会列出全部 tag)、`--mirror` 重复时退出码 2,不开始更新。白牌发行版自己管理更新源(如 hico),带 `--mirror` 时退出码 2 并说明原因。不带 `--mirror` 时行为不变:简中 locale 用清华,其他用 pypi.org。只改包索引,Python 下载镜像仍用 `UV_PYTHON_INSTALL_MIRROR` 环境变量。
7
8
  - `--disallowed-tools <names>` 启动参数:本次会话不把这些 tool 发给模型,子 agent 也拿不到(进入 SDK 的 `AgentConfig.disallowed_tools`)。名字逗号分隔,参数可重复,结果按出现顺序合并去重;只认精确名字,MCP tool 写 `mcp__<server>__<tool>`。TUI、`resume`、`--rpc-stdio`、`--rpc-ws`、`--rpc-relay` 都生效(RPC 下对整个进程生效);`-p` 下与它自带的 `SendMessage` 取并集。以下情况都在启动前报错退出:值为空、含 `*`、写了 `Agent` 或 `Skill`(这两个去掉后会话无法创建)、内置名拼错或大小写不对(`mcp__` 开头的名字不检查,MCP 在启动后才连接)。`comate mcp serve` 不支持。
8
9
  - 运行中的 Bash 显示 Live Output Tail:模型调用的 Bash 运行时,底部 running-tool 面板每秒读取一次最近输出,在签名行与 Running 状态行之间显示最多 3 个非空行(第一行带 `⎿`),`\r` 覆写的进度条只显示最后一段;`!` 命令活动区从 5 行改为 3 行。两处共用同一套行处理:丢空行、长行按显示宽度截断加 `…` 不折行(中文 / emoji 占 2 列)。命令结束、ctrl+b 转后台或中断后尾部立即消失,不进滚动区;折叠的 Bash 与子 agent 的 Bash 不受影响。
9
10
  - Interpreter Migration(macOS/Linux):CLI 不在 Python 3.12 上、并且没有待更新的新版本时,第一次启动在界面之前显示一行提示,之后的启动显示全屏提示,只有「立即迁移」和「跳过」。「立即迁移」把**当前版本**(`<包名>==<当前版本>`,带发行版的安装参数)用 `--python 3.12` 重装,成功后提示重启,本次启动停止;失败只显示一行原因(uv 输出的最后一行),继续在当前 Python 上进入界面。「跳过」不记住,下次启动再问。已经在 3.12、editable 安装、PATH 里没有 uv、Windows 都不提示;有待更新的新版本时只显示更新提示(接受更新会顺带迁移到 3.12)。文案四种语言齐全。
@@ -75,6 +76,7 @@
75
76
 
76
77
  ### Changed
77
78
 
79
+ - Self-Update 不再把用户换到 Python 3.12:`comate update`、启动时的「立即更新」、Windows 旁装,以及 Windows 手动修复命令,uv 命令里的 `--python` 改为当前解释器的 `主版本.次版本`(例如在 3.13 上运行就带 `--python 3.13`),更新后留在原来的 Python 上。命令仍然带 `--python`,否则 `--force` 重装会漂到 uv 默认找到的解释器上。不在 `requires-python` 范围内的解释器(例如 3.14)也照样保持。白牌发行版在 `install_args` 里自己指定了 `--python` 时仍以白牌为准,可以用它固定版本(例如 `"--python", "3.13.12"`)。决策见 ADR 0064。
78
80
  - 状态栏的 Job Indicator 只统计正在运行的后台 job:后台 subagent 跑完一轮进入待命(idle)后,不再显示 `x agent`;1 个运行中、2 个待命时显示 `1 agent`。待命的 agent 仍可在 `/ps` 里查看和停止,退出确认仍会提示它们(ADR 0050 补充)。
79
81
  - Self-Update 固定到 Python 3.12:`comate update`、启动时的「立即更新」、Windows 旁装,以及 Windows 自动路径不可用时显示的手动修复命令,都让新版本装在 Python 3.12 上(uv 命令带 `--python 3.12`;机器上没有 3.12 时 uv 会自动下载)。原因:uv 在读包之前就选好解释器,并且忽略 `requires-python` 的上限,所以以前用户会跑在 3.11 / 3.13 / 3.14 等不同版本上,而且不带 `--python` 的重装会把已经在 3.12 上的环境换成别的版本。白牌发行版在 `install_args` 里自己指定了 `--python` 时,以白牌的为准。`requires-python` 不变,3.11–3.13 继续支持。决策见 ADR 0055。
80
82
  - 简中用户更新时,uv 需要下载的 Python 改走国内镜像(npmmirror 的 python-build-standalone),不再依赖 GitHub;进程内重装和 Windows 旁装都生效。你自己设置了 `UV_PYTHON_INSTALL_MIRROR` 时以你的为准;其他语言环境不变。
@@ -212,6 +212,10 @@ _Avoid_: update check, update detection (plugin term), has-update probe
212
212
  Where a Version Check reads the newest version from: the public package index for the default distribution, or the whitelabel distribution's own index. It is derived from the distribution profile, never hard-coded.
213
213
  _Avoid_: registry, mirror (a mirror is one way to reach the same source)
214
214
 
215
+ **Update Mirror**:
216
+ A PyPI package index the user names for one `update` run (`--mirror <tag|url>`). It replaces the default Release Source for both the Version Check (read from the index's simple page) and the install of that run, and is never saved. Distributions with their own Release Source refuse it.
217
+ _Avoid_: Python download mirror (that is `UV_PYTHON_INSTALL_MIRROR`), update source setting
218
+
215
219
  **Side-Install**:
216
220
  Installing a new CLI version into its own version-isolated location without touching the currently running installation. Used where the running installation cannot be rebuilt in place.
217
221
  _Avoid_: in-place upgrade, reinstall, versioned install
@@ -389,7 +393,7 @@ _Avoid_: lag log, profiler output (the profiler records phase durations, not a s
389
393
  - **Self-Update** and **Plugin Auto Update** are separate concepts with separate vocabularies: a **Version Check** orders versions, plugin **Update Detection** only compares for equality. Neither triggers the other.
390
394
  - A **Side-Install** followed by an **Entrypoint Flip** is one Self-Update strategy; an in-process reinstall of the current installation is another. Which one applies is a property of the platform, not of the user's choice.
391
395
  - **Restart-to-Apply** holds for every Self-Update strategy and mirrors the plugin **Update Effectiveness Boundary**: on-disk state changes, the running process does not.
392
- - **Self-Update** is the only way an installation reaches the target Python (3.12, ADR 0055). A CLI that runs on another interpreter stays there until its next Self-Update.
396
+ - **Self-Update** keeps the installation on the interpreter it runs on: every uv install command requests the running `major.minor` (ADR 0064), unless the distribution profile's `install_args` already pins `--python`. There is no target Python; a CLI moves to another interpreter only when a whitelabel pin asks for it.
393
397
 
394
398
  - A **Session Title** is a fact of the session, not of the **Session Report**: it exists whether or not a report backend is configured, and the report only mirrors it. **Durable Title Completion** is therefore judged from the session's own metadata.
395
399
  - A **Session Title** is generated from the session's earliest **Committed Title Input**, never from the latest one. A resumed session without a title is titled from its original first input, so the title does not change to whatever was typed after resume.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: comate-cli
3
- Version: 0.12.7b1
3
+ Version: 0.12.8
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
@@ -317,6 +317,9 @@ class _ShutdownNoiseGuard:
317
317
 
318
318
 
319
319
  def _usage_text(command_name: str = "comate") -> str:
320
+ # 懒导入:usage 只在 --help 与参数错误时生成,不让启动路径多 import 更新模块。
321
+ from comate_cli.update_cli import UPDATE_MIRROR_TAGS
322
+
320
323
  return (
321
324
  "Usage:\n"
322
325
  f" {command_name} [--rpc-stdio] [--add-dir <path>]...\n"
@@ -326,7 +329,7 @@ def _usage_text(command_name: str = "comate") -> str:
326
329
  f" {command_name} -p [--output-format text|json] <prompt>\n"
327
330
  f" {command_name} resume [<session_id>]\n"
328
331
  f" {command_name} mcp <subcommand> [options]\n"
329
- f" {command_name} update [--pre]\n"
332
+ f" {command_name} update [--pre] [--mirror <tag|url>]\n"
330
333
  "\n"
331
334
  f'MCP subcommands (run "{command_name} mcp <subcommand> --help" for details):\n'
332
335
  f" add Add an MCP server to {command_name}\n"
@@ -366,7 +369,10 @@ def _usage_text(command_name: str = "comate") -> str:
366
369
  " bypassPermissions; refused by default\n"
367
370
  " --yolo Start in bypassPermissions (YOLO) mode\n"
368
371
  " --version, -V Print version and exit\n"
369
- " --pre (update) Also consider pre-release versions"
372
+ " --pre (update) Also consider pre-release versions\n"
373
+ " --mirror <tag|url> (update) PyPI package index for this update only (not the Python\n"
374
+ " download mirror): an http(s):// URL or one of\n"
375
+ f" {', '.join(UPDATE_MIRROR_TAGS)}"
370
376
  )
371
377
 
372
378
 
@@ -881,19 +887,18 @@ def main(argv: list[str] | None = None, *, profile=None) -> None:
881
887
  return
882
888
 
883
889
  if run_argv and run_argv[0] == "update":
884
- update_args = run_argv[1:]
885
- include_prereleases = "--pre" in update_args
886
- unknown = [arg for arg in update_args if arg != "--pre"]
887
- if unknown:
888
- sys.stderr.write(
889
- f"update: unknown arguments: {' '.join(unknown)}\n"
890
- f"{_usage_text(command_name=command_name)}\n"
891
- )
892
- raise SystemExit(2)
893
- from comate_cli.update_cli import run_update_cli
890
+ from comate_cli.update_cli import UpdateArgumentError, parse_update_args, run_update_cli
891
+
892
+ try:
893
+ include_prereleases, index_url = parse_update_args(run_argv[1:])
894
+ except UpdateArgumentError as exc:
895
+ sys.stderr.write(f"update: {exc}\n{_usage_text(command_name=command_name)}\n")
896
+ raise SystemExit(2) from None
894
897
 
895
898
  raise SystemExit(
896
- run_update_cli(profile=profile, include_prereleases=include_prereleases)
899
+ run_update_cli(
900
+ profile=profile, include_prereleases=include_prereleases, index_url=index_url
901
+ )
897
902
  )
898
903
 
899
904
  if run_argv and run_argv[0] == "mcp":
@@ -398,6 +398,7 @@ async def stage_update(
398
398
  _notify(progress, StagePhase.STAGING)
399
399
  # 延迟导入理由同 _staging_env:顶层互导会成环。
400
400
  from comate_cli.terminal_agent.update_check import (
401
+ default_index_args,
401
402
  index_strategy_fallback_args,
402
403
  python_request_args,
403
404
  )
@@ -414,6 +415,7 @@ async def stage_update(
414
415
  "--refresh",
415
416
  *python_request_args(target.install_args),
416
417
  *index_strategy_fallback_args(target.install_args),
418
+ *default_index_args(target.index_url),
417
419
  *target.install_args,
418
420
  )
419
421
  code, output = await run(
@@ -190,6 +190,9 @@ class UpdateTarget:
190
190
  install_args: tuple[str, ...] = ()
191
191
  command_name: str = "comate"
192
192
  python_install_mirror: str | None = None
193
+ # `<command> update --mirror` 指定的包索引(simple 地址);只在这一次运行里有效。
194
+ # 设置后 Version Check 读它的 simple 页,三条安装路径都带 --default-index。
195
+ index_url: str | None = None
193
196
 
194
197
  def update_command(self, *, pin_version: str | None = None) -> tuple[str, ...]:
195
198
  """进程内重装命令(macOS/Linux 路径)。"""
@@ -205,6 +208,7 @@ class UpdateTarget:
205
208
  "--refresh",
206
209
  *python_request_args(self.install_args),
207
210
  *index_strategy_fallback_args(self.install_args),
211
+ *default_index_args(self.index_url),
208
212
  *self.install_args,
209
213
  )
210
214
 
@@ -274,6 +278,17 @@ def _pins_default_index(install_args: tuple[str, ...]) -> bool:
274
278
  return any(arg in _DEFAULT_INDEX_FLAGS for arg in install_args)
275
279
 
276
280
 
281
+ def has_own_update_source(target: UpdateTarget) -> bool:
282
+ """白牌自己管理更新源(profile 查询源或 install_args 已设默认索引):此时拒绝 --mirror。
283
+ uv 对重复的 --default-index 直接报错(实测 2026-11-06)。"""
284
+ return target.fetch_latest is not None or _pins_default_index(target.install_args)
285
+
286
+
287
+ def default_index_args(index_url: str | None) -> tuple[str, ...]:
288
+ # 命令行的 --default-index 盖过子进程环境里注入的清华 UV_DEFAULT_INDEX(实测 2026-11-06)。
289
+ return ("--default-index", index_url) if index_url else ()
290
+
291
+
277
292
  def _install_spec(package: str, pin_version: str | None) -> str:
278
293
  """正式版沿用 `@latest`;目标是预发布版时精确 pin `==<version>`:`@latest`
279
294
  会解析到最新正式版,把 beta 用户降级(Q9 预发布规则的另一半)。
@@ -296,10 +311,15 @@ def index_strategy_fallback_args(install_args: tuple[str, ...]) -> tuple[str, ..
296
311
  return () if "--index-strategy" in install_args else _INDEX_STRATEGY_FALLBACK
297
312
 
298
313
 
299
- # CLI 的目标运行时(ADR 0055)。uv 在读包之前就选好 tool 环境的解释器,且忽略
300
- # requires-python 上限,所以只有命令里的 --python 能定运行时;实测 2026-11-02:
301
- # 不带它的 `--force` 重装把 3.12 环境重建到了 uv 默认找到的 3.13 上。
302
- TARGET_PYTHON = "3.12"
314
+ def _running_python() -> str:
315
+ """当前进程解释器的 `主版本.次版本`:Self-Update 后保持在这个版本上(ADR 0064)。
316
+
317
+ uv 在读包之前就选好 tool 环境的解释器,且忽略 requires-python 上限,所以只有命令里的
318
+ --python 能定运行时;实测 2026-11-02:不带它的 `--force` 重装把 3.12 环境重建到了
319
+ uv 默认找到的 3.13 上。不带补丁号:当前解释器已在机器上,uv 不用下载。
320
+ """
321
+ major, minor = sys.version_info[:2]
322
+ return f"{major}.{minor}"
303
323
 
304
324
 
305
325
  def _pins_python(install_args: tuple[str, ...]) -> bool:
@@ -313,7 +333,7 @@ def _pins_python(install_args: tuple[str, ...]) -> bool:
313
333
 
314
334
 
315
335
  def python_request_args(install_args: tuple[str, ...]) -> tuple[str, ...]:
316
- return () if _pins_python(install_args) else ("--python", TARGET_PYTHON)
336
+ return () if _pins_python(install_args) else ("--python", _running_python())
317
337
 
318
338
 
319
339
  def windows_update_command(
@@ -336,9 +356,15 @@ def windows_update_command(
336
356
  target.package,
337
357
  *python_request_args(target.install_args),
338
358
  *index_strategy_fallback_args(target.install_args),
359
+ *default_index_args(target.index_url),
339
360
  *target.install_args,
340
361
  ]
341
- if _is_chinese_locale() and not _pins_default_index(target.install_args):
362
+ # 用户用 --mirror 指定了索引时不追加清华:uv 对重复的 --default-index 直接报错。
363
+ if (
364
+ _is_chinese_locale()
365
+ and target.index_url is None
366
+ and not _pins_default_index(target.install_args)
367
+ ):
342
368
  command += ["--default-index", TUNA_PYPI_INDEX]
343
369
  return tuple(command)
344
370
 
@@ -414,8 +440,9 @@ def _is_chinese_locale() -> bool:
414
440
  def uv_default_index_env(*, python_install_mirror: str | None = None) -> dict[str, str]:
415
441
  """uv 安装子进程的镜像环境变量。
416
442
 
417
- 简中 locale:包索引(清华)与 Python 下载镜像(npmmirror)。安装命令带 --python 3.12,
418
- 机器上没有 3.12 时 uv 默认从 GitHub 下载,国内可能慢或失败(ADR 0055 取舍四)。
443
+ 简中 locale:包索引(清华)与 Python 下载镜像(npmmirror)。安装命令请求的 Python
444
+ (白牌在 install_args 里指定的版本)机器上没有时,uv 默认从 GitHub 下载,国内可能慢或
445
+ 失败(ADR 0055 取舍四)。
419
446
  白牌镜像 `python_install_mirror` 不看 locale,并且盖过 npmmirror(ADR 0056)。
420
447
  调用方以 setdefault 语义合并,用户已显式设置的同名变量不覆盖。
421
448
  """
@@ -462,6 +489,125 @@ def pypi_json_source(
462
489
  return fetch
463
490
 
464
491
 
492
+ # PEP 691 JSON 优先,退回 PEP 503 HTML。实测 2026-11-06:pypi.org / 清华 / 中科大回 JSON,
493
+ # 阿里云 / 腾讯云 / 华为云只回 HTML;后三家的 `/pypi/<pkg>/json` 都是 404,所以 --mirror 不用 JSON API。
494
+ _SIMPLE_INDEX_ACCEPT = "application/vnd.pypi.simple.v1+json, text/html;q=0.1"
495
+
496
+
497
+ def simple_index_source(
498
+ package: str,
499
+ index_url: str,
500
+ *,
501
+ include_prereleases: bool = False,
502
+ ) -> LatestVersionFetcher:
503
+ """`--mirror` 的 Version Check:读 `<index_url>/<package>/`,从文件名取版本。"""
504
+
505
+ async def fetch() -> LatestRelease | None:
506
+ from packaging.utils import canonicalize_name
507
+
508
+ url = f"{index_url}/{canonicalize_name(package)}/"
509
+ files = await _fetch_simple_index_files(url, trust_env=_update_check_trust_env())
510
+ payload = _simple_index_payload(files, package)
511
+ latest = _select_latest_version(
512
+ payload,
513
+ current=installed_version(package),
514
+ include_prereleases=include_prereleases,
515
+ )
516
+ return LatestRelease(version=latest)
517
+
518
+ return fetch
519
+
520
+
521
+ async def _fetch_simple_index_files(url: str, *, trust_env: bool) -> list[tuple[str, bool]]:
522
+ """返回 (文件名, 是否 yanked) 列表。网络/解析失败直接抛,由 `<command> update` 报「连不上」。"""
523
+ import httpx
524
+
525
+ client_kwargs: dict[str, Any] = {"timeout": 3.0, "trust_env": trust_env}
526
+ if not trust_env:
527
+ ssl_context = await _get_update_check_ssl_context_off_loop()
528
+ if ssl_context is None:
529
+ raise _UpdateCheckTransportUnavailable("update check SSL context is unavailable")
530
+ client_kwargs["verify"] = ssl_context
531
+ async with httpx.AsyncClient(**client_kwargs) as client:
532
+ resp = await client.get(
533
+ url, headers={"Accept": _SIMPLE_INDEX_ACCEPT}, follow_redirects=True
534
+ )
535
+ resp.raise_for_status()
536
+ if "application/vnd.pypi.simple.v1+json" in resp.headers.get("content-type", ""):
537
+ return [
538
+ (str(item["filename"]), bool(item.get("yanked")))
539
+ for item in resp.json()["files"]
540
+ ]
541
+ return _parse_simple_index_html(resp.text)
542
+
543
+
544
+ def _parse_simple_index_html(text: str) -> list[tuple[str, bool]]:
545
+ """PEP 503:每个 `<a>` 的文本是文件名;有 `data-yanked` 属性即 yanked(PEP 592)。"""
546
+ from html.parser import HTMLParser
547
+
548
+ class _Links(HTMLParser):
549
+ def __init__(self) -> None:
550
+ super().__init__()
551
+ self.files: list[tuple[str, bool]] = []
552
+ self._open: tuple[bool, list[str]] | None = None
553
+
554
+ def handle_starttag(self, tag: str, attrs: list[tuple[str, str | None]]) -> None:
555
+ if tag == "a":
556
+ self._open = (any(name == "data-yanked" for name, _ in attrs), [])
557
+
558
+ def handle_data(self, data: str) -> None:
559
+ if self._open is not None:
560
+ self._open[1].append(data)
561
+
562
+ def handle_endtag(self, tag: str) -> None:
563
+ if tag == "a" and self._open is not None:
564
+ yanked, parts = self._open
565
+ self.files.append(("".join(parts).strip(), yanked))
566
+ self._open = None
567
+
568
+ parser = _Links()
569
+ parser.feed(text)
570
+ parser.close()
571
+ return parser.files
572
+
573
+
574
+ def _simple_index_payload(files: list[tuple[str, bool]], package: str) -> dict[str, Any]:
575
+ """把文件列表整理成 PyPI JSON 的形状,交给 _select_latest_version 套用同一套预发布规则。
576
+
577
+ `info.version` 取最大的未 yanked 正式版(没有正式版时取最大的未 yanked 版本);
578
+ 一个版本的文件全部 yanked 才算 yanked,与 _select_latest_version 一致。
579
+ """
580
+ from packaging.utils import canonicalize_name, parse_sdist_filename, parse_wheel_filename
581
+ from packaging.version import Version
582
+
583
+ wanted = canonicalize_name(package)
584
+ releases: dict[str, list[dict[str, bool]]] = {}
585
+ for filename, yanked in files:
586
+ try:
587
+ if filename.endswith(".whl"):
588
+ name, version, _build, _tags = parse_wheel_filename(filename)
589
+ elif filename.endswith((".tar.gz", ".zip")):
590
+ name, version = parse_sdist_filename(filename)
591
+ else:
592
+ continue
593
+ except ValueError:
594
+ logger.debug("skipping unparsable index file name: %s", filename)
595
+ continue
596
+ if name != wanted:
597
+ continue
598
+ releases.setdefault(str(version), []).append({"yanked": yanked})
599
+
600
+ available = [
601
+ Version(raw)
602
+ for raw, entries in releases.items()
603
+ if not all(entry["yanked"] for entry in entries)
604
+ ]
605
+ if not available:
606
+ raise ValueError(f"no installable {package} versions on the index")
607
+ stable = [version for version in available if not version.is_prerelease]
608
+ return {"info": {"version": str(max(stable or available))}, "releases": releases}
609
+
610
+
465
611
  def _select_latest_version(
466
612
  payload: dict[str, Any],
467
613
  *,
@@ -595,6 +741,10 @@ async def fetch_latest_release(
595
741
  启动期 best-effort 语义。include_prereleases 只对 PyPI 源有意义:白牌
596
742
  profile 源只回一个版本号,没有预发布的概念。
597
743
  """
744
+ if target.index_url is not None:
745
+ return await simple_index_source(
746
+ target.package, target.index_url, include_prereleases=include_prereleases
747
+ )()
598
748
  profile_fetch_latest = target.fetch_latest
599
749
  if profile_fetch_latest is not None:
600
750
  return await _fetch_profile_latest_with_timeout(profile_fetch_latest)
@@ -673,6 +823,7 @@ def _target_for_info(info: UpdateInfo, target: UpdateTarget | None = None) -> Up
673
823
  install_args=target.install_args,
674
824
  command_name=target.command_name,
675
825
  python_install_mirror=target.python_install_mirror,
826
+ index_url=target.index_url,
676
827
  )
677
828
  return UpdateTarget(
678
829
  package=info.package,
@@ -1044,7 +1195,7 @@ async def run_update_command(
1044
1195
  def _write_plain_after_reinstall(console: Console, text: str) -> None:
1045
1196
  """成功重装之后写终端:不经过 Rich。
1046
1197
 
1047
- 换解释器的重装(Self-Update 带 --python 3.12)会删掉旧的
1198
+ 换解释器的重装(例如白牌 install_args 指定了别的 --python)会删掉旧的
1048
1199
  lib/python3.X/site-packages,之后任何懒 import 都会 ModuleNotFoundError。Rich 渲染
1049
1200
  非 ASCII 字符时懒加载 rich._unicode_data:真机实测 2026-11-02,
1050
1201
  `comate update`(3.13 → 3.12)在打印成功文案时崩溃。
@@ -44,6 +44,9 @@ class UpdateMessages:
44
44
  update_cli_unreachable: str
45
45
  update_cli_editable: str
46
46
  update_cli_uv_missing: str
47
+ # `<command> update --mirror`:这次运行用的包索引;白牌自管更新源时拒绝
48
+ update_cli_using_mirror: str
49
+ update_cli_mirror_unsupported: str
47
50
 
48
51
 
49
52
  _MESSAGES: dict[str, UpdateMessages] = {
@@ -107,6 +110,8 @@ _MESSAGES: dict[str, UpdateMessages] = {
107
110
  "uv was not found on PATH, so {product} cannot update itself. "
108
111
  "Install uv (https://docs.astral.sh/uv/) and run `{command}`."
109
112
  ),
113
+ update_cli_using_mirror="Using package index: {url}",
114
+ update_cli_mirror_unsupported="{product} uses its own update source, so --mirror is not supported.",
110
115
  ),
111
116
  "zh_cn": UpdateMessages(
112
117
  hint=(
@@ -163,6 +168,8 @@ _MESSAGES: dict[str, UpdateMessages] = {
163
168
  "PATH 上找不到 uv,{product} 无法自更新。"
164
169
  "请先安装 uv(https://docs.astral.sh/uv/),再运行 `{command}`。"
165
170
  ),
171
+ update_cli_using_mirror="使用包索引:{url}",
172
+ update_cli_mirror_unsupported="{product} 使用自己的更新源,不支持 --mirror。",
166
173
  ),
167
174
  "zh_tw": UpdateMessages(
168
175
  hint=(
@@ -219,6 +226,8 @@ _MESSAGES: dict[str, UpdateMessages] = {
219
226
  "PATH 上找不到 uv,{product} 無法自我更新。"
220
227
  "請先安裝 uv(https://docs.astral.sh/uv/),再執行 `{command}`。"
221
228
  ),
229
+ update_cli_using_mirror="使用套件索引:{url}",
230
+ update_cli_mirror_unsupported="{product} 使用自己的更新來源,不支援 --mirror。",
222
231
  ),
223
232
  "ja": UpdateMessages(
224
233
  hint=(
@@ -279,6 +288,8 @@ _MESSAGES: dict[str, UpdateMessages] = {
279
288
  "PATH に uv が見つからないため、{product} は自己更新できません。"
280
289
  "uv(https://docs.astral.sh/uv/)をインストールしてから `{command}` を実行してください。"
281
290
  ),
291
+ update_cli_using_mirror="使用するパッケージインデックス:{url}",
292
+ update_cli_mirror_unsupported="{product} は独自の更新元を使うため、--mirror は使えません。",
282
293
  ),
283
294
  }
284
295
 
@@ -2,13 +2,14 @@
2
2
 
3
3
  流程:安装方式探测 → Version Check → 打印结果 → 交给 update_check 的平台
4
4
  升级路径(macOS/Linux 进程内 uv 重装;Windows Side-Install + Entrypoint Flip)。
5
- 退出码:0=成功或已最新,1=失败/无法检查/不支持,130=中断。
5
+ 退出码:0=成功或已最新,1=失败/无法检查/不支持,2=白牌不支持 --mirror,130=中断。
6
6
  所有用户可见文案来自 update_messages(四 locale),命令名/包名来自发行配置。
7
7
  """
8
8
 
9
9
  from __future__ import annotations
10
10
 
11
11
  import asyncio
12
+ import dataclasses
12
13
  import logging
13
14
  from typing import TYPE_CHECKING
14
15
 
@@ -16,10 +17,12 @@ from rich.console import Console
16
17
 
17
18
  from comate_cli.terminal_agent import theme
18
19
  from comate_cli.terminal_agent.update_check import (
20
+ TUNA_PYPI_INDEX,
19
21
  InstallKind,
20
22
  UpdateInfo,
21
23
  detect_install_kind,
22
24
  fetch_latest_release,
25
+ has_own_update_source,
23
26
  installed_version,
24
27
  run_update_command,
25
28
  update_target_from_profile,
@@ -32,12 +35,82 @@ logger = logging.getLogger(__name__)
32
35
 
33
36
  # InstallKind / detect_install_kind 已搬到 update_check(启动期提示也要用),这里保留导入。
34
37
 
38
+ # `--mirror <tag>` 可用的 PyPI 包索引(simple 地址)。2026-11-06 逐个实测都能返回 simple 页。
39
+ UPDATE_MIRROR_TAGS: dict[str, str] = {
40
+ "pypi": "https://pypi.org/simple",
41
+ "tuna": TUNA_PYPI_INDEX,
42
+ "aliyun": "https://mirrors.aliyun.com/pypi/simple",
43
+ "tencent": "https://mirrors.cloud.tencent.com/pypi/simple",
44
+ "huawei": "https://repo.huaweicloud.com/repository/pypi/simple",
45
+ "ustc": "https://mirrors.ustc.edu.cn/pypi/simple",
46
+ }
47
+
48
+
49
+ class UpdateArgumentError(ValueError):
50
+ """`<command> update` 的参数不合法;main 打印原因与 usage 后以退出码 2 结束。"""
51
+
52
+
53
+ def parse_update_args(args: list[str]) -> tuple[bool, str | None]:
54
+ """解析 `update [--pre] [--mirror <tag|url>]`,返回 (include_prereleases, index_url)。"""
55
+ include_prereleases = False
56
+ mirror_values: list[str] = []
57
+ unknown: list[str] = []
58
+ index = 0
59
+ while index < len(args):
60
+ arg = args[index]
61
+ if arg == "--pre":
62
+ include_prereleases = True
63
+ elif arg == "--mirror":
64
+ # 下一个参数缺失或是另一个 flag(例:`--mirror --pre`)都算没给值。
65
+ if index + 1 >= len(args) or args[index + 1].startswith("-"):
66
+ raise UpdateArgumentError("--mirror requires a value")
67
+ index += 1
68
+ mirror_values.append(args[index])
69
+ elif arg.startswith("--mirror="):
70
+ value = arg.split("=", 1)[1]
71
+ if not value.strip():
72
+ raise UpdateArgumentError("--mirror requires a value")
73
+ mirror_values.append(value)
74
+ else:
75
+ unknown.append(arg)
76
+ index += 1
77
+ if unknown:
78
+ raise UpdateArgumentError(f"unknown arguments: {' '.join(unknown)}")
79
+ if len(mirror_values) > 1:
80
+ raise UpdateArgumentError("--mirror can only be given once")
81
+ index_url = resolve_update_mirror(mirror_values[0]) if mirror_values else None
82
+ return include_prereleases, index_url
83
+
84
+
85
+ def resolve_update_mirror(value: str) -> str:
86
+ """`http://` / `https://` 开头按 URL(去掉结尾 /),否则按 tag 查表(不分大小写)。"""
87
+ raw = value.strip()
88
+ if raw.lower().startswith(("http://", "https://")):
89
+ return raw.rstrip("/")
90
+ url = UPDATE_MIRROR_TAGS.get(raw.lower())
91
+ if url is None:
92
+ raise UpdateArgumentError(
93
+ f"unknown mirror {value!r}; use an http(s):// URL or one of: "
94
+ + ", ".join(UPDATE_MIRROR_TAGS)
95
+ )
96
+ return url
97
+
35
98
 
36
- def run_update_cli(*, profile: "DistributionProfile", include_prereleases: bool = False) -> int:
99
+ def run_update_cli(
100
+ *,
101
+ profile: "DistributionProfile",
102
+ include_prereleases: bool = False,
103
+ index_url: str | None = None,
104
+ ) -> int:
37
105
  console = Console()
38
106
  try:
39
107
  return asyncio.run(
40
- _run_update(profile=profile, console=console, include_prereleases=include_prereleases)
108
+ _run_update(
109
+ profile=profile,
110
+ console=console,
111
+ include_prereleases=include_prereleases,
112
+ index_url=index_url,
113
+ )
41
114
  )
42
115
  except KeyboardInterrupt:
43
116
  return 130
@@ -48,6 +121,7 @@ async def _run_update(
48
121
  profile: "DistributionProfile",
49
122
  console: Console,
50
123
  include_prereleases: bool = False,
124
+ index_url: str | None = None,
51
125
  ) -> int:
52
126
  from comate_cli.terminal_agent.update_messages import get_update_messages
53
127
  from packaging.version import InvalidVersion, Version
@@ -55,6 +129,16 @@ async def _run_update(
55
129
  target = update_target_from_profile(profile)
56
130
  messages = get_update_messages()
57
131
 
132
+ if index_url is not None:
133
+ if has_own_update_source(target):
134
+ console.print(
135
+ messages.update_cli_mirror_unsupported.format(product=target.product_label),
136
+ style=theme.ERROR,
137
+ markup=False,
138
+ )
139
+ return 2
140
+ target = dataclasses.replace(target, index_url=index_url)
141
+
58
142
  kind = detect_install_kind(target.package)
59
143
  if kind is InstallKind.EDITABLE:
60
144
  console.print(
@@ -74,6 +158,8 @@ async def _run_update(
74
158
  )
75
159
  return 1
76
160
 
161
+ if target.index_url is not None:
162
+ console.print(messages.update_cli_using_mirror.format(url=target.index_url), markup=False)
77
163
  console.print(messages.update_cli_checking, markup=False)
78
164
  current = installed_version(target.package)
79
165
  try:
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "comate-cli"
7
- version = "0.12.7b1"
7
+ version = "0.12.8"
8
8
  description = "Comate terminal CLI built on comate-agent-sdk"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11,<3.14"
@@ -12,6 +12,7 @@ Windows 独有的 OS 文件锁行为不进单测,归 tools/verify_windows_self
12
12
  from __future__ import annotations
13
13
 
14
14
  import os
15
+ import sys
15
16
  import time
16
17
  import unittest
17
18
  from pathlib import Path
@@ -21,6 +22,9 @@ from unittest.mock import patch
21
22
  from comate_cli.terminal_agent import side_install as vi
22
23
  from comate_cli.terminal_agent.update_check import UpdateInfo, UpdateTarget
23
24
 
25
+ # 旁装命令请求当前解释器的 主版本.次版本(ADR 0064)。
26
+ _RUNNING_PYTHON = f"{sys.version_info.major}.{sys.version_info.minor}"
27
+
24
28
 
25
29
  def _target(**overrides) -> UpdateTarget:
26
30
  base = dict(
@@ -255,19 +259,36 @@ class _FakeUv:
255
259
 
256
260
 
257
261
  class TestStageUpdate(unittest.IsolatedAsyncioTestCase):
258
- async def test_side_install_requests_target_python(self) -> None:
259
- """Windows 的 Self-Update 也必须把新版本装到 3.12(ADR 0055):旁装是全新的
260
- tool 环境,不带 --python 时 uv 用它默认找到的解释器,Windows 用户就永远落不到 3.12。"""
261
- with TemporaryDirectory() as tmp:
262
+ async def test_side_install_requests_running_python(self) -> None:
263
+ """Windows 的 Self-Update 也要把新版本装在当前解释器的 主版本.次版本上(ADR 0064):
264
+ 旁装是全新的 tool 环境,不带 --python 时 uv 用它默认找到的解释器,更新后就换了 Python。
265
+ 伪造成 3.14(不在 requires-python 范围内):改回固定版本或加范围判断,这里会失败。"""
266
+ with TemporaryDirectory() as tmp, patch(
267
+ "comate_cli.terminal_agent.update_check.sys.version_info", (3, 14, 2, "final", 0)
268
+ ):
262
269
  base = Path(tmp)
263
270
  fake = _FakeUv(base)
264
271
  await vi.stage_update(_info(), _target(), layout=_layout_for(base), run_command=fake)
265
272
  install_cmd, _ = fake.calls[0]
266
273
  self.assertIn("--python", install_cmd)
267
- self.assertEqual(install_cmd[install_cmd.index("--python") + 1], "3.12")
274
+ self.assertEqual(install_cmd[install_cmd.index("--python") + 1], "3.14")
275
+
276
+ async def test_side_install_installs_from_update_mirror(self) -> None:
277
+ """`update --mirror`:Windows 旁装也要从查版本的那个索引装包,否则精确 pin 的版本
278
+ 在 uv 的默认索引上可能还不存在(镜像落后时正是用户换镜像的原因)。"""
279
+ mirror = "https://mirrors.example/pypi/simple"
280
+ with TemporaryDirectory() as tmp:
281
+ base = Path(tmp)
282
+ fake = _FakeUv(base)
283
+ await vi.stage_update(
284
+ _info(), _target(install_args=(), index_url=mirror), layout=_layout_for(base), run_command=fake
285
+ )
286
+ install_cmd, _ = fake.calls[0]
287
+ defaults = [install_cmd[i + 1] for i, arg in enumerate(install_cmd) if arg == "--default-index"]
288
+ self.assertEqual(defaults, [mirror])
268
289
 
269
290
  async def test_zh_cn_side_install_downloads_python_through_mirror(self) -> None:
270
- """旁装要求 3.12,机器上没有时 uv 从 GitHub 下载,国内可能失败(ADR 0055 取舍四);
291
+ """旁装请求的 Python 机器上没有时 uv 从 GitHub 下载,国内可能失败(ADR 0055 取舍四);
271
292
  用户自己设置的镜像必须保留。"""
272
293
  mirror = "https://registry.npmmirror.com/-/binary/python-build-standalone"
273
294
  own = "https://mirror.corp.example/python-build-standalone"
@@ -329,7 +350,7 @@ class TestStageUpdate(unittest.IsolatedAsyncioTestCase):
329
350
  "uv", "tool", "install", "acme-cli==1.1.0",
330
351
  "--refresh",
331
352
  "--python",
332
- "3.12",
353
+ _RUNNING_PYTHON,
333
354
  "--index-strategy", "unsafe-first-match",
334
355
  "--default-index", "https://pypi.example.com/simple",
335
356
  ),