comate-cli 0.7.1__tar.gz → 0.7.2__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.
- {comate_cli-0.7.1 → comate_cli-0.7.2}/PKG-INFO +1 -1
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/app.py +40 -68
- comate_cli-0.7.2/comate_cli/terminal_agent/update_check.py +334 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/pyproject.toml +7 -1
- comate_cli-0.7.2/tests/test_update_check.py +371 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/uv.lock +1457 -1441
- comate_cli-0.7.1/tests/test_update_check.py +0 -201
- {comate_cli-0.7.1 → comate_cli-0.7.2}/.gitignore +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/AGENTS.md +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/CHANGELOG.md +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/README.md +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/__init__.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/__main__.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/main.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/mcp_cli.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/__init__.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/animations.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/assistant_render.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/codenames.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/config/__init__.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/config/model.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/config/picker.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/config/picker_state.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/config/store.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/custom_slash_commands.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/env_utils.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/error_display.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/event_renderer.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/figures.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/fragment_utils.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/history_printer.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/input_geometry.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/layout_coordinator.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/logging_adapter.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/logo.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/markdown_render.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/mention_completer.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/message_style.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/models.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/path_context_hint.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/plugins/__init__.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/plugins/components/__init__.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/plugins/components/detail_view.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/plugins/components/plugin_list.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/plugins/components/search_box.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/plugins/components/tab_bar.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/plugins/marketplace_install_view.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/plugins/plugin_picker.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/plugins/tabs/__init__.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/plugins/tabs/discover_tab.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/plugins/tabs/errors_tab.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/plugins/tabs/installed_tab.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/plugins/tabs/marketplaces_tab.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/preflight.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/question_view.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/resume_picker.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/resume_preview.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/resume_selector.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/rpc_protocol.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/rpc_stdio.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/selection_menu.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/slash_commands.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/startup.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/status_bar.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/statusline/__init__.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/statusline/model.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/statusline/picker.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/statusline/picker_state.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/statusline/store.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/text_effects.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/tips.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/tool_fold.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/tool_result_formatters.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/tool_result_store.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/tool_result_viewer.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/tool_view.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/transcript_viewer.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/tui.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/tui_parts/__init__.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/tui_parts/btw_view.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/tui_parts/commands.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/tui_parts/history_sync.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/tui_parts/input_behavior.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/tui_parts/key_bindings.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/tui_parts/mcp_connecting_view.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/tui_parts/render_panels.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/tui_parts/slash_command_registry.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/comate_cli/terminal_agent/tui_parts/ui_mode.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/docs/hooks.md +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/docs/superpowers/plans/2026-04-03-phrase-shuffle.md +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/docs/superpowers/plans/2026-05-22-log-style-implementation-plan.md +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/docs/superpowers/specs/2026-04-01-conditional-diff-subtitle-design.md +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/docs/superpowers/specs/2026-04-03-phrase-shuffle-design.md +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/docs/superpowers/specs/2026-05-22-comate-cli-log-styling-design.md +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/docs/superpowers/specs/2026-05-22-log-style-optimization-design.md +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/report.md +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/config/__init__.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/config/test_model.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/config/test_picker_state.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/config/test_picker_ui.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/config/test_roundtrip.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/config/test_store_load.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/config/test_store_save.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/conftest.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/fixtures/fake_mcp_misbehaving_stdout.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/statusline/__init__.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/statusline/test_model.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/statusline/test_picker_state.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/statusline/test_store.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_animator_shuffle.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_app_mcp_preload.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_app_preflight_gate.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_app_print_mode.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_app_shutdown.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_app_usage_line.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_btw_slash_command.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_cli_project_root.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_compact_command_semantics.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_completion_context_activation.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_completion_status_panel.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_context_command.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_custom_slash_commands.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_discover_tab.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_errors_tab.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_event_renderer.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_event_renderer_boundary.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_event_renderer_e2e.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_event_renderer_log_boundary.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_event_renderer_log_queue.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_event_renderer_streaming.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_event_renderer_tool_fold.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_format_error.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_handle_error.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_history_printer.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_history_printer_log.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_history_printer_subtitle_position.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_history_printer_tool_fold.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_history_sync.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_history_sync_tool_fold.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_input_behavior.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_input_history.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_installed_tab.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_interrupt_exit_semantics.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_layout_coordinator.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_logging_adapter.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_logo.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_main_args.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_markdown_render.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_marketplaces_tab.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_mcp_cli.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_mcp_slash_command.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_mention_completer.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_path_context_hint.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_plugin_slash_commands.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_plugin_tui_components.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_preflight.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_preflight_copilot.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_question_key_bindings.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_question_view.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_resume_picker.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_resume_preview.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_resume_selector.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_rewind_command_semantics.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_rpc_protocol.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_rpc_stdio_bridge.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_selection_menu.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_session_query_token_summary.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_shutdown_noise_guard.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_shutdown_noise_integration.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_skills_slash_command.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_slash_argument_hint.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_slash_clear.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_slash_completer.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_slash_registry.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_status_bar.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_status_bar_transient.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_task_panel_format.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_task_panel_key_bindings.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_task_panel_rendering.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_task_poll.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_tool_fold.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_tool_fold_panel.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_tool_result_formatters.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_tool_result_store.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_tool_result_viewer.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_tool_result_viewer_key_bindings.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_tool_view.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_transcript_viewer.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_transcript_viewer_tool_fold.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_tui_elapsed_status.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_tui_esc_queue.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_tui_mcp_init_gate.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_tui_paste_newline_guard.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_tui_paste_placeholder.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_tui_queue_preview.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_tui_queue_sdk_source.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_tui_split_invariance.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_tui_team_messages.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_tui_thinking_display.py +0 -0
- {comate_cli-0.7.1 → comate_cli-0.7.2}/tests/test_tui_tool_result_registry_lifecycle.py +0 -0
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import asyncio
|
|
4
|
-
import importlib.metadata
|
|
5
|
-
import locale
|
|
6
4
|
import logging
|
|
7
5
|
import os
|
|
8
6
|
import random
|
|
@@ -27,6 +25,18 @@ from comate_cli.terminal_agent.resume_selector import select_resume_session_id
|
|
|
27
25
|
from comate_cli.terminal_agent.rpc_stdio import StdioRPCBridge
|
|
28
26
|
from comate_cli.terminal_agent.status_bar import StatusBar
|
|
29
27
|
from comate_cli.terminal_agent.tui import TerminalAgentTUI
|
|
28
|
+
from comate_cli.terminal_agent.update_check import (
|
|
29
|
+
UpdateInfo,
|
|
30
|
+
UpdatePromptChoice,
|
|
31
|
+
UpdatePromptDecision,
|
|
32
|
+
check_update,
|
|
33
|
+
decide_update_prompt,
|
|
34
|
+
format_update_hint,
|
|
35
|
+
mark_update_seen,
|
|
36
|
+
record_skip_until_next_version,
|
|
37
|
+
run_update_command,
|
|
38
|
+
show_update_prompt,
|
|
39
|
+
)
|
|
30
40
|
|
|
31
41
|
console = Console()
|
|
32
42
|
logger = logging.getLogger(__name__)
|
|
@@ -37,70 +47,32 @@ def _resolve_cli_project_root() -> Path:
|
|
|
37
47
|
return Path.cwd().expanduser().resolve()
|
|
38
48
|
|
|
39
49
|
|
|
40
|
-
def
|
|
41
|
-
|
|
42
|
-
# zh_tw(台湾)和 zh_hk(香港)不走清华镜像源
|
|
43
|
-
_CN_PREFIXES = ("zh_cn", "zh_sg", "zh_mo", "zh_hans")
|
|
44
|
-
for env_var in ("LC_ALL", "LC_MESSAGES", "LANG", "LANGUAGE"):
|
|
45
|
-
val = os.environ.get(env_var, "").lower()
|
|
46
|
-
if any(val.startswith(p) for p in _CN_PREFIXES):
|
|
47
|
-
return True
|
|
48
|
-
try:
|
|
49
|
-
lang, _ = locale.getlocale()
|
|
50
|
-
if lang:
|
|
51
|
-
lang_lower = lang.lower()
|
|
52
|
-
if any(lang_lower.startswith(p) for p in _CN_PREFIXES):
|
|
53
|
-
return True
|
|
54
|
-
except Exception:
|
|
55
|
-
pass
|
|
56
|
-
return False
|
|
50
|
+
async def _check_update() -> UpdateInfo | None:
|
|
51
|
+
return await check_update(log=logger)
|
|
57
52
|
|
|
58
53
|
|
|
59
|
-
async def
|
|
60
|
-
"""
|
|
54
|
+
async def _handle_update_on_launch(info: UpdateInfo) -> bool:
|
|
55
|
+
"""Handle interactive startup update UX.
|
|
61
56
|
|
|
62
|
-
|
|
57
|
+
Returns True when launch should stop after a successful update.
|
|
63
58
|
"""
|
|
64
|
-
package = "comate-cli"
|
|
65
59
|
try:
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
async with httpx.AsyncClient(timeout=3.0) as client:
|
|
80
|
-
resp = await client.get(url)
|
|
81
|
-
resp.raise_for_status()
|
|
82
|
-
latest = resp.json()["info"]["version"]
|
|
60
|
+
decision = decide_update_prompt(info)
|
|
61
|
+
if decision == UpdatePromptDecision.SKIP:
|
|
62
|
+
return False
|
|
63
|
+
if decision == UpdatePromptDecision.SHOW_HINT:
|
|
64
|
+
console.print(format_update_hint(info))
|
|
65
|
+
mark_update_seen(info)
|
|
66
|
+
return False
|
|
67
|
+
|
|
68
|
+
choice = await show_update_prompt(info)
|
|
69
|
+
if choice == UpdatePromptChoice.UPDATE_NOW:
|
|
70
|
+
return await run_update_command(console, info)
|
|
71
|
+
if choice == UpdatePromptChoice.SKIP_UNTIL_NEXT_VERSION:
|
|
72
|
+
record_skip_until_next_version(info)
|
|
83
73
|
except Exception:
|
|
84
|
-
logger.debug(
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
try:
|
|
88
|
-
from packaging.version import Version
|
|
89
|
-
|
|
90
|
-
if Version(latest) > Version(current):
|
|
91
|
-
return (
|
|
92
|
-
f"[dim] New version available: [bold cyan]{latest}[/] "
|
|
93
|
-
f"(current: {current}) "
|
|
94
|
-
f"Run [bold green]uv tool upgrade {package}[/] to upgrade.[/]"
|
|
95
|
-
)
|
|
96
|
-
except Exception:
|
|
97
|
-
logger.debug(
|
|
98
|
-
"update comparison failed (current=%s, latest=%s)",
|
|
99
|
-
current,
|
|
100
|
-
latest,
|
|
101
|
-
exc_info=True,
|
|
102
|
-
)
|
|
103
|
-
return None
|
|
74
|
+
logger.debug("startup update prompt failed", exc_info=True)
|
|
75
|
+
return False
|
|
104
76
|
|
|
105
77
|
|
|
106
78
|
def _flush_langfuse_if_configured() -> None:
|
|
@@ -366,6 +338,14 @@ async def run(
|
|
|
366
338
|
|
|
367
339
|
print_logo(console, project_root=project_root)
|
|
368
340
|
|
|
341
|
+
# 版本检查:带超时,不阻塞启动;仅交互启动路径触发升级 UX。
|
|
342
|
+
try:
|
|
343
|
+
update_info = await asyncio.wait_for(_check_update(), timeout=2.0)
|
|
344
|
+
if update_info is not None and await _handle_update_on_launch(update_info):
|
|
345
|
+
return
|
|
346
|
+
except (asyncio.TimeoutError, Exception):
|
|
347
|
+
pass
|
|
348
|
+
|
|
369
349
|
if resume_select and not resume_session_id:
|
|
370
350
|
selected_session_id = await select_resume_session_id(console, cwd=project_root)
|
|
371
351
|
if not selected_session_id:
|
|
@@ -384,14 +364,6 @@ async def run(
|
|
|
384
364
|
# 这些日志没有交互 anchor,需在恢复历史或首次用户输入前落为 standalone log。
|
|
385
365
|
renderer.flush_pending_logs()
|
|
386
366
|
|
|
387
|
-
# 版本检查:带超时,不阻塞启动
|
|
388
|
-
try:
|
|
389
|
-
update_hint = await asyncio.wait_for(_check_update(), timeout=2.0)
|
|
390
|
-
if update_hint:
|
|
391
|
-
console.print(update_hint)
|
|
392
|
-
except (asyncio.TimeoutError, Exception):
|
|
393
|
-
pass
|
|
394
|
-
|
|
395
367
|
status_bar = StatusBar(session)
|
|
396
368
|
status_bar.set_mode(session.get_mode())
|
|
397
369
|
try:
|
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import asyncio
|
|
4
|
+
import importlib.metadata
|
|
5
|
+
import locale
|
|
6
|
+
import logging
|
|
7
|
+
import os
|
|
8
|
+
from dataclasses import dataclass
|
|
9
|
+
from enum import Enum
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
from typing import Any
|
|
12
|
+
|
|
13
|
+
from rich.console import Console
|
|
14
|
+
|
|
15
|
+
from comate_agent_sdk.agent.settings import (
|
|
16
|
+
USER_SETTINGS_PATH,
|
|
17
|
+
read_settings_json_object,
|
|
18
|
+
write_settings_json_atomic,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
logger = logging.getLogger(__name__)
|
|
22
|
+
|
|
23
|
+
PACKAGE_NAME = "comate-cli"
|
|
24
|
+
RELEASE_NOTES_URL = "https://github.com/AndyLee1024/agent-sdk/releases/latest"
|
|
25
|
+
UPDATE_COMMAND = ("uv", "tool", "update", PACKAGE_NAME)
|
|
26
|
+
_SETTINGS_SECTION = "updates"
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class UpdatePromptDecision(Enum):
|
|
30
|
+
SKIP = "skip"
|
|
31
|
+
SHOW_HINT = "show_hint"
|
|
32
|
+
SHOW_PROMPT = "show_prompt"
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class UpdatePromptChoice(Enum):
|
|
36
|
+
UPDATE_NOW = "update_now"
|
|
37
|
+
SKIP = "skip"
|
|
38
|
+
SKIP_UNTIL_NEXT_VERSION = "skip_until_next_version"
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
@dataclass(frozen=True, slots=True)
|
|
42
|
+
class UpdateInfo:
|
|
43
|
+
package: str
|
|
44
|
+
current_version: str
|
|
45
|
+
latest_version: str
|
|
46
|
+
release_notes_url: str
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def _is_chinese_locale() -> bool:
|
|
50
|
+
"""判断当前系统 locale 是否为中文环境。"""
|
|
51
|
+
# zh_tw(台湾)和 zh_hk(香港)不走清华镜像源
|
|
52
|
+
cn_prefixes = ("zh_cn", "zh_sg", "zh_mo", "zh_hans")
|
|
53
|
+
for env_var in ("LC_ALL", "LC_MESSAGES", "LANG", "LANGUAGE"):
|
|
54
|
+
val = os.environ.get(env_var, "").lower()
|
|
55
|
+
if any(val.startswith(prefix) for prefix in cn_prefixes):
|
|
56
|
+
return True
|
|
57
|
+
try:
|
|
58
|
+
lang, _ = locale.getlocale()
|
|
59
|
+
if lang:
|
|
60
|
+
lang_lower = lang.lower()
|
|
61
|
+
if any(lang_lower.startswith(prefix) for prefix in cn_prefixes):
|
|
62
|
+
return True
|
|
63
|
+
except Exception:
|
|
64
|
+
pass
|
|
65
|
+
return False
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
async def check_update(
|
|
69
|
+
*,
|
|
70
|
+
package: str = PACKAGE_NAME,
|
|
71
|
+
release_notes_url: str = RELEASE_NOTES_URL,
|
|
72
|
+
log: logging.Logger | None = None,
|
|
73
|
+
) -> UpdateInfo | None:
|
|
74
|
+
"""异步检查 comate-cli 是否有新版本,返回结构化版本信息或 None。"""
|
|
75
|
+
active_logger = log or logger
|
|
76
|
+
try:
|
|
77
|
+
current = importlib.metadata.version(package)
|
|
78
|
+
except importlib.metadata.PackageNotFoundError:
|
|
79
|
+
return None
|
|
80
|
+
|
|
81
|
+
if _is_chinese_locale():
|
|
82
|
+
url = f"https://mirrors.tuna.tsinghua.edu.cn/pypi/{package}/json"
|
|
83
|
+
source_label = "tuna"
|
|
84
|
+
else:
|
|
85
|
+
url = f"https://pypi.org/pypi/{package}/json"
|
|
86
|
+
source_label = "pypi"
|
|
87
|
+
|
|
88
|
+
try:
|
|
89
|
+
import httpx
|
|
90
|
+
|
|
91
|
+
async with httpx.AsyncClient(timeout=3.0) as client:
|
|
92
|
+
resp = await client.get(url)
|
|
93
|
+
resp.raise_for_status()
|
|
94
|
+
latest = resp.json()["info"]["version"]
|
|
95
|
+
except Exception:
|
|
96
|
+
active_logger.debug(f"update check failed (source={source_label})", exc_info=True)
|
|
97
|
+
return None
|
|
98
|
+
|
|
99
|
+
try:
|
|
100
|
+
from packaging.version import Version
|
|
101
|
+
|
|
102
|
+
if Version(latest) > Version(current):
|
|
103
|
+
return UpdateInfo(
|
|
104
|
+
package=package,
|
|
105
|
+
current_version=current,
|
|
106
|
+
latest_version=latest,
|
|
107
|
+
release_notes_url=release_notes_url,
|
|
108
|
+
)
|
|
109
|
+
except Exception:
|
|
110
|
+
active_logger.debug(
|
|
111
|
+
"update comparison failed (current=%s, latest=%s)",
|
|
112
|
+
current,
|
|
113
|
+
latest,
|
|
114
|
+
exc_info=True,
|
|
115
|
+
)
|
|
116
|
+
return None
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def format_update_hint(info: UpdateInfo) -> str:
|
|
120
|
+
return (
|
|
121
|
+
f"[dim] New version available: [bold cyan]{info.latest_version}[/] "
|
|
122
|
+
f"(current: {info.current_version}) "
|
|
123
|
+
f"Run [bold green]uv tool update {info.package}[/] to update.[/]"
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def decide_update_prompt(
|
|
128
|
+
info: UpdateInfo,
|
|
129
|
+
*,
|
|
130
|
+
settings_path: Path | None = None,
|
|
131
|
+
) -> UpdatePromptDecision:
|
|
132
|
+
state = _load_package_update_state(info.package, settings_path=settings_path)
|
|
133
|
+
if state.get("skip_until_version") == info.latest_version:
|
|
134
|
+
return UpdatePromptDecision.SKIP
|
|
135
|
+
if state.get("last_seen_version") == info.latest_version:
|
|
136
|
+
return UpdatePromptDecision.SHOW_PROMPT
|
|
137
|
+
return UpdatePromptDecision.SHOW_HINT
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def mark_update_seen(info: UpdateInfo, *, settings_path: Path | None = None) -> None:
|
|
141
|
+
_write_package_update_state(
|
|
142
|
+
info.package,
|
|
143
|
+
{"last_seen_version": info.latest_version},
|
|
144
|
+
settings_path=settings_path,
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def record_skip_until_next_version(
|
|
149
|
+
info: UpdateInfo,
|
|
150
|
+
*,
|
|
151
|
+
settings_path: Path | None = None,
|
|
152
|
+
) -> None:
|
|
153
|
+
_write_package_update_state(
|
|
154
|
+
info.package,
|
|
155
|
+
{
|
|
156
|
+
"last_seen_version": info.latest_version,
|
|
157
|
+
"skip_until_version": info.latest_version,
|
|
158
|
+
},
|
|
159
|
+
settings_path=settings_path,
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
async def show_update_prompt(info: UpdateInfo) -> UpdatePromptChoice:
|
|
164
|
+
from prompt_toolkit.application import Application
|
|
165
|
+
from prompt_toolkit.key_binding import KeyBindings
|
|
166
|
+
from prompt_toolkit.layout import HSplit, Layout, Window
|
|
167
|
+
from prompt_toolkit.layout.controls import FormattedTextControl
|
|
168
|
+
from prompt_toolkit.patch_stdout import patch_stdout
|
|
169
|
+
from prompt_toolkit.styles import Style as PTStyle
|
|
170
|
+
|
|
171
|
+
choices = (
|
|
172
|
+
UpdatePromptChoice.UPDATE_NOW,
|
|
173
|
+
UpdatePromptChoice.SKIP,
|
|
174
|
+
UpdatePromptChoice.SKIP_UNTIL_NEXT_VERSION,
|
|
175
|
+
)
|
|
176
|
+
selected_index = 0
|
|
177
|
+
|
|
178
|
+
def render() -> list[tuple[str, str]]:
|
|
179
|
+
rows = [
|
|
180
|
+
("class:title", f"✨ Update available! {info.current_version} -> {info.latest_version}\n"),
|
|
181
|
+
("", "\n"),
|
|
182
|
+
# ("class:dim", f" Release notes: {info.release_notes_url}\n"),
|
|
183
|
+
# ("", "\n"),
|
|
184
|
+
]
|
|
185
|
+
labels = (
|
|
186
|
+
f"Update now (runs `{_format_update_command()}`)",
|
|
187
|
+
"Skip",
|
|
188
|
+
"Skip until next version",
|
|
189
|
+
)
|
|
190
|
+
for index, label in enumerate(labels):
|
|
191
|
+
marker = "›" if index == selected_index else " "
|
|
192
|
+
style = "class:selected" if index == selected_index else ""
|
|
193
|
+
rows.append((style, f"{marker} {index + 1}. {label}\n"))
|
|
194
|
+
rows.extend(
|
|
195
|
+
[
|
|
196
|
+
("", "\n"),
|
|
197
|
+
("class:dim", " Press enter to continue"),
|
|
198
|
+
]
|
|
199
|
+
)
|
|
200
|
+
return rows
|
|
201
|
+
|
|
202
|
+
kb = KeyBindings()
|
|
203
|
+
|
|
204
|
+
def exit_with(index: int, event: Any) -> None:
|
|
205
|
+
event.app.exit(result=choices[index])
|
|
206
|
+
|
|
207
|
+
@kb.add("up")
|
|
208
|
+
def _on_up(event: Any) -> None:
|
|
209
|
+
nonlocal selected_index
|
|
210
|
+
del event
|
|
211
|
+
selected_index = max(0, selected_index - 1)
|
|
212
|
+
|
|
213
|
+
@kb.add("down")
|
|
214
|
+
def _on_down(event: Any) -> None:
|
|
215
|
+
nonlocal selected_index
|
|
216
|
+
del event
|
|
217
|
+
selected_index = min(len(choices) - 1, selected_index + 1)
|
|
218
|
+
|
|
219
|
+
@kb.add("1")
|
|
220
|
+
def _on_one(event: Any) -> None:
|
|
221
|
+
exit_with(0, event)
|
|
222
|
+
|
|
223
|
+
@kb.add("2")
|
|
224
|
+
def _on_two(event: Any) -> None:
|
|
225
|
+
exit_with(1, event)
|
|
226
|
+
|
|
227
|
+
@kb.add("3")
|
|
228
|
+
def _on_three(event: Any) -> None:
|
|
229
|
+
exit_with(2, event)
|
|
230
|
+
|
|
231
|
+
@kb.add("enter")
|
|
232
|
+
def _on_enter(event: Any) -> None:
|
|
233
|
+
exit_with(selected_index, event)
|
|
234
|
+
|
|
235
|
+
@kb.add("escape")
|
|
236
|
+
@kb.add("c-c")
|
|
237
|
+
def _on_cancel(event: Any) -> None:
|
|
238
|
+
event.app.exit(result=UpdatePromptChoice.SKIP)
|
|
239
|
+
|
|
240
|
+
app: Application[UpdatePromptChoice] = Application(
|
|
241
|
+
layout=Layout(
|
|
242
|
+
HSplit(
|
|
243
|
+
[
|
|
244
|
+
Window(
|
|
245
|
+
content=FormattedTextControl(text=render, focusable=True),
|
|
246
|
+
wrap_lines=False,
|
|
247
|
+
)
|
|
248
|
+
]
|
|
249
|
+
)
|
|
250
|
+
),
|
|
251
|
+
key_bindings=kb,
|
|
252
|
+
style=PTStyle.from_dict(
|
|
253
|
+
{
|
|
254
|
+
"title": "bold",
|
|
255
|
+
"dim": "ansibrightblack",
|
|
256
|
+
"selected": "bold",
|
|
257
|
+
}
|
|
258
|
+
),
|
|
259
|
+
full_screen=True,
|
|
260
|
+
erase_when_done=True,
|
|
261
|
+
mouse_support=False,
|
|
262
|
+
)
|
|
263
|
+
with patch_stdout(raw=True):
|
|
264
|
+
return await app.run_async()
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
async def run_update_command(console: Console, info: UpdateInfo) -> bool:
|
|
268
|
+
command = ("uv", "tool", "update", info.package)
|
|
269
|
+
command_text = " ".join(command)
|
|
270
|
+
console.print(f"Updating Comate via `{command_text}`...")
|
|
271
|
+
try:
|
|
272
|
+
process = await asyncio.create_subprocess_exec(
|
|
273
|
+
*command,
|
|
274
|
+
stdout=asyncio.subprocess.PIPE,
|
|
275
|
+
stderr=asyncio.subprocess.STDOUT,
|
|
276
|
+
)
|
|
277
|
+
except OSError as exc:
|
|
278
|
+
logger.warning("failed to start update command: %s", exc, exc_info=True)
|
|
279
|
+
console.print(f"[red]Failed to start `{command_text}`: {exc}[/]")
|
|
280
|
+
return False
|
|
281
|
+
|
|
282
|
+
output, _ = await process.communicate()
|
|
283
|
+
if output:
|
|
284
|
+
console.out(output.decode(errors="replace"), end="")
|
|
285
|
+
|
|
286
|
+
if process.returncode == 0:
|
|
287
|
+
console.print("🎉 Update ran successfully! Please restart Comate.")
|
|
288
|
+
return True
|
|
289
|
+
|
|
290
|
+
console.print(f"[red]Update failed with exit code {process.returncode}. Continuing with current Comate.[/]")
|
|
291
|
+
return False
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
def _load_package_update_state(
|
|
295
|
+
package: str,
|
|
296
|
+
*,
|
|
297
|
+
settings_path: Path | None,
|
|
298
|
+
) -> dict[str, Any]:
|
|
299
|
+
data = read_settings_json_object(settings_path or USER_SETTINGS_PATH)
|
|
300
|
+
updates = data.get(_SETTINGS_SECTION)
|
|
301
|
+
if not isinstance(updates, dict):
|
|
302
|
+
return {}
|
|
303
|
+
state = updates.get(_package_state_key(package))
|
|
304
|
+
if not isinstance(state, dict):
|
|
305
|
+
return {}
|
|
306
|
+
return dict(state)
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
def _write_package_update_state(
|
|
310
|
+
package: str,
|
|
311
|
+
values: dict[str, str],
|
|
312
|
+
*,
|
|
313
|
+
settings_path: Path | None,
|
|
314
|
+
) -> None:
|
|
315
|
+
path = settings_path or USER_SETTINGS_PATH
|
|
316
|
+
data = read_settings_json_object(path)
|
|
317
|
+
updates = data.get(_SETTINGS_SECTION)
|
|
318
|
+
if not isinstance(updates, dict):
|
|
319
|
+
updates = {}
|
|
320
|
+
state = updates.get(_package_state_key(package))
|
|
321
|
+
if not isinstance(state, dict):
|
|
322
|
+
state = {}
|
|
323
|
+
state.update(values)
|
|
324
|
+
updates[_package_state_key(package)] = state
|
|
325
|
+
data[_SETTINGS_SECTION] = updates
|
|
326
|
+
write_settings_json_atomic(path=path, data=data)
|
|
327
|
+
|
|
328
|
+
|
|
329
|
+
def _package_state_key(package: str) -> str:
|
|
330
|
+
return package.replace("-", "_")
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
def _format_update_command() -> str:
|
|
334
|
+
return " ".join(UPDATE_COMMAND)
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "comate-cli"
|
|
7
|
-
version = "0.7.
|
|
7
|
+
version = "0.7.2"
|
|
8
8
|
description = "Comate terminal CLI built on comate-agent-sdk"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.11"
|
|
@@ -42,6 +42,12 @@ comate = "comate_cli.main:main"
|
|
|
42
42
|
|
|
43
43
|
[tool.hatch.build.targets.wheel]
|
|
44
44
|
packages = ["comate_cli"]
|
|
45
|
+
# hatchling>=1.30 默认输出 core metadata 2.5 (PEP 794),但 PyPI warehouse
|
|
46
|
+
# 暂未接受 metadata 2.5,上传会被拒。先固定到 2.4,等 warehouse 支持后再切回。
|
|
47
|
+
core-metadata-version = "2.4"
|
|
48
|
+
|
|
49
|
+
[tool.hatch.build.targets.sdist]
|
|
50
|
+
core-metadata-version = "2.4"
|
|
45
51
|
|
|
46
52
|
[tool.pytest.ini_options]
|
|
47
53
|
asyncio_mode = "auto"
|