comate-cli 0.12.7__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.
- {comate_cli-0.12.7 → comate_cli-0.12.8}/CHANGELOG.md +1 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/CONTEXT.md +4 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/PKG-INFO +1 -1
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/main.py +18 -13
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/side_install.py +2 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/update_check.py +146 -1
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/update_messages.py +11 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/update_cli.py +89 -3
- {comate_cli-0.12.7 → comate_cli-0.12.8}/pyproject.toml +1 -1
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_side_install.py +14 -0
- comate_cli-0.12.8/tests/test_update_mirror.py +338 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/uv.lock +1 -1
- {comate_cli-0.12.7 → comate_cli-0.12.8}/.agent/scheduled_prompts.json +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/.gitignore +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/.python-version +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/README.md +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/bash_settle_diag.log +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/__init__.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/__main__.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/device_identity.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/distribution.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/mcp_cli.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/__init__.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/animations.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/app.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/approval_bridge.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/approval_content_preview.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/assistant_render.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/backend/__init__.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/backend/announcements.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/backend/client.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/backend/feedback.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/backend/provider_snapshot.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/backend/rating.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/backend/runtime.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/backend/session_report.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/backend/session_title.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/backend/tasks.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/bash_command_display.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/browser_open.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/builtin_commands/.keep +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/builtin_commands/commit.md +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/builtin_commands/implement-plan.md +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/builtin_commands/learn.md +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/builtin_commands/open-pr.md +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/clipboard_image.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/clipboard_text.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/codenames.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/config/__init__.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/config/edit_session.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/config/model.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/config/picker.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/config/picker_state.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/config/store.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/config_check.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/console_profile.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/context_view.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/custom_slash_commands.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/effort_menu.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/effort_ruler.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/effort_style.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/env_utils.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/error_display.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/event_renderer.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/exit_confirm_view.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/exit_watchdog.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/figures.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/file_ref_hint.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/focus_events.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/fragment_utils.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/goal_edit_view.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/goal_resume_view.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/history_printer.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/i18n/__init__.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/i18n/_en.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/i18n/_ja.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/i18n/_zh.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/i18n/message.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/image_chips.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/input_geometry.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/job_activity.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/job_indicator.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/jobs_menu.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/jobs_state.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/layout_coordinator.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/locale.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/logging_adapter.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/logging_file_handler.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/logo.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/loop_freeze_watchdog.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/markdown_render.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/mcp_serve.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/mention_completer.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/menu_panel.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/message_style.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/model_tier_style.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/models.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/output_style_menu.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/plugins/__init__.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/plugins/auto_update_runner.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/plugins/auto_update_store.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/plugins/components/__init__.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/plugins/components/detail_view.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/plugins/components/plugin_list.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/plugins/components/search_box.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/plugins/components/tab_bar.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/plugins/marketplace_install_view.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/plugins/operation_state.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/plugins/plugin_picker.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/plugins/tabs/__init__.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/plugins/tabs/discover_tab.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/plugins/tabs/errors_tab.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/plugins/tabs/installed_tab.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/plugins/tabs/marketplaces_tab.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/preflight.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/preflight_wizard.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/preflight_wizard_ui.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/print_mode.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/question_broker.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/question_view.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/recap/__init__.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/recap/controller.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/resume_picker.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/resume_preview.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/resume_selector.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/rpc_commands.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/rpc_relay.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/rpc_stdio.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/rpc_ws.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/scm_request_status.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/selection_menu.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/sigint_guard.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/skill_slash_input.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/skills_menu.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/slash_commands.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/startup.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/startup_profile.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/status_bar.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/statusline/__init__.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/statusline/model.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/statusline/picker.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/statusline/picker_state.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/statusline/store.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/stream_pacer.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/suggestion/__init__.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/suggestion/controller.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/synchronized_output.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/text_effects.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/theme.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/tip_highlight.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/tips.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/tool_approval_view.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/tool_fold.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/tool_fold_view.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/tool_result_formatters.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/tool_result_state.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/tool_result_store.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/tool_result_viewer.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/tool_view.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/transcript_viewer.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/tui.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/tui_parts/__init__.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/tui_parts/approval_queue.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/tui_parts/btw_view.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/tui_parts/commands.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/tui_parts/history_sync.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/tui_parts/input_behavior.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/tui_parts/key_bindings.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/tui_parts/mcp_auth_view.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/tui_parts/mcp_connecting_view.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/tui_parts/render_panels.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/tui_parts/resize_guard.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/tui_parts/run_clock.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/tui_parts/shell_mode.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/tui_parts/slash_command_registry.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/tui_parts/ui_mode.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/ultracode_keyword.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/workflows_menu.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_agent/workflows_panel_model.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/comate_cli/terminal_title.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/docs/cli-rpc-stdio-guide.md +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/docs/release-notes/0.12.3.md +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/docs/startup-performance.md +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/docs/superpowers/plans/2026-07-07-tui-first-repaint-before-sdk-submit.md +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/docs/superpowers/plans/2026-07-07-windows-update-manual-rollback.md +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/_fake_anthropic_server.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/_rpc_ws_client.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/config/__init__.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/config/test_config_exit.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/config/test_edit_session.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/config/test_model.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/config/test_picker_state.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/config/test_picker_ui.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/config/test_roundtrip.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/config/test_runtime_settings.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/config/test_skills_denylist_migration.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/config/test_store_load.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/config/test_store_save.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/conftest.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/fixtures/exit_watchdog_child.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/fixtures/fake_mcp_misbehaving_stdout.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/fixtures/mcp_stub_stdio_server.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/recap/test_idle_recap_controller.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/recap/test_recap_history_rendering.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/recap/test_tui_idle_recap_integration.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/statusline/__init__.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/statusline/test_model.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/statusline/test_picker_state.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/statusline/test_store.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/suggestion/test_next_step_suggestion_controller.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/suggestion/test_next_step_suggestion_render.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/suggestion/test_tab_accepts_next_step_suggestion.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/suggestion/test_tui_next_step_suggestion_integration.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_animations_styles.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_animator_shuffle.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_app_config_check_gate.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_app_disallowed_tools.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_app_exit_lifecycle.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_app_mcp_needs_auth_hint.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_app_mcp_preload.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_app_mcp_preload_kick.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_app_preflight_gate.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_app_print_mode.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_app_profile_threading.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_app_pty_ctrl_b.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_app_pty_ctrl_c_exit.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_app_pty_live_tail.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_app_pty_shell_mode.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_app_pty_smoke.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_app_shutdown.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_app_startup_latency.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_app_startup_order.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_app_token_cost_config.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_app_usage_line.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_approval_bridge.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_approval_content_preview.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_backend_announcements.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_backend_client.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_backend_feedback.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_backend_provider_snapshot.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_backend_rating.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_backend_session_report.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_backend_tasks.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_btw_slash_command.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_builtin_marketplaces.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_busy_slash_gating.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_cli_project_root.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_clipboard_chip_restore.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_clipboard_image_reader.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_clipboard_text.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_commands_system_messages.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_compact_command_semantics.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_completion_context_activation.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_completion_status_panel.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_config_check.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_console_profile.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_context_command.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_context_view.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_context_view_tool_search.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_ctrl_b_background.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_ctrl_c_clear_input.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_custom_slash_commands.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_device_identity.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_discover_tab.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_distribution_contract.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_drain_frame_atomicity.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_effort_menu.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_effort_menu_frame_rate.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_effort_ruler.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_effort_slash_command.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_effort_style.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_errors_tab.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_event_renderer.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_event_renderer_approval_wait.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_event_renderer_bash_background.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_event_renderer_boundary.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_event_renderer_budget_floor.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_event_renderer_e2e.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_event_renderer_fixed_overhead.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_event_renderer_idle_prune.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_event_renderer_jobs.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_event_renderer_log_boundary.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_event_renderer_log_queue.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_event_renderer_mcp_background.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_event_renderer_oversized_tools.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_event_renderer_provider_overflow.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_event_renderer_shell.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_event_renderer_stream_pacing.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_event_renderer_stream_staging.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_event_renderer_streaming.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_event_renderer_tool_args_progress.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_event_renderer_tool_fold.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_event_renderer_tool_search_notice.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_exit_confirm_view.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_exit_guard.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_exit_watchdog.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_exit_watchdog_subprocess.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_file_ref_hint.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_focus_events.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_format_error.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_goal_edit_handlers.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_goal_edit_view.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_goal_paused_hint.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_goal_resume_tui.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_goal_resume_view.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_goal_slash_command.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_handle_error.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_history_drain_throttle.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_history_printer.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_history_printer_log.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_history_printer_styles.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_history_printer_subtitle_position.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_history_printer_tool_fold.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_history_sync.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_history_sync_tool_fold.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_i18n.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_image_chip_deletion.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_image_chips.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_image_preprocess_offload_lag.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_import_weight.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_input_behavior.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_input_history.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_input_separator_counter.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_installed_tab.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_interrupt_exit_semantics.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_job_activity.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_job_indicator.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_job_indicator_host.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_job_indicator_pty.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_jobs_menu.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_jobs_menu_host.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_jobs_menu_pty.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_jobs_state.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_key_bindings_system_messages.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_layout_coordinator.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_live_output_tail.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_loading_line_fragments.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_loading_modal_suppression.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_loading_tip_picker.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_logging_adapter.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_logging_file_handler.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_logo.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_loop_freeze_watchdog.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_main_args.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_main_args_yolo.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_main_profile_entry.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_markdown_render.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_marketplace_add_commands.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_marketplace_install_view.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_marketplaces_tab.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_mcp_auth_panel_pty.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_mcp_cli.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_mcp_cli_auth.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_mcp_cli_scope_defaults.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_mcp_cli_stdout_encoding.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_mcp_jobs_pty.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_mcp_panel_auth.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_mcp_serve.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_mcp_slash_command.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_mention_completer.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_menu_cursor_unification.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_menu_panel.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_menu_panel_pty.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_message_style.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_modal_freeze_timing.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_modal_panel_visibility.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_model_switch_command.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_model_tier_style.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_no_raw_colors.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_output_style_slash_command.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_permission_mode_cycle.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_plugin_auto_update_runner.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_plugin_auto_update_store.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_plugin_auto_update_tui.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_plugin_mcp_keeps_disk_servers.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_plugin_operation_state.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_plugin_slash_commands.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_plugin_tui_components.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_preflight.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_preflight_copilot.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_preflight_wizard_ui.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_print_mode_monitor_cap.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_print_mode_stdout_encoding.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_pty_output_integrity.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_question_broker.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_question_key_bindings.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_question_view.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_resize_guard.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_resume_picker.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_resume_preview.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_resume_selector.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_rewind_command_semantics.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_rpc_mode_logging.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_rpc_relay_dial_out.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_rpc_relay_e2e_smoke.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_rpc_relay_process_smoke.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_rpc_v4_stdio_smoke.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_rpc_v4_ws_smoke.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_rpc_ws_bind_failure.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_run_clock.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_running_tool_live_tail.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_running_tool_status_line.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_scm_request_status.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_scrollback_write_encoding.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_selection_menu.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_session_auto_title.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_session_query_token_summary.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_settings_write_guard.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_shell_mode.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_shutdown_noise_guard.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_shutdown_noise_integration.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_sigint_guard.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_sigint_key_binding.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_skill_slash_input.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_skills_slash_command.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_slash_add_dir.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_slash_argument_hint.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_slash_clear.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_slash_completer.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_slash_registry.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_startup_import_budget.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_startup_profile.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_status_bar.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_status_bar_mid_turn_refresh.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_status_bar_request_status.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_status_bar_transient.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_stream_pacer.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_stream_pacing_tick.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_stream_staging_panel.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_style_class_coverage.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_synchronized_output.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_tab_title.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_task_panel_format.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_task_panel_key_bindings.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_task_panel_rendering.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_task_poll.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_terminal_title.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_theme.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_tip_highlight.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_tips.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_todo_panel_busy_gating.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_tool_approval_key_bindings.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_tool_approval_tui.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_tool_approval_view.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_tool_approval_view_workflow.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_tool_call_protection.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_tool_fold.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_tool_fold_panel.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_tool_fold_view.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_tool_result_formatters.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_tool_result_state.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_tool_result_store.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_tool_result_viewer.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_tool_result_viewer_key_bindings.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_tool_view.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_tool_view_styles.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_transcript_viewer.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_transcript_viewer_record_matching.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_transcript_viewer_tool_fold.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_tui_builtin_slash_chain.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_tui_deferred_prewarm.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_tui_elapsed_status.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_tui_esc_queue.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_tui_exit_idempotence.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_tui_exit_paced_tail.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_tui_exit_pending_logs.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_tui_hot_reload.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_tui_image_chip_retention.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_tui_image_chip_seed.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_tui_image_paste.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_tui_image_path_upgrade.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_tui_image_restore.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_tui_image_submit.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_tui_interrupt_queue_recall.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_tui_llm_retry_panel.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_tui_loading_tip_rotation.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_tui_local_interactive_barrier.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_tui_mcp_init_gate.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_tui_paste_history_persistence.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_tui_paste_newline_guard.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_tui_paste_placeholder.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_tui_plugin_load.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_tui_provider_error_shield.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_tui_queue_pop_images.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_tui_queue_preview.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_tui_queue_sdk_source.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_tui_replace_session_resume_hint.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_tui_scheduled_fire_log.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_tui_scratchpad_fold_wiring.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_tui_send_undo_window.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_tui_session_observers.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_tui_shutdown_cancel_propagation.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_tui_split_invariance.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_tui_startup_latency.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_tui_surrogate_repair.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_tui_thinking_display.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_tui_tool_result_registry_lifecycle.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_tui_window_too_small_fallback.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_ui_mode_derivation.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_ui_tick_exception_isolation.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_ultracode_keyword.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_ultracode_keyword_frame_rate.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_ultracode_keyword_submit.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_ultracode_shimmer_render.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_update_check.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_update_cli.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_upstream_surrogate_merge_characterization.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_usage_command.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_wellformed_terminal_input.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_whitelabel_clear_logo.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_windows_sigint_console.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_workflows_menu.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_workflows_menu_host.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_workflows_menu_pty.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_workflows_panel_model.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_wrap_user_text.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tests/test_zipapp_launcher_path.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tools/diagnose_windows_shim_rename.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tools/logo_lab.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tools/nico_preview.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tools/probe_conhost_char_width.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tools/probe_conhost_render_replay.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tools/startup_bench.py +0 -0
- {comate_cli-0.12.7 → comate_cli-0.12.8}/tools/transcript_viewer_bench.py +0 -0
- {comate_cli-0.12.7 → 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)。文案四种语言齐全。
|
|
@@ -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
|
|
@@ -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
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
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(
|
|
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 预发布规则的另一半)。
|
|
@@ -341,9 +356,15 @@ def windows_update_command(
|
|
|
341
356
|
target.package,
|
|
342
357
|
*python_request_args(target.install_args),
|
|
343
358
|
*index_strategy_fallback_args(target.install_args),
|
|
359
|
+
*default_index_args(target.index_url),
|
|
344
360
|
*target.install_args,
|
|
345
361
|
]
|
|
346
|
-
|
|
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
|
+
):
|
|
347
368
|
command += ["--default-index", TUNA_PYPI_INDEX]
|
|
348
369
|
return tuple(command)
|
|
349
370
|
|
|
@@ -468,6 +489,125 @@ def pypi_json_source(
|
|
|
468
489
|
return fetch
|
|
469
490
|
|
|
470
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
|
+
|
|
471
611
|
def _select_latest_version(
|
|
472
612
|
payload: dict[str, Any],
|
|
473
613
|
*,
|
|
@@ -601,6 +741,10 @@ async def fetch_latest_release(
|
|
|
601
741
|
启动期 best-effort 语义。include_prereleases 只对 PyPI 源有意义:白牌
|
|
602
742
|
profile 源只回一个版本号,没有预发布的概念。
|
|
603
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
|
+
)()
|
|
604
748
|
profile_fetch_latest = target.fetch_latest
|
|
605
749
|
if profile_fetch_latest is not None:
|
|
606
750
|
return await _fetch_profile_latest_with_timeout(profile_fetch_latest)
|
|
@@ -679,6 +823,7 @@ def _target_for_info(info: UpdateInfo, target: UpdateTarget | None = None) -> Up
|
|
|
679
823
|
install_args=target.install_args,
|
|
680
824
|
command_name=target.command_name,
|
|
681
825
|
python_install_mirror=target.python_install_mirror,
|
|
826
|
+
index_url=target.index_url,
|
|
682
827
|
)
|
|
683
828
|
return UpdateTarget(
|
|
684
829
|
package=info.package,
|
|
@@ -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(
|
|
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(
|
|
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:
|
|
@@ -273,6 +273,20 @@ class TestStageUpdate(unittest.IsolatedAsyncioTestCase):
|
|
|
273
273
|
self.assertIn("--python", install_cmd)
|
|
274
274
|
self.assertEqual(install_cmd[install_cmd.index("--python") + 1], "3.14")
|
|
275
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])
|
|
289
|
+
|
|
276
290
|
async def test_zh_cn_side_install_downloads_python_through_mirror(self) -> None:
|
|
277
291
|
"""旁装请求的 Python 机器上没有时 uv 从 GitHub 下载,国内可能失败(ADR 0055 取舍四);
|
|
278
292
|
用户自己设置的镜像必须保留。"""
|