From 8f6ae6d983538295359a6f329844ef791518dbeb Mon Sep 17 00:00:00 2001 From: Ed_ Date: Fri, 26 Jun 2026 05:55:22 -0400 Subject: [PATCH] misc --- src/events.py | 32 ++------- src/vendor_capabilities.py | 144 ++++++++++++++++++------------------- 2 files changed, 75 insertions(+), 101 deletions(-) diff --git a/src/events.py b/src/events.py index 814a6bc2..2f990a0a 100644 --- a/src/events.py +++ b/src/events.py @@ -38,11 +38,7 @@ from src.api_hooks import WebSocketMessage class EventEmitter: - """ - - - Simple event emitter for decoupled communication between modules. - """ + """Simple event emitter for decoupled communication between modules.""" def __init__(self) -> None: """ @@ -57,7 +53,6 @@ class EventEmitter: Args: event_name: The name of the event to listen for. callback: The function to call when the event is emitted. - [C: tests/test_api_events.py:test_event_emission, tests/test_api_events.py:test_send_emits_events_proper, tests/test_api_events.py:test_send_emits_tool_events] """ if event_name not in self._listeners: self._listeners[event_name] = [] @@ -70,17 +65,13 @@ class EventEmitter: event_name: The name of the event to emit. *args: Positional arguments to pass to callbacks. **kwargs: Keyword arguments to pass to callbacks. - [C: tests/test_api_events.py:test_event_emission] """ if event_name in self._listeners: for callback in self._listeners[event_name]: callback(*args, **kwargs) def clear(self) -> None: - """ - Clears all registered listeners. - [C: src/gui_2.py:App._render_add_context_files_modal, src/gui_2.py:App._render_comms_history_panel, src/gui_2.py:App._render_context_batch_actions, src/gui_2.py:App._render_discussion_entry_controls, src/gui_2.py:App._render_main_interface, src/gui_2.py:App._render_ticket_queue, src/gui_2.py:App._render_tool_calls_panel, src/gui_2.py:App._show_menus, src/history.py:HistoryManager.push, src/markdown_helper.py:MarkdownRenderer._render_code_block, src/markdown_helper.py:MarkdownRenderer.clear_cache, src/multi_agent_conductor.py:ConductorEngine.resume, src/multi_agent_conductor.py:WorkerPool.join_all, src/paths.py:reset_resolved, src/summary_cache.py:SummaryCache.clear, tests/conftest.py:reset_ai_client] - """ + """Clears all registered listeners.""" self._listeners.clear() class AsyncEventQueue: @@ -92,7 +83,6 @@ class AsyncEventQueue: def __init__(self) -> None: """ Initializes the AsyncEventQueue with an internal queue.Queue. - [C: src/mcp_client.py:_DDGParser.__init__, src/mcp_client.py:_TextExtractor.__init__] """ self._queue: queue.Queue[Tuple[str, Any]] = queue.Queue() self.websocket_server: Optional[Any] = None @@ -103,7 +93,6 @@ class AsyncEventQueue: Args: event_name: The name of the event. payload: Optional data associated with the event. - [C: src/gui_2.py:App._render_external_tools_panel, src/gui_2.py:App._render_log_management, src/gui_2.py:App._render_rag_panel, src/gui_2.py:App._render_token_budget_panel, src/gui_2.py:App._show_menus, src/multi_agent_conductor.py:ConductorEngine._push_state, src/multi_agent_conductor.py:_queue_put, tests/test_gui_events_v2.py:test_sync_event_queue, tests/test_sync_events.py:test_sync_event_queue_multiple, tests/test_sync_events.py:test_sync_event_queue_none_payload, tests/test_sync_events.py:test_sync_event_queue_put_get] """ self._queue.put((event_name, payload)) if self.websocket_server: @@ -121,7 +110,6 @@ class AsyncEventQueue: Gets an event from the queue. Returns: A tuple containing (event_name, payload). - [C: simulation/live_walkthrough.py:main, simulation/ping_pong.py:main, simulation/sim_context.py:ContextSimulation.run, simulation/sim_execution.py:ExecutionSimulation.run, simulation/sim_tools.py:ToolsSimulation.run, simulation/user_agent.py:UserSimAgent.generate_response, simulation/workflow_sim.py:WorkflowSimulator.run_discussion_turn_async, simulation/workflow_sim.py:WorkflowSimulator.wait_for_ai_response, src/external_editor.py:ExternalEditorLauncher.get_editor, src/external_editor.py:get_default_launcher, src/gemini_cli_adapter.py:GeminiCliAdapter.send, src/gui_2.py:App.__init__, src/gui_2.py:App._cb_block_ticket, src/gui_2.py:App._cb_unblock_ticket, src/gui_2.py:App._handle_history_logic, src/gui_2.py:App._populate_auto_slices, src/gui_2.py:App._render_ast_inspector_modal, src/gui_2.py:App._render_cache_panel, src/gui_2.py:App._render_comms_history_panel, src/gui_2.py:App._render_context_files_table, src/gui_2.py:App._render_context_presets, src/gui_2.py:App._render_context_presets_panel, src/gui_2.py:App._render_diagnostics_panel, src/gui_2.py:App._render_discussion_entries, src/gui_2.py:App._render_discussion_entry, src/gui_2.py:App._render_discussion_metadata, src/gui_2.py:App._render_discussion_selector, src/gui_2.py:App._render_external_editor_panel, src/gui_2.py:App._render_external_tools_panel, src/gui_2.py:App._render_history_window, src/gui_2.py:App._render_log_management, src/gui_2.py:App._render_main_interface, src/gui_2.py:App._render_mma_modals, src/gui_2.py:App._render_mma_ticket_editor, src/gui_2.py:App._render_mma_track_browser, src/gui_2.py:App._render_mma_track_summary, src/gui_2.py:App._render_mma_usage_section, src/gui_2.py:App._render_operations_hub, src/gui_2.py:App._render_path_field, src/gui_2.py:App._render_persona_editor_window, src/gui_2.py:App._render_persona_selector_panel, src/gui_2.py:App._render_prior_session_view, src/gui_2.py:App._render_projects_panel, src/gui_2.py:App._render_session_insights_panel, src/gui_2.py:App._render_shader_live_editor, src/gui_2.py:App._render_snapshot_tab, src/gui_2.py:App._render_synthesis_panel, src/gui_2.py:App._render_takes_panel, src/gui_2.py:App._render_task_dag_panel, src/gui_2.py:App._render_text_viewer_window, src/gui_2.py:App._render_theme_panel, src/gui_2.py:App._render_thinking_trace, src/gui_2.py:App._render_ticket_queue, src/gui_2.py:App._render_tier_stream_panel, src/gui_2.py:App._render_token_budget_panel, src/gui_2.py:App._render_tool_analytics_panel, src/gui_2.py:App._render_tool_calls_panel, src/gui_2.py:App._render_tool_preset_manager_content, src/gui_2.py:App._render_track_proposal_modal, src/gui_2.py:App._render_window_if_open, src/gui_2.py:App._reorder_ticket, src/gui_2.py:App._update_context_file_stats, src/gui_2.py:App.bulk_block, src/gui_2.py:App.bulk_execute, src/gui_2.py:App.bulk_skip, src/gui_2.py:App.iterate_history, src/gui_2.py:App.load_context_preset, src/gui_2.py:App.run, src/gui_2.py:truncate_entries, src/history.py:UISnapshot.from_dict, src/log_registry.py:LogRegistry.get_old_non_whitelisted_sessions, src/log_registry.py:LogRegistry.is_session_whitelisted, src/log_registry.py:LogRegistry.update_auto_whitelist_status, src/log_registry.py:LogRegistry.update_session_metadata, src/markdown_helper.py:MarkdownRenderer._render_code_block, src/mcp_client.py:StdioMCPServer._send_request, src/mcp_client.py:StdioMCPServer.call_tool, src/mcp_client.py:_DDGParser.handle_starttag, src/mcp_client.py:configure, src/mcp_client.py:dispatch, src/mcp_client.py:get_tool_schemas, src/models.py:BiasProfile.from_dict, src/models.py:ContextPreset.from_dict, src/models.py:ExternalEditorConfig.from_dict, src/models.py:FileItem.from_dict, src/models.py:FileViewPreset.from_dict, src/models.py:MCPConfiguration.from_dict, src/models.py:MCPServerConfig.from_dict, src/models.py:Metadata.from_dict, src/models.py:NamedViewPreset.from_dict, src/models.py:Persona.from_dict, src/models.py:Persona.max_output_tokens, src/models.py:Persona.model, src/models.py:Persona.provider, src/models.py:Persona.temperature, src/models.py:Persona.top_p, src/models.py:Preset.from_dict, src/models.py:RAGConfig.from_dict, src/models.py:TextEditorConfig.from_dict, src/models.py:Ticket.from_dict, src/models.py:Tool.from_dict, src/models.py:ToolPreset.from_dict, src/models.py:Track.from_dict, src/models.py:TrackState.from_dict, src/models.py:VectorStoreConfig.from_dict, src/models.py:WorkspaceProfile.from_dict, src/models.py:save_config, src/multi_agent_conductor.py:ConductorEngine.__init__, src/multi_agent_conductor.py:ConductorEngine.kill_worker, src/multi_agent_conductor.py:ConductorEngine.parse_json_tickets, src/multi_agent_conductor.py:ConductorEngine.run, src/multi_agent_conductor.py:clutch_callback, src/multi_agent_conductor.py:confirm_spawn, src/multi_agent_conductor.py:run_worker_lifecycle, src/multi_agent_conductor.py:worker_comms_callback, src/orchestrator_pm.py:generate_tracks, src/orchestrator_pm.py:get_track_history_summary, src/orchestrator_pm.py:module, src/paths.py:_get_project_conductor_dir_from_toml, src/paths.py:get_config_path, src/paths.py:get_global_personas_path, src/paths.py:get_global_presets_path, src/paths.py:get_global_tool_presets_path, src/paths.py:get_global_workspace_profiles_path, src/performance_monitor.py:PerformanceMonitor._get_avg, src/performance_monitor.py:PerformanceMonitor.end_component, src/performance_monitor.py:PerformanceMonitor.get_metrics, src/personas.py:PersonaManager.get_persona_scope, src/personas.py:PersonaManager.load_all, src/presets.py:PresetManager.delete_preset, src/presets.py:PresetManager.get_preset_scope, src/presets.py:PresetManager.load_all, src/project_manager.py:branch_discussion, src/project_manager.py:entry_to_str, src/project_manager.py:flat_config, src/project_manager.py:get_all_tracks, src/project_manager.py:load_track_history, src/project_manager.py:migrate_from_legacy_config, src/project_manager.py:promote_take, src/rag_engine.py:RAGEngine.get_all_indexed_paths, src/rag_engine.py:RAGEngine.index_file, src/shell_runner.py:_build_subprocess_env, src/shell_runner.py:_load_env_config, src/summarize.py:build_summary_markdown, src/summarize.py:summarise_file, src/summarize.py:summarise_items, src/summary_cache.py:SummaryCache.get_summary, src/synthesis_formatter.py:format_takes_diff, src/theme_2.py:load_from_config, src/tool_bias.py:ToolBiasEngine.apply_semantic_nudges, src/tool_presets.py:ToolPresetManager.load_all_bias_profiles, src/tool_presets.py:ToolPresetManager.load_all_presets, src/workspace_manager.py:WorkspaceManager.load_all_profiles, tests/conftest.py:live_gui, tests/mock_gemini_cli.py:main, tests/test_ai_server.py:test_server_outputs_ready_marker, tests/test_ai_settings_layout.py:test_change_provider_via_hook, tests/test_ai_settings_layout.py:test_set_params_via_custom_callback, tests/test_async_tools.py:mocked_async_dispatch, tests/test_auto_switch_sim.py:test_auto_switch_sim, tests/test_cli_tool_bridge.py:TestCliToolBridge.test_allow_decision, tests/test_cli_tool_bridge.py:TestCliToolBridge.test_deny_decision, tests/test_cli_tool_bridge.py:TestCliToolBridge.test_unreachable_hook_server, tests/test_cli_tool_bridge_mapping.py:TestCliToolBridgeMapping.test_mapping_from_api_format, tests/test_conductor_api_hook_integration.py:simulate_conductor_phase_completion, tests/test_conductor_engine_v2.py:mock_open_side_effect, tests/test_conductor_engine_v2.py:mock_send_side_effect, tests/test_external_editor_gui.py:test_button_click_is_received, tests/test_external_editor_gui.py:test_patch_modal_shows_with_configured_editor, tests/test_external_editor_gui.py:test_vscode_launches_with_diff_view, tests/test_gemini_cli_adapter.py:TestGeminiCliAdapter.test_send_captures_usage_metadata, tests/test_gui2_performance.py:test_performance_benchmarking, tests/test_gui_context_presets.py:test_gui_context_preset_save_load, tests/test_gui_events_v2.py:test_sync_event_queue, tests/test_gui_performance_requirements.py:test_idle_performance_requirements, tests/test_gui_phase4.py:test_delete_ticket_logic, tests/test_gui_stress_performance.py:test_comms_volume_stress_performance, tests/test_gui_text_viewer.py:test_text_viewer_state_update, tests/test_gui_updates.py:test_gui_updates_on_event, tests/test_headless_service.py:TestHeadlessAPI.test_endpoint_no_api_key_configured, tests/test_headless_service.py:TestHeadlessAPI.test_get_context_endpoint, tests/test_headless_service.py:TestHeadlessAPI.test_health_endpoint, tests/test_headless_service.py:TestHeadlessAPI.test_list_sessions_endpoint, tests/test_headless_service.py:TestHeadlessAPI.test_pending_actions_endpoint, tests/test_headless_service.py:TestHeadlessAPI.test_status_endpoint_authorized, tests/test_headless_service.py:TestHeadlessAPI.test_status_endpoint_unauthorized, tests/test_live_gui_integration_v2.py:test_api_gui_state_live, tests/test_live_gui_integration_v2.py:test_user_request_error_handling, tests/test_live_gui_integration_v2.py:test_user_request_integration_flow, tests/test_live_workflow.py:test_full_live_workflow, tests/test_live_workflow.py:wait_for_value, tests/test_log_registry.py:TestLogRegistry.test_register_session, tests/test_log_registry.py:TestLogRegistry.test_update_session_metadata, tests/test_mma_agent_focus_phase3.py:test_comms_log_filter_not_applied_for_prior_session, tests/test_mma_agent_focus_phase3.py:test_comms_log_filter_tier3_only, tests/test_mma_agent_focus_phase3.py:test_tool_log_filter_all, tests/test_mma_agent_focus_phase3.py:test_tool_log_filter_excludes_none_tier, tests/test_mma_agent_focus_phase3.py:test_tool_log_filter_tier3_only, tests/test_mma_approval_indicators.py:_make_app, tests/test_mma_concurrent_tracks_sim.py:test_mma_concurrent_tracks_execution, tests/test_mma_concurrent_tracks_stress_sim.py:_poll_mma_workers, tests/test_mma_concurrent_tracks_stress_sim.py:test_mma_concurrent_tracks_stress, tests/test_mma_dashboard_streams.py:_make_app, tests/test_mma_orchestration_gui.py:test_handle_ai_response_with_stream_id, tests/test_mma_step_mode_sim.py:_poll_mma_status, tests/test_mma_step_mode_sim.py:test_mma_step_mode_approval_flow, tests/test_mock_gemini_cli.py:get_message_content, tests/test_patch_modal_gui.py:test_patch_apply_modal_workflow, tests/test_patch_modal_gui.py:test_patch_modal_appears_on_trigger, tests/test_per_ticket_model.py:test_model_override_serialization, tests/test_phase6_engine.py:test_worker_streaming_intermediate, tests/test_phase6_simulation.py:test_ast_inspector_modal_opens, tests/test_phase6_simulation.py:test_batch_operations_shift_click, tests/test_phase6_simulation.py:test_slice_editor_add_remove, tests/test_preset_windows_layout.py:test_api_hook_under_load, tests/test_preset_windows_layout.py:test_preset_windows_opening, tests/test_project_serialization.py:TestProjectSerialization.test_backward_compatibility_strings, tests/test_rag_phase4_final_verify.py:test_phase4_final_verify, tests/test_rag_phase4_stress.py:test_rag_large_codebase_verification_sim, tests/test_saved_presets_sim.py:test_preset_manager_modal, tests/test_saved_presets_sim.py:test_preset_switching, tests/test_selectable_ui.py:test_selectable_label_stability, tests/test_sim_ai_settings.py:side_effect, tests/test_sim_ai_settings.py:test_ai_settings_simulation_run, tests/test_sim_context.py:test_context_simulation_run, tests/test_sim_execution.py:side_effect, tests/test_spawn_interception_v2.py:test_confirm_spawn_pushed_to_queue, tests/test_status_encapsulation.py:test_status_properties, tests/test_sync_events.py:test_sync_event_queue_multiple, tests/test_sync_events.py:test_sync_event_queue_none_payload, tests/test_sync_events.py:test_sync_event_queue_put_get, tests/test_task_dag_popout_sim.py:test_task_dag_popout, tests/test_tier4_interceptor.py:test_ai_client_passes_qa_callback, tests/test_tiered_aggregation.py:test_app_controller_do_generate_uses_persona_strategy, tests/test_tiered_aggregation.py:test_persona_aggregation_strategy, tests/test_token_usage.py:test_token_usage_tracking, tests/test_tool_management_layout.py:test_tool_management_state_updates, tests/test_tool_preset_env.py:test_tool_preset_env_loading, tests/test_tool_preset_env.py:test_tool_preset_env_no_var, tests/test_tool_presets_sim.py:test_tool_preset_switching, tests/test_ui_cache_controls_sim.py:test_ui_cache_controls, tests/test_ui_summary_only_removal.py:test_project_without_summary_only_loads, tests/test_usage_analytics_popout_sim.py:test_usage_analytics_popout, tests/test_visual_mma.py:test_visual_mma_components, tests/test_visual_orchestration.py:test_mma_epic_lifecycle, tests/test_visual_sim_gui_ux.py:test_gui_ux_event_routing, tests/test_visual_sim_mma_v2.py:_drain_approvals, tests/test_visual_sim_mma_v2.py:_mma_active, tests/test_visual_sim_mma_v2.py:_poll, tests/test_visual_sim_mma_v2.py:_tier3_in_streams, tests/test_visual_sim_mma_v2.py:_tier3_usage_nonzero, tests/test_visual_sim_mma_v2.py:_track_loaded, tests/test_visual_sim_mma_v2.py:test_mma_complete_lifecycle] """ return self._queue.get() @@ -130,7 +118,6 @@ class AsyncEventQueue: Checks if the queue is empty. Returns: True if the queue is empty, False otherwise. - [C: tests/test_gui_updates.py:test_gui_updates_on_event, tests/test_live_gui_integration_v2.py:test_user_request_error_handling, tests/test_live_gui_integration_v2.py:test_user_request_integration_flow] """ return self._queue.empty() @@ -139,24 +126,16 @@ class AsyncEventQueue: self._queue.task_done() def join(self) -> None: - """ - Blocks until all items in the queue have been gotten and processed. - [C: simulation/live_walkthrough.py:main, simulation/ping_pong.py:module, simulation/sim_base.py:module, src/file_cache.py:ASTParser.get_code_outline, src/fuzzy_anchor.py:FuzzyAnchor.create_slice, src/fuzzy_anchor.py:FuzzyAnchor.resolve_slice, src/gemini_cli_adapter.py:GeminiCliAdapter.count_tokens, src/gemini_cli_adapter.py:GeminiCliAdapter.send, src/gui_2.py:App._render_ast_inspector_modal, src/gui_2.py:App._render_beads_tab, src/gui_2.py:App._render_discussion_entry, src/gui_2.py:App._render_mma_ticket_editor, src/log_pruner.py:LogPruner.prune, src/log_registry.py:LogRegistry.update_auto_whitelist_status, src/markdown_helper.py:MarkdownRenderer._render_code_block, src/mcp_client.py:StdioMCPServer.call_tool, src/mcp_client.py:_resolve_and_check, src/mcp_client.py:derive_code_path, src/mcp_client.py:dispatch, src/mcp_client.py:fetch_url, src/mcp_client.py:get_file_slice, src/mcp_client.py:get_tree, src/mcp_client.py:list_directory, src/mcp_client.py:py_find_usages, src/mcp_client.py:py_get_class_summary, src/mcp_client.py:py_get_definition, src/mcp_client.py:py_get_hierarchy, src/mcp_client.py:py_get_imports, src/mcp_client.py:py_get_signature, src/mcp_client.py:py_get_symbol_info, src/mcp_client.py:py_get_var_declaration, src/mcp_client.py:search_files, src/mcp_client.py:set_file_slice, src/mcp_client.py:web_search, src/models.py:parse_history_entries, src/multi_agent_conductor.py:ConductorEngine.kill_worker, src/multi_agent_conductor.py:WorkerPool.join_all, src/orchestrator_pm.py:generate_tracks, src/orchestrator_pm.py:get_track_history_summary, src/outline_tool.py:CodeOutliner.outline, src/performance_monitor.py:PerformanceMonitor.stop, src/project_manager.py:str_to_entry, src/rag_engine.py:RAGEngine._init_vector_store, src/rag_engine.py:RAGEngine.index_file, src/session_logger.py:open_session, src/shell_runner.py:_build_subprocess_env, src/shell_runner.py:run_powershell, src/summarize.py:_summarise_generic, src/summarize.py:_summarise_markdown, src/summarize.py:_summarise_python, src/summarize.py:_summarise_toml, src/summarize.py:build_summary_markdown, src/synthesis_formatter.py:format_takes_diff, src/tool_bias.py:ToolBiasEngine.generate_tooling_strategy, tests/conftest.py:live_gui, tests/conftest.py:module, tests/mock_gemini_cli.py:main, tests/smoke_status_hook.py:module, tests/test_agent_capabilities.py:module, tests/test_agent_tools_wiring.py:module, tests/test_ai_client_concurrency.py:test_ai_client_tier_isolation, tests/test_api_hook_client.py:module, tests/test_api_hook_extensions.py:module, tests/test_arch_boundary_phase1.py:module, tests/test_arch_boundary_phase2.py:module, tests/test_arch_boundary_phase3.py:module, tests/test_auto_switch_sim.py:module, tests/test_cli_tool_bridge.py:module, tests/test_cli_tool_bridge_mapping.py:module, tests/test_context_composition_phase3.py:test_compute_file_stats, tests/test_context_pruner.py:test_performance_large_file, tests/test_context_pruner.py:test_token_reduction_logging, tests/test_deepseek_infra.py:module, tests/test_extended_sims.py:module, tests/test_external_editor_gui.py:module, tests/test_gemini_metrics.py:module, tests/test_gui2_parity.py:module, tests/test_gui2_performance.py:module, tests/test_gui_diagnostics.py:module, tests/test_gui_performance_requirements.py:module, tests/test_gui_stress_performance.py:module, tests/test_gui_updates.py:module, tests/test_headless_service.py:module, tests/test_history_management.py:module, tests/test_hooks.py:module, tests/test_layout_reorganization.py:module, tests/test_live_workflow.py:module, tests/test_log_pruning_heuristic.py:TestLogPruningHeuristic.test_prune_handles_relative_paths_starting_with_logs, tests/test_log_pruning_heuristic.py:TestLogPruningHeuristic.test_prune_removes_empty_sessions_regardless_of_age, tests/test_log_pruning_heuristic.py:TestLogPruningHeuristic.test_prune_removes_sessions_without_metadata_regardless_of_age, tests/test_log_registry.py:TestLogRegistry.setUp, tests/test_mcp_perf_tool.py:module, tests/test_mcp_ts_integration.py:module, tests/test_mma_approval_indicators.py:_collect_text_colored_args, tests/test_mma_concurrent_tracks_sim.py:module, tests/test_mma_concurrent_tracks_stress_sim.py:module, tests/test_mma_dashboard_streams.py:TestMMADashboardStreams.test_tier3_renders_worker_subheaders, tests/test_mma_step_mode_sim.py:module, tests/test_patch_modal_gui.py:module, tests/test_performance_monitor.py:module, tests/test_phase6_simulation.py:module, tests/test_rag_integration.py:mock_project, tests/test_rag_integration.py:test_rag_integration, tests/test_rag_phase4_final_verify.py:module, tests/test_rag_phase4_final_verify.py:test_phase4_final_verify, tests/test_rag_phase4_stress.py:module, tests/test_rag_phase4_stress.py:test_rag_large_codebase_verification_sim, tests/test_rag_visual_sim.py:module, tests/test_selectable_ui.py:module, tests/test_sim_ai_settings.py:module, tests/test_sim_base.py:module, tests/test_sim_context.py:module, tests/test_sim_execution.py:module, tests/test_sim_tools.py:module, tests/test_skeleton_injection.py:test_update_inject_preview_truncation, tests/test_spawn_interception_v2.py:test_confirm_spawn_pushed_to_queue, tests/test_system_prompt_exposure.py:module, tests/test_token_usage.py:module, tests/test_tool_management_layout.py:module, tests/test_ts_c_tools.py:module, tests/test_ts_cpp_tools.py:module, tests/test_ui_cache_controls_sim.py:module, tests/test_user_agent.py:module, tests/test_visual_orchestration.py:module, tests/test_visual_sim_mma_v2.py:module, tests/test_workflow_sim.py:module, tests/test_workspace_profiles_sim.py:module] - """ + """Blocks until all items in the queue have been gotten and processed.""" self._queue.join() # Alias for backward compatibility SyncEventQueue = AsyncEventQueue class UserRequestEvent: - """ - Payload for a user request event. - """ + """Payload for a user request event.""" def __init__(self, prompt: str, stable_md: str, file_items: List[Any], disc_text: str, base_dir: str) -> None: - """ - [C: src/mcp_client.py:_DDGParser.__init__, src/mcp_client.py:_TextExtractor.__init__] - """ self.prompt = prompt self.stable_md = stable_md self.file_items = file_items @@ -164,9 +143,6 @@ class UserRequestEvent: self.base_dir = base_dir def to_dict(self) -> Dict[str, Any]: - """ - [C: src/gui_2.py:App._take_snapshot, src/gui_2.py:App.save_context_preset, src/models.py:ContextPreset.to_dict, src/models.py:ExternalEditorConfig.to_dict, src/models.py:MCPConfiguration.to_dict, src/models.py:RAGConfig.to_dict, src/models.py:ToolPreset.to_dict, src/models.py:Track.to_dict, src/models.py:TrackState.to_dict, src/personas.py:PersonaManager.save_persona, src/presets.py:PresetManager.save_preset, src/project_manager.py:save_project, src/project_manager.py:save_track_state, src/tool_presets.py:ToolPresetManager.save_bias_profile, src/tool_presets.py:ToolPresetManager.save_preset, src/workspace_manager.py:WorkspaceManager.save_profile, tests/test_bias_models.py:test_bias_profile_model, tests/test_bias_models.py:test_tool_model, tests/test_bias_models.py:test_tool_preset_extension, tests/test_context_presets_models.py:test_context_preset_serialization, tests/test_context_presets_models.py:test_file_view_preset_serialization, tests/test_custom_slices_annotations.py:test_file_item_custom_slices_round_trip_annotations, tests/test_custom_slices_annotations.py:test_file_item_custom_slices_serialization_with_annotations, tests/test_event_serialization.py:test_user_request_event_serialization, tests/test_external_editor.py:TestExternalEditorConfig.test_to_dict, tests/test_external_editor.py:TestTextEditorConfig.test_to_dict, tests/test_file_item_model.py:test_file_item_to_dict, tests/test_gui_events_v2.py:test_user_request_event_payload, tests/test_history_manager.py:TestHistoryManager.test_snapshot_roundtrip, tests/test_mcp_config.py:test_mcp_configuration_to_from_dict, tests/test_mcp_config.py:test_mcp_server_config_to_from_dict, tests/test_per_ticket_model.py:test_model_override_serialization, tests/test_persona_id.py:test_ticket_persona_id_serialization, tests/test_persona_models.py:test_persona_defaults, tests/test_persona_models.py:test_persona_serialization, tests/test_slice_editor_behavior.py:test_add_slice_with_annotations, tests/test_thinking_gui.py:test_thinking_segment_model_compatibility, tests/test_ticket_queue.py:test_ticket_to_dict_priority, tests/test_tiered_aggregation.py:test_persona_aggregation_strategy, tests/test_track_state_schema.py:test_track_state_to_dict, tests/test_track_state_schema.py:test_track_state_to_dict_with_none, tests/test_ui_summary_only_removal.py:test_file_item_serialization_with_flags] - """ def _make_serializable(obj: Any) -> Any: if isinstance(obj, dict): return {k: _make_serializable(v) for k, v in obj.items()} if isinstance(obj, list): return [_make_serializable(x) for x in obj] diff --git a/src/vendor_capabilities.py b/src/vendor_capabilities.py index 42ea44e4..04c8f31e 100644 --- a/src/vendor_capabilities.py +++ b/src/vendor_capabilities.py @@ -3,31 +3,31 @@ from dataclasses import dataclass @dataclass(frozen=True) class VendorCapabilities: - vendor: str - model: str - vision: bool = False - tool_calling: bool = True - caching: bool = False - streaming: bool = True - model_discovery: bool = True - context_window: int = 8192 - cost_tracking: bool = True - cost_input_per_mtok: float = 0.0 + vendor: str + model: str + vision: bool = False + tool_calling: bool = True + caching: bool = False + streaming: bool = True + model_discovery: bool = True + context_window: int = 8192 + cost_tracking: bool = True + cost_input_per_mtok: float = 0.0 cost_output_per_mtok: float = 0.0 - notes: str = '' + notes: str = '' # v2 fields (added 2026-06-11) - local: bool = False - reasoning: bool = False + local: bool = False + reasoning: bool = False structured_output: bool = False - code_execution: bool = False - web_search: bool = False - x_search: bool = False - file_search: bool = False - mcp_support: bool = False - audio: bool = False - video: bool = False - grounding: bool = False - computer_use: bool = False + code_execution: bool = False + web_search: bool = False + x_search: bool = False + file_search: bool = False + mcp_support: bool = False + audio: bool = False + video: bool = False + grounding: bool = False + computer_use: bool = False _REGISTRY: dict[tuple[str, str], VendorCapabilities] = {} @@ -35,59 +35,57 @@ def register(cap: VendorCapabilities) -> None: _REGISTRY[(cap.vendor, cap.model)] = cap def get_capabilities(vendor: str, model: str) -> VendorCapabilities: - if (vendor, model) in _REGISTRY: - return _REGISTRY[(vendor, model)] - if (vendor, '*') in _REGISTRY: - return _REGISTRY[(vendor, '*')] + if (vendor, model) in _REGISTRY: return _REGISTRY[(vendor, model)] + if (vendor, '*') in _REGISTRY: return _REGISTRY[(vendor, '*')] raise KeyError(f'No capabilities registered for vendor={vendor!r} model={model!r}') def list_models_for_vendor(vendor: str) -> list[str]: return sorted({m for v, m in _REGISTRY if v == vendor and m != '*'}) -register(VendorCapabilities(vendor='minimax', model='*', context_window=131072, cost_input_per_mtok=0.20, cost_output_per_mtok=0.20)) -register(VendorCapabilities(vendor='minimax', model='MiniMax-M2.7', context_window=131072, cost_input_per_mtok=0.20, cost_output_per_mtok=0.20, reasoning=True)) -register(VendorCapabilities(vendor='minimax', model='MiniMax-M2.5', context_window=131072, cost_input_per_mtok=0.20, cost_output_per_mtok=0.20, reasoning=True)) -register(VendorCapabilities(vendor='minimax', model='MiniMax-M2.1', context_window=131072, cost_input_per_mtok=0.20, cost_output_per_mtok=0.20)) -register(VendorCapabilities(vendor='minimax', model='MiniMax-M2', context_window=131072, cost_input_per_mtok=0.20, cost_output_per_mtok=0.20)) -register(VendorCapabilities(vendor='grok', model='*', context_window=131072, cost_input_per_mtok=2.00, cost_output_per_mtok=10.00, web_search=True, x_search=True)) -register(VendorCapabilities(vendor='grok', model='grok-2', context_window=131072, web_search=True, x_search=True)) -register(VendorCapabilities(vendor='grok', model='grok-2-vision', vision=True, context_window=32768, web_search=True, x_search=True)) -register(VendorCapabilities(vendor='grok', model='grok-beta', context_window=131072, cost_input_per_mtok=5.00, cost_output_per_mtok=15.00, web_search=True, x_search=True)) -register(VendorCapabilities(vendor='llama', model='*', context_window=131072)) -register(VendorCapabilities(vendor='llama', model='llama-3.1-8b-instant', context_window=131072, cost_input_per_mtok=0.05, cost_output_per_mtok=0.08)) -register(VendorCapabilities(vendor='llama', model='llama-3.1-70b-versatile', context_window=131072, cost_input_per_mtok=0.59, cost_output_per_mtok=0.79)) -register(VendorCapabilities(vendor='llama', model='llama-3.1-405b-reasoning', context_window=131072, cost_input_per_mtok=3.00, cost_output_per_mtok=3.00, reasoning=True)) -register(VendorCapabilities(vendor='llama', model='llama-3.2-1b-preview', context_window=131072, cost_input_per_mtok=0.04, cost_output_per_mtok=0.04)) -register(VendorCapabilities(vendor='llama', model='llama-3.2-3b-preview', context_window=131072, cost_input_per_mtok=0.06, cost_output_per_mtok=0.06)) -register(VendorCapabilities(vendor='llama', model='llama-3.2-11b-vision-preview', vision=True, context_window=131072, cost_input_per_mtok=0.18, cost_output_per_mtok=0.18)) -register(VendorCapabilities(vendor='llama', model='llama-3.2-90b-vision-preview', vision=True, context_window=131072, cost_input_per_mtok=0.90, cost_output_per_mtok=0.90)) -register(VendorCapabilities(vendor='llama', model='llama-3.3-70b-specdec', context_window=131072, cost_input_per_mtok=0.59, cost_output_per_mtok=0.79)) -register(VendorCapabilities(vendor='qwen', model='*', context_window=32768)) -register(VendorCapabilities(vendor='qwen', model='qwen-turbo', context_window=1000000, cost_input_per_mtok=0.05, cost_output_per_mtok=0.10)) -register(VendorCapabilities(vendor='qwen', model='qwen-plus', context_window=131072, cost_input_per_mtok=0.40, cost_output_per_mtok=1.20)) -register(VendorCapabilities(vendor='qwen', model='qwen-max', context_window=32768, cost_input_per_mtok=2.00, cost_output_per_mtok=6.00)) -register(VendorCapabilities(vendor='qwen', model='qwen-long', context_window=1000000, cost_input_per_mtok=0.07, cost_output_per_mtok=0.28, caching=True, notes='qwen-long supports custom chunked long-context caching')) -register(VendorCapabilities(vendor='qwen', model='qwen-vl-plus', vision=True, context_window=131072, cost_input_per_mtok=0.21, cost_output_per_mtok=0.63)) -register(VendorCapabilities(vendor='qwen', model='qwen-vl-max', vision=True, context_window=32768, cost_input_per_mtok=0.50, cost_output_per_mtok=1.50)) -register(VendorCapabilities(vendor='qwen', model='qwen-audio', context_window=32768, cost_input_per_mtok=0.10, cost_output_per_mtok=0.30, audio=True, notes='Audio input support added 2026-06-11 (v2 matrix)')) -register(VendorCapabilities(vendor='anthropic', model='*', context_window=200000, cost_input_per_mtok=3.00, cost_output_per_mtok=15.00, caching=True, structured_output=True, file_search=True, mcp_support=True, computer_use=True, notes='Anthropic wildcard: Sonnet defaults. Per-model variations below.')) -register(VendorCapabilities(vendor='anthropic', model='claude-sonnet-4-5-20250929', context_window=200000, cost_input_per_mtok=3.00, cost_output_per_mtok=15.00, caching=True, structured_output=True, file_search=True, mcp_support=True, computer_use=True)) -register(VendorCapabilities(vendor='anthropic', model='claude-sonnet-4-20250514', context_window=200000, cost_input_per_mtok=3.00, cost_output_per_mtok=15.00, caching=True, structured_output=True, file_search=True, mcp_support=True, computer_use=True)) -register(VendorCapabilities(vendor='anthropic', model='claude-sonnet-4-6', context_window=200000, cost_input_per_mtok=3.00, cost_output_per_mtok=15.00, caching=True, structured_output=True, file_search=True, mcp_support=True, computer_use=True)) -register(VendorCapabilities(vendor='anthropic', model='claude-opus-4-1-20250805', context_window=200000, cost_input_per_mtok=15.00, cost_output_per_mtok=75.00, caching=True, structured_output=True, file_search=True, mcp_support=True, computer_use=True)) -register(VendorCapabilities(vendor='anthropic', model='claude-opus-4-20250514', context_window=200000, cost_input_per_mtok=15.00, cost_output_per_mtok=75.00, caching=True, structured_output=True, file_search=True, mcp_support=True, computer_use=True)) -register(VendorCapabilities(vendor='anthropic', model='claude-opus-4-5-20251101', context_window=200000, cost_input_per_mtok=15.00, cost_output_per_mtok=75.00, caching=True, structured_output=True, file_search=True, mcp_support=True, computer_use=True)) -register(VendorCapabilities(vendor='anthropic', model='claude-opus-4-6', context_window=200000, cost_input_per_mtok=15.00, cost_output_per_mtok=75.00, caching=True, structured_output=True, file_search=True, mcp_support=True, computer_use=True)) -register(VendorCapabilities(vendor='anthropic', model='claude-opus-4-7', context_window=200000, cost_input_per_mtok=15.00, cost_output_per_mtok=75.00, caching=True, structured_output=True, file_search=True, mcp_support=True, computer_use=True)) -register(VendorCapabilities(vendor='anthropic', model='claude-opus-4-8', context_window=200000, cost_input_per_mtok=15.00, cost_output_per_mtok=75.00, caching=True, structured_output=True, file_search=True, mcp_support=True, computer_use=True)) -register(VendorCapabilities(vendor='anthropic', model='claude-haiku-4-5-20251001', context_window=200000, cost_input_per_mtok=1.00, cost_output_per_mtok=5.00, caching=True, structured_output=True, file_search=True, mcp_support=True, computer_use=True)) -register(VendorCapabilities(vendor='anthropic', model='claude-fable-5', context_window=200000, cost_input_per_mtok=3.00, cost_output_per_mtok=15.00, caching=True, structured_output=True, file_search=True, mcp_support=True, computer_use=True)) -register(VendorCapabilities(vendor='gemini', model='*', context_window=1000000, cost_input_per_mtok=1.25, cost_output_per_mtok=5.00, caching=True, vision=True, video=True, audio=True, grounding=True, structured_output=True, notes='Gemini wildcard: 1M+ context window. Per-model variations below.')) -register(VendorCapabilities(vendor='gemini', model='gemini-3.1-pro-preview', context_window=1000000, cost_input_per_mtok=3.50, cost_output_per_mtok=10.50, caching=True, vision=True, video=True, audio=True, grounding=True, structured_output=True)) -register(VendorCapabilities(vendor='gemini', model='gemini-3-flash-preview', context_window=1000000, cost_input_per_mtok=0.15, cost_output_per_mtok=0.60, caching=True, vision=True, video=True, audio=True, grounding=True, structured_output=True)) -register(VendorCapabilities(vendor='gemini', model='gemini-2.5-flash', context_window=1000000, cost_input_per_mtok=0.15, cost_output_per_mtok=0.60, caching=True, vision=True, video=True, audio=True, grounding=True, structured_output=True)) -register(VendorCapabilities(vendor='gemini', model='gemini-2.5-flash-lite', context_window=1000000, cost_input_per_mtok=0.075, cost_output_per_mtok=0.30, caching=True, vision=True, grounding=True, structured_output=True)) -register(VendorCapabilities(vendor='deepseek', model='*', context_window=32768, cost_input_per_mtok=0.27, cost_output_per_mtok=1.10, reasoning=True, structured_output=True, notes='DeepSeek wildcard: V3 defaults. R1/reasoner variants below.')) -register(VendorCapabilities(vendor='deepseek', model='deepseek-v3', context_window=32768, cost_input_per_mtok=0.27, cost_output_per_mtok=1.10, structured_output=True)) -register(VendorCapabilities(vendor='deepseek', model='deepseek-reasoner', context_window=32768, cost_input_per_mtok=0.55, cost_output_per_mtok=2.19, reasoning=True, structured_output=True)) -register(VendorCapabilities(vendor='deepseek', model='deepseek-r1', context_window=32768, cost_input_per_mtok=0.55, cost_output_per_mtok=2.19, reasoning=True, structured_output=True)) +register(VendorCapabilities(vendor='minimax', model='*', context_window=131072, cost_input_per_mtok=0.20, cost_output_per_mtok=0.20)) +register(VendorCapabilities(vendor='minimax', model='MiniMax-M2.7', context_window=131072, cost_input_per_mtok=0.20, cost_output_per_mtok=0.20, reasoning=True)) +register(VendorCapabilities(vendor='minimax', model='MiniMax-M2.5', context_window=131072, cost_input_per_mtok=0.20, cost_output_per_mtok=0.20, reasoning=True)) +register(VendorCapabilities(vendor='minimax', model='MiniMax-M2.1', context_window=131072, cost_input_per_mtok=0.20, cost_output_per_mtok=0.20)) +register(VendorCapabilities(vendor='minimax', model='MiniMax-M2', context_window=131072, cost_input_per_mtok=0.20, cost_output_per_mtok=0.20)) +register(VendorCapabilities(vendor='grok', model='*', context_window=131072, cost_input_per_mtok=2.00, cost_output_per_mtok=10.00, web_search=True, x_search=True)) +register(VendorCapabilities(vendor='grok', model='grok-2', context_window=131072, web_search=True, x_search=True)) +register(VendorCapabilities(vendor='grok', model='grok-2-vision', vision=True, context_window=32768, web_search=True, x_search=True)) +register(VendorCapabilities(vendor='grok', model='grok-beta', context_window=131072, cost_input_per_mtok=5.00, cost_output_per_mtok=15.00, web_search=True, x_search=True)) +register(VendorCapabilities(vendor='llama', model='*', context_window=131072)) +register(VendorCapabilities(vendor='llama', model='llama-3.1-8b-instant', context_window=131072, cost_input_per_mtok=0.05, cost_output_per_mtok=0.08)) +register(VendorCapabilities(vendor='llama', model='llama-3.1-70b-versatile', context_window=131072, cost_input_per_mtok=0.59, cost_output_per_mtok=0.79)) +register(VendorCapabilities(vendor='llama', model='llama-3.1-405b-reasoning', context_window=131072, cost_input_per_mtok=3.00, cost_output_per_mtok=3.00, reasoning=True)) +register(VendorCapabilities(vendor='llama', model='llama-3.2-1b-preview', context_window=131072, cost_input_per_mtok=0.04, cost_output_per_mtok=0.04)) +register(VendorCapabilities(vendor='llama', model='llama-3.2-3b-preview', context_window=131072, cost_input_per_mtok=0.06, cost_output_per_mtok=0.06)) +register(VendorCapabilities(vendor='llama', model='llama-3.2-11b-vision-preview', vision=True, context_window=131072, cost_input_per_mtok=0.18, cost_output_per_mtok=0.18)) +register(VendorCapabilities(vendor='llama', model='llama-3.2-90b-vision-preview', vision=True, context_window=131072, cost_input_per_mtok=0.90, cost_output_per_mtok=0.90)) +register(VendorCapabilities(vendor='llama', model='llama-3.3-70b-specdec', context_window=131072, cost_input_per_mtok=0.59, cost_output_per_mtok=0.79)) +register(VendorCapabilities(vendor='qwen', model='*', context_window=32768)) +register(VendorCapabilities(vendor='qwen', model='qwen-turbo', context_window=1000000, cost_input_per_mtok=0.05, cost_output_per_mtok=0.10)) +register(VendorCapabilities(vendor='qwen', model='qwen-plus', context_window=131072, cost_input_per_mtok=0.40, cost_output_per_mtok=1.20)) +register(VendorCapabilities(vendor='qwen', model='qwen-max', context_window=32768, cost_input_per_mtok=2.00, cost_output_per_mtok=6.00)) +register(VendorCapabilities(vendor='qwen', model='qwen-long', context_window=1000000, cost_input_per_mtok=0.07, cost_output_per_mtok=0.28, caching=True, notes='qwen-long supports custom chunked long-context caching')) +register(VendorCapabilities(vendor='qwen', model='qwen-vl-plus', vision=True, context_window=131072, cost_input_per_mtok=0.21, cost_output_per_mtok=0.63)) +register(VendorCapabilities(vendor='qwen', model='qwen-vl-max', vision=True, context_window=32768, cost_input_per_mtok=0.50, cost_output_per_mtok=1.50)) +register(VendorCapabilities(vendor='qwen', model='qwen-audio', context_window=32768, cost_input_per_mtok=0.10, cost_output_per_mtok=0.30, audio=True, notes='Audio input support added 2026-06-11 (v2 matrix)')) +register(VendorCapabilities(vendor='anthropic', model='*', context_window=200000, cost_input_per_mtok=3.00, cost_output_per_mtok=15.00, caching=True, structured_output=True, file_search=True, mcp_support=True, computer_use=True, notes='Anthropic wildcard: Sonnet defaults. Per-model variations below.')) +register(VendorCapabilities(vendor='anthropic', model='claude-sonnet-4-5-20250929', context_window=200000, cost_input_per_mtok=3.00, cost_output_per_mtok=15.00, caching=True, structured_output=True, file_search=True, mcp_support=True, computer_use=True)) +register(VendorCapabilities(vendor='anthropic', model='claude-sonnet-4-20250514', context_window=200000, cost_input_per_mtok=3.00, cost_output_per_mtok=15.00, caching=True, structured_output=True, file_search=True, mcp_support=True, computer_use=True)) +register(VendorCapabilities(vendor='anthropic', model='claude-sonnet-4-6', context_window=200000, cost_input_per_mtok=3.00, cost_output_per_mtok=15.00, caching=True, structured_output=True, file_search=True, mcp_support=True, computer_use=True)) +register(VendorCapabilities(vendor='anthropic', model='claude-opus-4-1-20250805', context_window=200000, cost_input_per_mtok=15.00, cost_output_per_mtok=75.00, caching=True, structured_output=True, file_search=True, mcp_support=True, computer_use=True)) +register(VendorCapabilities(vendor='anthropic', model='claude-opus-4-20250514', context_window=200000, cost_input_per_mtok=15.00, cost_output_per_mtok=75.00, caching=True, structured_output=True, file_search=True, mcp_support=True, computer_use=True)) +register(VendorCapabilities(vendor='anthropic', model='claude-opus-4-5-20251101', context_window=200000, cost_input_per_mtok=15.00, cost_output_per_mtok=75.00, caching=True, structured_output=True, file_search=True, mcp_support=True, computer_use=True)) +register(VendorCapabilities(vendor='anthropic', model='claude-opus-4-6', context_window=200000, cost_input_per_mtok=15.00, cost_output_per_mtok=75.00, caching=True, structured_output=True, file_search=True, mcp_support=True, computer_use=True)) +register(VendorCapabilities(vendor='anthropic', model='claude-opus-4-7', context_window=200000, cost_input_per_mtok=15.00, cost_output_per_mtok=75.00, caching=True, structured_output=True, file_search=True, mcp_support=True, computer_use=True)) +register(VendorCapabilities(vendor='anthropic', model='claude-opus-4-8', context_window=200000, cost_input_per_mtok=15.00, cost_output_per_mtok=75.00, caching=True, structured_output=True, file_search=True, mcp_support=True, computer_use=True)) +register(VendorCapabilities(vendor='anthropic', model='claude-haiku-4-5-20251001', context_window=200000, cost_input_per_mtok=1.00, cost_output_per_mtok=5.00, caching=True, structured_output=True, file_search=True, mcp_support=True, computer_use=True)) +register(VendorCapabilities(vendor='anthropic', model='claude-fable-5', context_window=200000, cost_input_per_mtok=3.00, cost_output_per_mtok=15.00, caching=True, structured_output=True, file_search=True, mcp_support=True, computer_use=True)) +register(VendorCapabilities(vendor='gemini', model='*', context_window=1000000, cost_input_per_mtok=1.25, cost_output_per_mtok=5.00, caching=True, vision=True, video=True, audio=True, grounding=True, structured_output=True, notes='Gemini wildcard: 1M+ context window. Per-model variations below.')) +register(VendorCapabilities(vendor='gemini', model='gemini-3.1-pro-preview', context_window=1000000, cost_input_per_mtok=3.50, cost_output_per_mtok=10.50, caching=True, vision=True, video=True, audio=True, grounding=True, structured_output=True)) +register(VendorCapabilities(vendor='gemini', model='gemini-3-flash-preview', context_window=1000000, cost_input_per_mtok=0.15, cost_output_per_mtok=0.60, caching=True, vision=True, video=True, audio=True, grounding=True, structured_output=True)) +register(VendorCapabilities(vendor='gemini', model='gemini-2.5-flash', context_window=1000000, cost_input_per_mtok=0.15, cost_output_per_mtok=0.60, caching=True, vision=True, video=True, audio=True, grounding=True, structured_output=True)) +register(VendorCapabilities(vendor='gemini', model='gemini-2.5-flash-lite', context_window=1000000, cost_input_per_mtok=0.075, cost_output_per_mtok=0.30, caching=True, vision=True, grounding=True, structured_output=True)) +register(VendorCapabilities(vendor='deepseek', model='*', context_window=32768, cost_input_per_mtok=0.27, cost_output_per_mtok=1.10, reasoning=True, structured_output=True, notes='DeepSeek wildcard: V3 defaults. R1/reasoner variants below.')) +register(VendorCapabilities(vendor='deepseek', model='deepseek-v3', context_window=32768, cost_input_per_mtok=0.27, cost_output_per_mtok=1.10, structured_output=True)) +register(VendorCapabilities(vendor='deepseek', model='deepseek-reasoner', context_window=32768, cost_input_per_mtok=0.55, cost_output_per_mtok=2.19, reasoning=True, structured_output=True)) +register(VendorCapabilities(vendor='deepseek', model='deepseek-r1', context_window=32768, cost_input_per_mtok=0.55, cost_output_per_mtok=2.19, reasoning=True, structured_output=True))