alysis-code 0.13.0__py3-none-any.whl
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.
- alysis_code/__init__.py +3 -0
- alysis_code/__main__.py +4 -0
- alysis_code/_build_info.py +14 -0
- alysis_code/account_login.py +468 -0
- alysis_code/agent/README.md +35 -0
- alysis_code/agent/__init__.py +11 -0
- alysis_code/agent/acceptance_contract.py +2217 -0
- alysis_code/agent/blast_radius.py +1403 -0
- alysis_code/agent/cache_keepalive.py +227 -0
- alysis_code/agent/completion_certificate.py +366 -0
- alysis_code/agent/completion_gate.py +306 -0
- alysis_code/agent/empty_response_stall.py +403 -0
- alysis_code/agent/errors.py +28 -0
- alysis_code/agent/llm_calls.py +475 -0
- alysis_code/agent/mutation_classification.py +227 -0
- alysis_code/agent/prompt_context.py +2508 -0
- alysis_code/agent/read_ledger.py +253 -0
- alysis_code/agent/regression_baseline.py +642 -0
- alysis_code/agent/reproduction_first.py +610 -0
- alysis_code/agent/sensitive_output.py +629 -0
- alysis_code/agent/session.py +3218 -0
- alysis_code/agent/steering.py +191 -0
- alysis_code/agent/subagent_execution.py +5177 -0
- alysis_code/agent/subagent_workspace.py +666 -0
- alysis_code/agent/tools_assembly.py +4728 -0
- alysis_code/agent/turn/__init__.py +101 -0
- alysis_code/agent/turn/core.py +8483 -0
- alysis_code/agent/turn/events.py +113 -0
- alysis_code/agent/turn/exploration.py +590 -0
- alysis_code/agent/turn/interventions.py +65 -0
- alysis_code/agent/turn/read_cache.py +420 -0
- alysis_code/agent/turn/snapshot.py +179 -0
- alysis_code/agent/turn_contract.py +661 -0
- alysis_code/agent/turn_path.py +129 -0
- alysis_code/agent/verification.py +2885 -0
- alysis_code/agent/verification_commands.py +512 -0
- alysis_code/agent/verification_evidence.py +738 -0
- alysis_code/agent_loop.py +693 -0
- alysis_code/agent_runtimes/__init__.py +51 -0
- alysis_code/agent_runtimes/base.py +114 -0
- alysis_code/agent_runtimes/builtins.py +129 -0
- alysis_code/agent_runtimes/codex_cli.py +664 -0
- alysis_code/agent_runtimes/host.py +263 -0
- alysis_code/agent_runtimes/registry.py +64 -0
- alysis_code/agent_runtimes/service.py +150 -0
- alysis_code/agentbox_client.py +416 -0
- alysis_code/agentbox_integration.py +310 -0
- alysis_code/alysis_cloud.py +152 -0
- alysis_code/approval_scope.py +276 -0
- alysis_code/assets/README.md +33 -0
- alysis_code/assets/__init__.py +126 -0
- alysis_code/assets/asset_read_core.py +281 -0
- alysis_code/assets/budget_allocator.py +456 -0
- alysis_code/assets/comprehender.py +759 -0
- alysis_code/assets/index.py +654 -0
- alysis_code/assets/ingestion.py +275 -0
- alysis_code/assets/legacy_migration.py +413 -0
- alysis_code/assets/models.py +263 -0
- alysis_code/assets/ocr.py +239 -0
- alysis_code/assets/owl/ascii/f-000.txt +13 -0
- alysis_code/assets/owl/ascii/f-001.txt +13 -0
- alysis_code/assets/owl/ascii/f-002.txt +13 -0
- alysis_code/assets/owl/ascii/f-003.txt +13 -0
- alysis_code/assets/owl/ascii/f-004.txt +13 -0
- alysis_code/assets/owl/ascii/f-005.txt +13 -0
- alysis_code/assets/owl/ascii/f-006.txt +13 -0
- alysis_code/assets/owl/ascii/f-007.txt +13 -0
- alysis_code/assets/owl/ascii/f-008.txt +13 -0
- alysis_code/assets/owl/ascii/f-009.txt +13 -0
- alysis_code/assets/owl/ascii/f-010.txt +13 -0
- alysis_code/assets/owl/ascii/f-011.txt +13 -0
- alysis_code/assets/owl/ascii/f-012.txt +13 -0
- alysis_code/assets/owl/ascii/f-013.txt +13 -0
- alysis_code/assets/owl/ascii/f-014.txt +13 -0
- alysis_code/assets/owl/ascii/f-015.txt +13 -0
- alysis_code/assets/owl/ascii/f-016.txt +13 -0
- alysis_code/assets/owl/ascii/f-017.txt +13 -0
- alysis_code/assets/owl/ascii/f-018.txt +13 -0
- alysis_code/assets/owl/ascii/f-019.txt +13 -0
- alysis_code/assets/owl/ascii/f-020.txt +13 -0
- alysis_code/assets/owl/index.html +98 -0
- alysis_code/assets/owl/show-owl.sh +761 -0
- alysis_code/assets/paths.py +49 -0
- alysis_code/assets/plan_binding.py +326 -0
- alysis_code/assets/planner_context.py +466 -0
- alysis_code/assets/planner_tools.py +184 -0
- alysis_code/assets/prompts.py +101 -0
- alysis_code/assets/replanner_context.py +239 -0
- alysis_code/assets/surface.py +521 -0
- alysis_code/assets/untrusted_content.py +48 -0
- alysis_code/assets/usage_logger.py +94 -0
- alysis_code/assets/worker_mirror.py +428 -0
- alysis_code/assets/worker_section.py +303 -0
- alysis_code/assets/worker_tools.py +468 -0
- alysis_code/atomic_io.py +83 -0
- alysis_code/auth_diagnostics.py +272 -0
- alysis_code/background_runner.py +366 -0
- alysis_code/branding.py +270 -0
- alysis_code/budget_policy.py +390 -0
- alysis_code/build_identity.py +465 -0
- alysis_code/builtin_hooks/__init__.py +7 -0
- alysis_code/builtin_hooks/notify_done_windows.py +65 -0
- alysis_code/bwrap_etc.py +76 -0
- alysis_code/cancellation.py +41 -0
- alysis_code/capabilities.py +137 -0
- alysis_code/chatgpt_codex_static_provider.py +133 -0
- alysis_code/cli.py +51 -0
- alysis_code/cli_impl/__init__.py +1 -0
- alysis_code/cli_impl/assets_cli.py +537 -0
- alysis_code/cli_impl/assets_modal.py +412 -0
- alysis_code/cli_impl/chat/__init__.py +156 -0
- alysis_code/cli_impl/chat/commands.py +2616 -0
- alysis_code/cli_impl/chat/loop.py +4508 -0
- alysis_code/cli_impl/chat/mid_turn_policy.py +125 -0
- alysis_code/cli_impl/chat/rendering.py +444 -0
- alysis_code/cli_impl/chat/state.py +124 -0
- alysis_code/cli_impl/chat_resume.py +830 -0
- alysis_code/cli_impl/chat_slash_completer.py +258 -0
- alysis_code/cli_impl/commands/__init__.py +11 -0
- alysis_code/cli_impl/commands/_shared.py +89 -0
- alysis_code/cli_impl/commands/auth.py +623 -0
- alysis_code/cli_impl/commands/chat_resume_helpers.py +1531 -0
- alysis_code/cli_impl/commands/chat_state.py +158 -0
- alysis_code/cli_impl/commands/chat_status.py +1248 -0
- alysis_code/cli_impl/commands/chat_terminal.py +942 -0
- alysis_code/cli_impl/commands/chat_tui_panels.py +1018 -0
- alysis_code/cli_impl/commands/cli_common.py +1223 -0
- alysis_code/cli_impl/commands/cli_surface.py +77 -0
- alysis_code/cli_impl/commands/config.py +131 -0
- alysis_code/cli_impl/commands/conventions.py +85 -0
- alysis_code/cli_impl/commands/execution_helpers.py +350 -0
- alysis_code/cli_impl/commands/extensions.py +401 -0
- alysis_code/cli_impl/commands/forge.py +1282 -0
- alysis_code/cli_impl/commands/forge_asset_view.py +121 -0
- alysis_code/cli_impl/commands/forge_helpers.py +1215 -0
- alysis_code/cli_impl/commands/hooks.py +737 -0
- alysis_code/cli_impl/commands/ide_bridge.py +31 -0
- alysis_code/cli_impl/commands/mcp.py +700 -0
- alysis_code/cli_impl/commands/profile.py +453 -0
- alysis_code/cli_impl/commands/prompt_helpers.py +307 -0
- alysis_code/cli_impl/commands/report.py +88 -0
- alysis_code/cli_impl/commands/root.py +1118 -0
- alysis_code/cli_impl/commands/sandbox.py +184 -0
- alysis_code/cli_impl/commands/server.py +54 -0
- alysis_code/cli_impl/commands/sessions.py +252 -0
- alysis_code/cli_impl/commands/skills.py +404 -0
- alysis_code/cli_impl/commands/startup.py +946 -0
- alysis_code/cli_impl/commands/tools.py +335 -0
- alysis_code/cli_impl/commands/update.py +364 -0
- alysis_code/cli_impl/commands/welcome.py +972 -0
- alysis_code/cli_impl/config_menu.py +3882 -0
- alysis_code/cli_impl/forge.py +4509 -0
- alysis_code/cli_impl/forge_recovery.py +485 -0
- alysis_code/cli_impl/setup_wizard.py +2409 -0
- alysis_code/cli_impl/tui/__init__.py +58 -0
- alysis_code/cli_impl/tui/app.py +4551 -0
- alysis_code/cli_impl/tui/config.py +32 -0
- alysis_code/cli_impl/tui/config_flow.py +2754 -0
- alysis_code/cli_impl/tui/config_overlay.py +566 -0
- alysis_code/cli_impl/tui/content.py +78 -0
- alysis_code/cli_impl/tui/footer.py +218 -0
- alysis_code/cli_impl/tui/forge_status.py +136 -0
- alysis_code/cli_impl/tui/markdown.py +244 -0
- alysis_code/cli_impl/tui/owl.py +109 -0
- alysis_code/cli_impl/tui/plan_meta.py +477 -0
- alysis_code/cli_impl/tui/setup_app.py +519 -0
- alysis_code/cli_impl/tui/setup_flow.py +1622 -0
- alysis_code/cli_impl/tui/state.py +101 -0
- alysis_code/cli_impl/tui/subagent_identity.py +66 -0
- alysis_code/cli_impl/tui/subagent_panel.py +186 -0
- alysis_code/cli_impl/tui/surface.py +796 -0
- alysis_code/cli_impl/tui/transcript.py +514 -0
- alysis_code/cli_impl/tui/update_prompt.py +79 -0
- alysis_code/cli_impl/tui/workspace_guard.py +384 -0
- alysis_code/clipboard.py +172 -0
- alysis_code/code_review.py +1211 -0
- alysis_code/compaction/__init__.py +28 -0
- alysis_code/compaction/conversation_compactor.py +2932 -0
- alysis_code/compaction/importance.py +177 -0
- alysis_code/compaction/settings.py +297 -0
- alysis_code/compaction/tool_output_offload.py +447 -0
- alysis_code/config.py +3509 -0
- alysis_code/conflict_auto_resolver.py +895 -0
- alysis_code/context/__init__.py +1 -0
- alysis_code/context/tool_schema_budgeter.py +220 -0
- alysis_code/crash_diagnostics.py +282 -0
- alysis_code/custom_tools/README.md +34 -0
- alysis_code/custom_tools/__init__.py +43 -0
- alysis_code/custom_tools/discovery.py +903 -0
- alysis_code/custom_tools/runtime.py +1516 -0
- alysis_code/custom_tools/session.py +227 -0
- alysis_code/custom_tools/trust.py +232 -0
- alysis_code/diff_paths.py +113 -0
- alysis_code/direction_change.py +293 -0
- alysis_code/dispatch_timing.py +306 -0
- alysis_code/durable_service_manager.py +1236 -0
- alysis_code/edit_discipline.py +659 -0
- alysis_code/error_text.py +73 -0
- alysis_code/execution_budget.py +411 -0
- alysis_code/execution_context.py +915 -0
- alysis_code/execution_deadline.py +1065 -0
- alysis_code/execution_shared.py +1904 -0
- alysis_code/extensions/README.md +30 -0
- alysis_code/extensions/__init__.py +93 -0
- alysis_code/extensions/activation.py +138 -0
- alysis_code/extensions/install.py +1436 -0
- alysis_code/extensions/manifest.py +487 -0
- alysis_code/extensions/models.py +74 -0
- alysis_code/extensions/paths.py +56 -0
- alysis_code/extensions/registry.json +4 -0
- alysis_code/extensions/registry.py +52 -0
- alysis_code/extensions/state.py +83 -0
- alysis_code/extensions/workspace_trust.py +101 -0
- alysis_code/failed_task_evidence.py +369 -0
- alysis_code/failure_category.py +315 -0
- alysis_code/feedback_report.py +1647 -0
- alysis_code/file_classification.py +485 -0
- alysis_code/forge.py +2064 -0
- alysis_code/forge_completion.py +362 -0
- alysis_code/forge_events.py +475 -0
- alysis_code/frontmatter_utils.py +95 -0
- alysis_code/git_evidence.py +1181 -0
- alysis_code/git_ops.py +560 -0
- alysis_code/git_safe.py +62 -0
- alysis_code/git_worktrees.py +190 -0
- alysis_code/hooks/README.md +33 -0
- alysis_code/hooks/__init__.py +67 -0
- alysis_code/hooks/audit.py +171 -0
- alysis_code/hooks/config.py +225 -0
- alysis_code/hooks/dispatcher.py +1110 -0
- alysis_code/hooks/models.py +447 -0
- alysis_code/hooks/trust.py +202 -0
- alysis_code/host_actions.py +543 -0
- alysis_code/host_browser.py +103 -0
- alysis_code/ide/__init__.py +5 -0
- alysis_code/ide/activity_events.py +399 -0
- alysis_code/ide/approvals.py +337 -0
- alysis_code/ide/artifacts.py +153 -0
- alysis_code/ide/browser_egress_proxy.py +1076 -0
- alysis_code/ide/cdp_websocket_transport.py +1192 -0
- alysis_code/ide/change_ledger.py +1721 -0
- alysis_code/ide/context_blocks.py +979 -0
- alysis_code/ide/event_stream.py +531 -0
- alysis_code/ide/forge_protocol.py +3112 -0
- alysis_code/ide/forge_request_ledger.py +737 -0
- alysis_code/ide/health.py +965 -0
- alysis_code/ide/managed_browser.py +2251 -0
- alysis_code/ide/management_protocol.py +3414 -0
- alysis_code/ide/mcp_oauth_coordinator.py +744 -0
- alysis_code/ide/mcp_oauth_lifecycle.py +1504 -0
- alysis_code/ide/prompt_queue.py +1070 -0
- alysis_code/ide/protocol.py +191 -0
- alysis_code/ide/resumable_swarm.py +1543 -0
- alysis_code/ide/session_search.py +295 -0
- alysis_code/ide/stdio_bridge.py +9935 -0
- alysis_code/ide/structured_state.py +1579 -0
- alysis_code/ide/swarm_protocol.py +816 -0
- alysis_code/integration_gate.py +506 -0
- alysis_code/interactive_input_guard.py +39 -0
- alysis_code/interactive_plan_mode.py +26 -0
- alysis_code/internal_artifacts.py +179 -0
- alysis_code/knowledge_base.py +1409 -0
- alysis_code/knowledge_capture.py +1190 -0
- alysis_code/knowledge_librarian.py +605 -0
- alysis_code/language_policy.py +34 -0
- alysis_code/litellm_static_provider.py +535 -0
- alysis_code/llm/__init__.py +1 -0
- alysis_code/llm/anthropic_messages.py +2288 -0
- alysis_code/llm/base.py +71 -0
- alysis_code/llm/cache_capabilities.py +985 -0
- alysis_code/llm/cache_control_blocks.py +244 -0
- alysis_code/llm/cache_policy.py +388 -0
- alysis_code/llm/factory.py +373 -0
- alysis_code/llm/gemini_generate_content.py +2652 -0
- alysis_code/llm/gemini_interactions.py +739 -0
- alysis_code/llm/metadata.py +450 -0
- alysis_code/llm/openai_compat.py +2947 -0
- alysis_code/llm/openai_responses.py +2604 -0
- alysis_code/llm/protocols.py +609 -0
- alysis_code/llm/provider_limits.py +525 -0
- alysis_code/llm/request_plan.py +389 -0
- alysis_code/llm/request_shape.py +238 -0
- alysis_code/llm/streaming.py +108 -0
- alysis_code/llm/temperature_compat.py +78 -0
- alysis_code/llm/types.py +195 -0
- alysis_code/llm/usage_normalization.py +222 -0
- alysis_code/llm_error_display.py +315 -0
- alysis_code/logging_redaction.py +326 -0
- alysis_code/managed_host_deadline.py +196 -0
- alysis_code/mcp/README.md +33 -0
- alysis_code/mcp/__init__.py +24 -0
- alysis_code/mcp/client.py +1137 -0
- alysis_code/mcp/config.py +597 -0
- alysis_code/mcp/errors.py +113 -0
- alysis_code/mcp/forge_scope.py +154 -0
- alysis_code/mcp/jsonrpc.py +214 -0
- alysis_code/mcp/manager.py +2308 -0
- alysis_code/mcp/models.py +666 -0
- alysis_code/mcp/oauth.py +972 -0
- alysis_code/mcp/oauth_runtime.py +310 -0
- alysis_code/mcp/oauth_store.py +276 -0
- alysis_code/mcp/prompts.py +329 -0
- alysis_code/mcp/resources.py +295 -0
- alysis_code/mcp/roots.py +106 -0
- alysis_code/mcp/server_requests.py +75 -0
- alysis_code/mcp/token_store.py +859 -0
- alysis_code/mcp/transport_http.py +1338 -0
- alysis_code/mcp/transport_stdio.py +1267 -0
- alysis_code/mcp/untrusted_content.py +119 -0
- alysis_code/merge_conflict_reviewer.py +729 -0
- alysis_code/model_catalog/__init__.py +1 -0
- alysis_code/model_catalog/chatgpt_codex_subscription_snapshot.json +186 -0
- alysis_code/model_catalog/litellm_model_prices_snapshot.json +44715 -0
- alysis_code/model_catalog/litellm_model_prices_snapshot.meta.json +17 -0
- alysis_code/model_metadata_policy.py +223 -0
- alysis_code/model_metadata_utils.py +103 -0
- alysis_code/model_registry.py +1420 -0
- alysis_code/model_router.py +147 -0
- alysis_code/permission_policy.py +1016 -0
- alysis_code/personas.py +451 -0
- alysis_code/pipeline_facts.py +233 -0
- alysis_code/plan_assistant.py +4763 -0
- alysis_code/plan_mode.py +393 -0
- alysis_code/plan_reconciliation.py +1228 -0
- alysis_code/plan_repair.py +652 -0
- alysis_code/plan_validation.py +1099 -0
- alysis_code/planning_constraints.py +904 -0
- alysis_code/policy.py +95 -0
- alysis_code/preview_server.py +457 -0
- alysis_code/process_reaping.py +566 -0
- alysis_code/profile_presets.py +1834 -0
- alysis_code/profiles.py +666 -0
- alysis_code/provider_auth/__init__.py +29 -0
- alysis_code/provider_auth/base.py +99 -0
- alysis_code/provider_auth/openai_codex.py +951 -0
- alysis_code/provider_auth/registry.py +76 -0
- alysis_code/provider_auth/store.py +125 -0
- alysis_code/provider_diagnostics.py +1209 -0
- alysis_code/provider_model_catalog.py +685 -0
- alysis_code/provider_telemetry.py +1699 -0
- alysis_code/provider_url.py +75 -0
- alysis_code/reasoning_contracts.py +911 -0
- alysis_code/remote_sync.py +350 -0
- alysis_code/replanning.py +1195 -0
- alysis_code/repo_scan.py +1152 -0
- alysis_code/request_estimation.py +296 -0
- alysis_code/review_gate.py +617 -0
- alysis_code/run_lock.py +1141 -0
- alysis_code/run_outcome.py +58 -0
- alysis_code/run_provenance.py +774 -0
- alysis_code/run_state.py +445 -0
- alysis_code/runtime_artifacts.py +116 -0
- alysis_code/runtime_context_features.py +78 -0
- alysis_code/runtime_kind.py +52 -0
- alysis_code/safety/__init__.py +11 -0
- alysis_code/safety/mcp_sanitize.py +29 -0
- alysis_code/safety/safe_http.py +297 -0
- alysis_code/safety/subagent_report.py +184 -0
- alysis_code/sandbox_doctor.py +682 -0
- alysis_code/sandbox_runner.py +1025 -0
- alysis_code/sandbox_settings.py +423 -0
- alysis_code/serialized_paths.py +355 -0
- alysis_code/server/__init__.py +3 -0
- alysis_code/server/app.py +367 -0
- alysis_code/server/auth.py +34 -0
- alysis_code/server/job_config.py +30 -0
- alysis_code/server/settings.py +215 -0
- alysis_code/server/store.py +193 -0
- alysis_code/server/worker_runner.py +657 -0
- alysis_code/service_persistence.py +355 -0
- alysis_code/session_artifacts.py +108 -0
- alysis_code/session_metrics.py +331 -0
- alysis_code/session_store.py +624 -0
- alysis_code/skills/README.md +34 -0
- alysis_code/skills/__init__.py +104 -0
- alysis_code/skills/conventions.py +84 -0
- alysis_code/skills/discovery.py +176 -0
- alysis_code/skills/eval_models.py +232 -0
- alysis_code/skills/eval_runner.py +372 -0
- alysis_code/skills/evals.py +1344 -0
- alysis_code/skills/install.py +293 -0
- alysis_code/skills/loader.py +118 -0
- alysis_code/skills/matching.py +103 -0
- alysis_code/skills/models.py +71 -0
- alysis_code/skills/paths.py +56 -0
- alysis_code/skills/prompting.py +500 -0
- alysis_code/skills/scaffold.py +142 -0
- alysis_code/skills/state.py +441 -0
- alysis_code/skills/transactions.py +125 -0
- alysis_code/skills/validation.py +304 -0
- alysis_code/step_budget.py +238 -0
- alysis_code/subagent_labels.py +49 -0
- alysis_code/subagents.py +1072 -0
- alysis_code/surface/__init__.py +80 -0
- alysis_code/surface/base.py +305 -0
- alysis_code/surface/console.py +387 -0
- alysis_code/surface/events.py +372 -0
- alysis_code/surface/hidden_surface.py +529 -0
- alysis_code/surface/noop_surface.py +219 -0
- alysis_code/surface/rich_surface.py +1555 -0
- alysis_code/surface/styles.py +67 -0
- alysis_code/surface/theme.py +455 -0
- alysis_code/surface/types.py +100 -0
- alysis_code/swarm_backend.py +926 -0
- alysis_code/swarm_orchestrator.py +4020 -0
- alysis_code/swarm_scheduler.py +441 -0
- alysis_code/swarm_trace.py +429 -0
- alysis_code/swarm_worker.py +2119 -0
- alysis_code/swarm_write_guard.py +348 -0
- alysis_code/task_dependencies.py +170 -0
- alysis_code/task_readiness.py +992 -0
- alysis_code/task_scope.py +2148 -0
- alysis_code/terminal_manager.py +762 -0
- alysis_code/terminal_ownership.py +460 -0
- alysis_code/text_normalization.py +30 -0
- alysis_code/token_budget.py +97 -0
- alysis_code/tools/README.md +34 -0
- alysis_code/tools/__init__.py +1 -0
- alysis_code/tools/artifacts.py +127 -0
- alysis_code/tools/availability.py +188 -0
- alysis_code/tools/fs.py +1456 -0
- alysis_code/tools/git.py +461 -0
- alysis_code/tools/history.py +229 -0
- alysis_code/tools/http_timeout.py +78 -0
- alysis_code/tools/image_generation.py +552 -0
- alysis_code/tools/registry.py +2936 -0
- alysis_code/tools/repo_map.py +476 -0
- alysis_code/tools/search.py +563 -0
- alysis_code/tools/shell.py +135 -0
- alysis_code/tools/symbols.py +1350 -0
- alysis_code/tools/test_discovery.py +643 -0
- alysis_code/tools/web.py +482 -0
- alysis_code/tools/web_search.py +2012 -0
- alysis_code/tools/web_search_dashscope.py +557 -0
- alysis_code/tools/web_search_ddgs.py +221 -0
- alysis_code/tools/web_search_provider_adapters.py +1429 -0
- alysis_code/tools/web_search_tavily.py +194 -0
- alysis_code/updates.py +933 -0
- alysis_code/usage_tracker.py +1990 -0
- alysis_code/verification_command_analysis.py +1004 -0
- alysis_code/verification_contract.py +574 -0
- alysis_code/verification_failure_summary.py +273 -0
- alysis_code/verification_repair.py +385 -0
- alysis_code/verify_gate.py +3129 -0
- alysis_code/web_research.py +1872 -0
- alysis_code/web_search_adapters.py +66 -0
- alysis_code/web_search_policy.py +27 -0
- alysis_code/workspace_binding.py +389 -0
- alysis_code/workspace_binding_ui.py +408 -0
- alysis_code/workspace_context.py +273 -0
- alysis_code/workspace_isolation.py +138 -0
- alysis_code/workspace_provisioning.py +455 -0
- alysis_code-0.13.0.dist-info/METADATA +507 -0
- alysis_code-0.13.0.dist-info/RECORD +458 -0
- alysis_code-0.13.0.dist-info/WHEEL +4 -0
- alysis_code-0.13.0.dist-info/entry_points.txt +3 -0
- alysis_code-0.13.0.dist-info/licenses/LICENSE +176 -0
- alysis_code-0.13.0.dist-info/licenses/NOTICE +4 -0
|
@@ -0,0 +1,1834 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass, field
|
|
4
|
+
from urllib.parse import urlsplit
|
|
5
|
+
|
|
6
|
+
from .llm.cache_capabilities import (
|
|
7
|
+
CACHE_STRATEGY_ANTHROPIC_CACHE_CONTROL,
|
|
8
|
+
CACHE_STRATEGY_GEMINI_EXPLICIT_CACHED_CONTENT,
|
|
9
|
+
CACHE_STRATEGY_IMPLICIT_PROVIDER,
|
|
10
|
+
CACHE_STRATEGY_MISTRAL_PROMPT_CACHE_KEY,
|
|
11
|
+
CACHE_STRATEGY_OPENAI_PROMPT_CACHE,
|
|
12
|
+
CACHE_STRATEGY_OPENROUTER_STICKY_SESSION,
|
|
13
|
+
CACHE_STRATEGY_QWEN_CACHE_CONTROL_BLOCKS,
|
|
14
|
+
CACHE_STRATEGY_XAI_CONVERSATION_HEADER,
|
|
15
|
+
CACHE_USAGE_SCHEMA_ANTHROPIC,
|
|
16
|
+
CACHE_USAGE_SCHEMA_GEMINI,
|
|
17
|
+
CACHE_USAGE_SCHEMA_OPENAI,
|
|
18
|
+
CACHE_USAGE_SCHEMA_PROVIDER,
|
|
19
|
+
OPENROUTER_SESSION_ID_FIELD,
|
|
20
|
+
XAI_CONVERSATION_ID_HEADER_FIELD,
|
|
21
|
+
CacheCapabilitySpec,
|
|
22
|
+
)
|
|
23
|
+
from .llm.protocols import (
|
|
24
|
+
ANTHROPIC_MESSAGES_PROTOCOL,
|
|
25
|
+
GEMINI_GENERATE_CONTENT_PROTOCOL,
|
|
26
|
+
GEMINI_INTERACTIONS_PROTOCOL,
|
|
27
|
+
OPENAI_COMPAT_PROTOCOL,
|
|
28
|
+
OPENAI_RESPONSES_PROTOCOL,
|
|
29
|
+
)
|
|
30
|
+
from .profiles import ProfileSpec
|
|
31
|
+
from .web_search_adapters import (
|
|
32
|
+
ANTHROPIC_MESSAGES_ADAPTER,
|
|
33
|
+
AUTO_WEB_SEARCH_ADAPTER,
|
|
34
|
+
COHERE_WEB_SEARCH_ADAPTER,
|
|
35
|
+
DASHSCOPE_CHAT_ADAPTER,
|
|
36
|
+
GEMINI_GROUNDING_ADAPTER,
|
|
37
|
+
GROQ_COMPOUND_ADAPTER,
|
|
38
|
+
MINIMAX_CODING_PLAN_ADAPTER,
|
|
39
|
+
MISTRAL_CONVERSATIONS_ADAPTER,
|
|
40
|
+
MOONSHOT_KIMI_ADAPTER,
|
|
41
|
+
OPENAI_RESPONSES_ADAPTER,
|
|
42
|
+
OPENROUTER_WEB_ADAPTER,
|
|
43
|
+
PERPLEXITY_SONAR_ADAPTER,
|
|
44
|
+
VOLCENGINE_WEB_SEARCH_ADAPTER,
|
|
45
|
+
XAI_RESPONSES_ADAPTER,
|
|
46
|
+
ZHIPU_WEB_SEARCH_ADAPTER,
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
NATIVE_PROFILE_PROTOCOLS: frozenset[str] = frozenset(
|
|
50
|
+
{
|
|
51
|
+
OPENAI_RESPONSES_PROTOCOL,
|
|
52
|
+
ANTHROPIC_MESSAGES_PROTOCOL,
|
|
53
|
+
GEMINI_GENERATE_CONTENT_PROTOCOL,
|
|
54
|
+
GEMINI_INTERACTIONS_PROTOCOL,
|
|
55
|
+
}
|
|
56
|
+
)
|
|
57
|
+
FIRST_PARTY_NATIVE_PRESET_KEYS: tuple[str, ...] = (
|
|
58
|
+
"openai-responses",
|
|
59
|
+
"anthropic",
|
|
60
|
+
"gemini",
|
|
61
|
+
)
|
|
62
|
+
FIRST_CLASS_SETUP_PRESET_KEYS: tuple[str, ...] = (
|
|
63
|
+
# "alysis" (hosted MiMo) deliberately absent: while no campaign is
|
|
64
|
+
# running it stays off the primary picker entirely (advanced picker only).
|
|
65
|
+
*FIRST_PARTY_NATIVE_PRESET_KEYS,
|
|
66
|
+
)
|
|
67
|
+
FIRST_PARTY_COMPATIBILITY_PRESET_KEYS: tuple[str, ...] = (
|
|
68
|
+
"openai",
|
|
69
|
+
"anthropic-compat",
|
|
70
|
+
"gemini-compat",
|
|
71
|
+
)
|
|
72
|
+
LEGACY_NATIVE_ALIAS_PRESET_KEYS: tuple[str, ...] = ("anthropic-native", "gemini-native")
|
|
73
|
+
LOCAL_PROFILE_PRESET_KEYS: tuple[str, ...] = ("ollama", "lm-studio", "vllm")
|
|
74
|
+
_CUSTOM_PRESET_KEY = "custom"
|
|
75
|
+
# Account-gated hosted presets (`alysis login`, no API key). Kept off the
|
|
76
|
+
# primary provider picker while no hosted campaign is running.
|
|
77
|
+
_ACCOUNT_GATED_PRESET_KEYS: tuple[str, ...] = ("alysis",)
|
|
78
|
+
_CONVERSION_PRESET_BY_FAMILY: dict[str, dict[str, str]] = {
|
|
79
|
+
"openai": {"native": "openai-responses", "compatibility": "openai"},
|
|
80
|
+
"anthropic": {"native": "anthropic", "compatibility": "anthropic-compat"},
|
|
81
|
+
"gemini": {"native": "gemini", "compatibility": "gemini-compat"},
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
@dataclass(frozen=True)
|
|
86
|
+
class ProfilePreset:
|
|
87
|
+
key: str
|
|
88
|
+
label: str
|
|
89
|
+
protocol: str
|
|
90
|
+
base_url: str
|
|
91
|
+
api_key_env: str | None
|
|
92
|
+
extra_headers: dict[str, str] = field(default_factory=dict)
|
|
93
|
+
suggested_models: tuple[str, ...] = ()
|
|
94
|
+
suggested_model_descriptions: dict[str, str] = field(default_factory=dict)
|
|
95
|
+
model_aliases: dict[str, str] = field(default_factory=dict)
|
|
96
|
+
validation_model: str = ""
|
|
97
|
+
web_search_adapter: str = AUTO_WEB_SEARCH_ADAPTER
|
|
98
|
+
web_search_model: str = ""
|
|
99
|
+
setup_warning: str = ""
|
|
100
|
+
notes: str = ""
|
|
101
|
+
cache_capability: CacheCapabilitySpec | None = None
|
|
102
|
+
# Keep new optional fields at the end so extensions using the legacy
|
|
103
|
+
# positional constructor continue to bind the sixth argument to headers.
|
|
104
|
+
provider_key: str = ""
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
_OPENAI_PROMPT_CACHE_CAPABILITY = CacheCapabilitySpec(
|
|
108
|
+
strategy=CACHE_STRATEGY_OPENAI_PROMPT_CACHE,
|
|
109
|
+
enabled=True,
|
|
110
|
+
supports_prompt_cache_key=True,
|
|
111
|
+
supports_prompt_cache_retention=True,
|
|
112
|
+
reports_cache_read_tokens=True,
|
|
113
|
+
reports_cache_write_tokens=True,
|
|
114
|
+
usage_schema=CACHE_USAGE_SCHEMA_OPENAI,
|
|
115
|
+
min_cacheable_tokens=1024,
|
|
116
|
+
source="preset",
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def _cache_minimum(tokens: int) -> CacheCapabilitySpec:
|
|
121
|
+
"""A scoped override that only narrows the minimum cacheable prefix."""
|
|
122
|
+
|
|
123
|
+
return CacheCapabilitySpec(min_cacheable_tokens=tokens, source="preset")
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
# Anthropic's minimum cacheable prefix is per-model and does not move
|
|
127
|
+
# monotonically with the version number: the 5-generation flagships halved the
|
|
128
|
+
# floor to 512 while Opus 4.6/4.5 and Haiku 4.5 still need 4096. A prefix under
|
|
129
|
+
# the floor is silently not cached, so the write premium buys nothing — the
|
|
130
|
+
# floor is what makes the request-shape report say so instead of guessing.
|
|
131
|
+
_ANTHROPIC_CACHE_CONTROL_CAPABILITY = CacheCapabilitySpec(
|
|
132
|
+
strategy=CACHE_STRATEGY_ANTHROPIC_CACHE_CONTROL,
|
|
133
|
+
enabled=True,
|
|
134
|
+
supports_cache_control=True,
|
|
135
|
+
reports_cache_read_tokens=True,
|
|
136
|
+
reports_cache_write_tokens=True,
|
|
137
|
+
usage_schema=CACHE_USAGE_SCHEMA_ANTHROPIC,
|
|
138
|
+
min_cacheable_tokens=1024,
|
|
139
|
+
model_family_overrides=(
|
|
140
|
+
("claude-opus-5", _cache_minimum(512)),
|
|
141
|
+
("claude-fable-5", _cache_minimum(512)),
|
|
142
|
+
("claude-mythos-5", _cache_minimum(512)),
|
|
143
|
+
("claude-mythos-preview", _cache_minimum(2048)),
|
|
144
|
+
("claude-opus-4-7", _cache_minimum(2048)),
|
|
145
|
+
("claude-opus-4-6", _cache_minimum(4096)),
|
|
146
|
+
("claude-opus-4-5", _cache_minimum(4096)),
|
|
147
|
+
("claude-haiku-4-5", _cache_minimum(4096)),
|
|
148
|
+
),
|
|
149
|
+
source="preset",
|
|
150
|
+
)
|
|
151
|
+
_GEMINI_EXPLICIT_CACHED_CONTENT_CAPABILITY = CacheCapabilitySpec(
|
|
152
|
+
strategy=CACHE_STRATEGY_GEMINI_EXPLICIT_CACHED_CONTENT,
|
|
153
|
+
enabled=True,
|
|
154
|
+
supports_explicit_cached_content=True,
|
|
155
|
+
reports_cache_read_tokens=True,
|
|
156
|
+
usage_schema=CACHE_USAGE_SCHEMA_GEMINI,
|
|
157
|
+
min_cacheable_tokens=4096,
|
|
158
|
+
source="preset",
|
|
159
|
+
)
|
|
160
|
+
_MISTRAL_PROMPT_CACHE_CAPABILITY = CacheCapabilitySpec(
|
|
161
|
+
strategy=CACHE_STRATEGY_MISTRAL_PROMPT_CACHE_KEY,
|
|
162
|
+
enabled=True,
|
|
163
|
+
supports_prompt_cache_key=True,
|
|
164
|
+
reports_cache_read_tokens=True,
|
|
165
|
+
usage_schema=CACHE_USAGE_SCHEMA_OPENAI,
|
|
166
|
+
min_cacheable_tokens=1024,
|
|
167
|
+
emits_request_fields=True,
|
|
168
|
+
notes=("Emits Mistral prompt_cache_key for stable server routing and prompt-cache hits.",),
|
|
169
|
+
source="preset",
|
|
170
|
+
)
|
|
171
|
+
_OPENROUTER_STICKY_SESSION_CACHE_CAPABILITY = CacheCapabilitySpec(
|
|
172
|
+
strategy=CACHE_STRATEGY_OPENROUTER_STICKY_SESSION,
|
|
173
|
+
enabled=True,
|
|
174
|
+
reports_cache_read_tokens=True,
|
|
175
|
+
reports_cache_write_tokens=True,
|
|
176
|
+
usage_schema=CACHE_USAGE_SCHEMA_PROVIDER,
|
|
177
|
+
emits_request_fields=True,
|
|
178
|
+
request_fields=(OPENROUTER_SESSION_ID_FIELD,),
|
|
179
|
+
notes=(
|
|
180
|
+
"Emits OpenRouter session_id for sticky routing; upstream cache semantics remain "
|
|
181
|
+
"route-dependent.",
|
|
182
|
+
),
|
|
183
|
+
source="preset",
|
|
184
|
+
)
|
|
185
|
+
_XAI_CONVERSATION_HEADER_CACHE_CAPABILITY = CacheCapabilitySpec(
|
|
186
|
+
strategy=CACHE_STRATEGY_XAI_CONVERSATION_HEADER,
|
|
187
|
+
enabled=True,
|
|
188
|
+
reports_cache_read_tokens=True,
|
|
189
|
+
usage_schema=CACHE_USAGE_SCHEMA_PROVIDER,
|
|
190
|
+
emits_request_fields=True,
|
|
191
|
+
request_fields=(XAI_CONVERSATION_ID_HEADER_FIELD,),
|
|
192
|
+
notes=("Emits x-grok-conv-id for sticky cache routing on xAI Chat Completions.",),
|
|
193
|
+
source="preset",
|
|
194
|
+
)
|
|
195
|
+
_QWEN_DIAGNOSTIC_CACHE_CAPABILITY = CacheCapabilitySpec(
|
|
196
|
+
strategy=CACHE_STRATEGY_QWEN_CACHE_CONTROL_BLOCKS,
|
|
197
|
+
enabled=True,
|
|
198
|
+
reports_cache_read_tokens=True,
|
|
199
|
+
reports_cache_write_tokens=True,
|
|
200
|
+
usage_schema=CACHE_USAGE_SCHEMA_PROVIDER,
|
|
201
|
+
min_cacheable_tokens=1024,
|
|
202
|
+
emits_request_fields=False,
|
|
203
|
+
notes=(
|
|
204
|
+
"Diagnostic-only in auto mode; Qwen cache_control content markers mutate "
|
|
205
|
+
"message shape and require request-shape gating.",
|
|
206
|
+
),
|
|
207
|
+
source="preset",
|
|
208
|
+
)
|
|
209
|
+
_MOONSHOT_AUTOMATIC_CACHE_CAPABILITY = CacheCapabilitySpec(
|
|
210
|
+
strategy=CACHE_STRATEGY_IMPLICIT_PROVIDER,
|
|
211
|
+
enabled=True,
|
|
212
|
+
supports_prompt_cache_key=True,
|
|
213
|
+
reports_cache_read_tokens=True,
|
|
214
|
+
usage_schema=CACHE_USAGE_SCHEMA_PROVIDER,
|
|
215
|
+
emits_request_fields=True,
|
|
216
|
+
notes=(
|
|
217
|
+
"Moonshot caches matching prompt prefixes automatically; prompt_cache_key keeps a "
|
|
218
|
+
"session on a stable cache-affinity route.",
|
|
219
|
+
),
|
|
220
|
+
source="preset",
|
|
221
|
+
)
|
|
222
|
+
_ZAI_CODING_PLAN_CACHE_CAPABILITY = CacheCapabilitySpec(
|
|
223
|
+
strategy=CACHE_STRATEGY_IMPLICIT_PROVIDER,
|
|
224
|
+
enabled=True,
|
|
225
|
+
reports_cache_read_tokens=True,
|
|
226
|
+
usage_schema=CACHE_USAGE_SCHEMA_PROVIDER,
|
|
227
|
+
emits_request_fields=False,
|
|
228
|
+
notes=(
|
|
229
|
+
"Z.AI Coding Plan caches matching prompt prefixes automatically and reports "
|
|
230
|
+
"cached-input usage; Alysis Code emits no provider-specific cache fields.",
|
|
231
|
+
),
|
|
232
|
+
source="preset",
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
def preset_protocol_kind(preset: ProfilePreset) -> str:
|
|
237
|
+
return "native" if preset.protocol in NATIVE_PROFILE_PROTOCOLS else "compatibility"
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
def preset_protocol_summary(preset: ProfilePreset) -> str:
|
|
241
|
+
if preset.protocol in NATIVE_PROFILE_PROTOCOLS:
|
|
242
|
+
return (
|
|
243
|
+
f"Native first-party protocol: {preset.protocol} (recommended for first-party API keys)"
|
|
244
|
+
)
|
|
245
|
+
return "Compatibility protocol: OpenAI-compatible chat transport"
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
def preset_selection_label(preset: ProfilePreset) -> str:
|
|
249
|
+
"""Return a setup/config label that keeps protocol details out of the primary choice."""
|
|
250
|
+
if preset.key == "alysis":
|
|
251
|
+
return "Alysis Code Pro (hosted models) - requires login"
|
|
252
|
+
if preset.key == "openai-responses":
|
|
253
|
+
return "OpenAI - Native Responses"
|
|
254
|
+
if preset.key in {"anthropic", "anthropic-native"}:
|
|
255
|
+
return "Anthropic Claude - Native Messages"
|
|
256
|
+
if preset.key in {"gemini", "gemini-native"}:
|
|
257
|
+
return "Google Gemini - Native GenerateContent"
|
|
258
|
+
if preset.key == "openai":
|
|
259
|
+
return "OpenAI - Compatibility/gateway Chat Completions"
|
|
260
|
+
if preset.key == "anthropic-compat":
|
|
261
|
+
return "Anthropic Claude compatibility - legacy OpenAI-compatible"
|
|
262
|
+
if preset.key == "gemini-compat":
|
|
263
|
+
return "Google Gemini compatibility - legacy OpenAI-compatible"
|
|
264
|
+
if preset.key in LOCAL_PROFILE_PRESET_KEYS:
|
|
265
|
+
return f"{preset.label} - Local endpoint"
|
|
266
|
+
if preset.key == "custom":
|
|
267
|
+
return "Custom OpenAI-compatible endpoint"
|
|
268
|
+
return preset.label
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
def _advanced_only_preset_keys() -> frozenset[str]:
|
|
272
|
+
"""Preset keys deliberately kept off the primary provider picker.
|
|
273
|
+
|
|
274
|
+
Everything else in :data:`PROFILE_PRESETS` is a real hosted provider — the
|
|
275
|
+
native first-party APIs *and* the third-party API/gateway endpoints — and is
|
|
276
|
+
surfaced directly so users are not limited to the big-three brands. Only the
|
|
277
|
+
OpenAI-compatible duplicates of the native first-party providers, local
|
|
278
|
+
endpoints (Ollama/LM Studio/vLLM), the manual custom-URL entry, the
|
|
279
|
+
one-release legacy aliases, and the account-gated hosted MiMo preset
|
|
280
|
+
(no hosted campaign is running, so it is not a provider choice) stay
|
|
281
|
+
behind the advanced picker.
|
|
282
|
+
"""
|
|
283
|
+
return frozenset(
|
|
284
|
+
{
|
|
285
|
+
_CUSTOM_PRESET_KEY,
|
|
286
|
+
*FIRST_PARTY_COMPATIBILITY_PRESET_KEYS,
|
|
287
|
+
*LOCAL_PROFILE_PRESET_KEYS,
|
|
288
|
+
*LEGACY_NATIVE_ALIAS_PRESET_KEYS,
|
|
289
|
+
*_ACCOUNT_GATED_PRESET_KEYS,
|
|
290
|
+
}
|
|
291
|
+
)
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
def provider_selection_presets() -> list[ProfilePreset]:
|
|
295
|
+
"""Presets shown directly on the primary provider picker.
|
|
296
|
+
|
|
297
|
+
Native first-party providers lead — the best defaults for new users —
|
|
298
|
+
followed by every other hosted provider in registration order.
|
|
299
|
+
Compatibility duplicates, local endpoints, the custom-URL entry,
|
|
300
|
+
one-release legacy aliases, and the account-gated hosted MiMo preset are
|
|
301
|
+
the only presets held back for the advanced picker, so the user sees the
|
|
302
|
+
full range of hosted providers up front instead of just
|
|
303
|
+
OpenAI/Anthropic/Gemini.
|
|
304
|
+
"""
|
|
305
|
+
by_key = PRESET_BY_KEY
|
|
306
|
+
advanced = _advanced_only_preset_keys()
|
|
307
|
+
leading = [by_key[key] for key in FIRST_CLASS_SETUP_PRESET_KEYS if key in by_key]
|
|
308
|
+
leading_keys = {preset.key for preset in leading}
|
|
309
|
+
rest = [
|
|
310
|
+
preset
|
|
311
|
+
for preset in PROFILE_PRESETS
|
|
312
|
+
if preset.key not in advanced and preset.key not in leading_keys
|
|
313
|
+
]
|
|
314
|
+
return [*leading, *rest]
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
def advanced_provider_selection_presets() -> list[ProfilePreset]:
|
|
318
|
+
"""Return the compatibility, local, custom, legacy alias, and account-gated presets.
|
|
319
|
+
|
|
320
|
+
These are exactly the presets held off the primary provider picker: the
|
|
321
|
+
OpenAI-compatible duplicates of the native first-party providers, local
|
|
322
|
+
endpoints (Ollama/LM Studio/vLLM), the manual custom-URL entry, the
|
|
323
|
+
one-release legacy aliases, and the account-gated hosted MiMo preset.
|
|
324
|
+
"""
|
|
325
|
+
by_key = PRESET_BY_KEY
|
|
326
|
+
first_party_compat = [
|
|
327
|
+
by_key[key] for key in FIRST_PARTY_COMPATIBILITY_PRESET_KEYS if key in by_key
|
|
328
|
+
]
|
|
329
|
+
local = [by_key[key] for key in LOCAL_PROFILE_PRESET_KEYS if key in by_key]
|
|
330
|
+
custom = [by_key[_CUSTOM_PRESET_KEY]] if _CUSTOM_PRESET_KEY in by_key else []
|
|
331
|
+
aliases = [by_key[key] for key in LEGACY_NATIVE_ALIAS_PRESET_KEYS if key in by_key]
|
|
332
|
+
account_gated = [by_key[key] for key in _ACCOUNT_GATED_PRESET_KEYS if key in by_key]
|
|
333
|
+
return [*first_party_compat, *local, *custom, *aliases, *account_gated]
|
|
334
|
+
|
|
335
|
+
|
|
336
|
+
PROFILE_PRESETS: tuple[ProfilePreset, ...] = (
|
|
337
|
+
ProfilePreset(
|
|
338
|
+
key="openai",
|
|
339
|
+
provider_key="openai",
|
|
340
|
+
label="OpenAI",
|
|
341
|
+
protocol="openai_compat",
|
|
342
|
+
base_url="https://api.openai.com/v1",
|
|
343
|
+
api_key_env="OPENAI_API_KEY",
|
|
344
|
+
suggested_models=(
|
|
345
|
+
"gpt-5.6-terra",
|
|
346
|
+
"gpt-5.6-sol",
|
|
347
|
+
"gpt-5.6-luna",
|
|
348
|
+
"gpt-5.3-codex",
|
|
349
|
+
"gpt-5.4-mini",
|
|
350
|
+
"gpt-5.4-nano",
|
|
351
|
+
),
|
|
352
|
+
suggested_model_descriptions={
|
|
353
|
+
"gpt-5.6-terra": "default - balanced 5.6 tier, 1.05M context",
|
|
354
|
+
"gpt-5.6-sol": "advanced - flagship 5.6 tier, 1.05M context",
|
|
355
|
+
"gpt-5.6-luna": "fast - low-cost 5.6 tier, full 1.05M context",
|
|
356
|
+
"gpt-5.3-codex": "coding - agentic codex model, 400K context",
|
|
357
|
+
"gpt-5.4-mini": "fallback - cheap tier for subagents, 400K",
|
|
358
|
+
"gpt-5.4-nano": "economy - cheapest live id, 400K context",
|
|
359
|
+
},
|
|
360
|
+
model_aliases={
|
|
361
|
+
"gpt-5.6": "gpt-5.6-sol",
|
|
362
|
+
"gpt-5-nano": "gpt-5.4-nano",
|
|
363
|
+
# 2026-07-23 shutdowns from OpenAI's deprecations page: codex and
|
|
364
|
+
# chat-latest ids remap to the still-callable gpt-5.5 tier.
|
|
365
|
+
"gpt-5-codex": "gpt-5.5",
|
|
366
|
+
"gpt-5.1-codex": "gpt-5.5",
|
|
367
|
+
"gpt-5.1-codex-max": "gpt-5.5",
|
|
368
|
+
"gpt-5.2-codex": "gpt-5.5",
|
|
369
|
+
"gpt-5.1-codex-mini": "gpt-5.4-mini",
|
|
370
|
+
"gpt-5-chat-latest": "gpt-5.5",
|
|
371
|
+
"gpt-5.1-chat-latest": "gpt-5.5",
|
|
372
|
+
},
|
|
373
|
+
validation_model="gpt-5.4-nano",
|
|
374
|
+
web_search_adapter=OPENAI_RESPONSES_ADAPTER,
|
|
375
|
+
cache_capability=_OPENAI_PROMPT_CACHE_CAPABILITY,
|
|
376
|
+
setup_warning=(
|
|
377
|
+
"gpt-5.6/5.4 reject tool calls with reasoning_effort other than "
|
|
378
|
+
"'none' on Chat Completions (and 5.6 defaults to 'medium') — for "
|
|
379
|
+
"agentic runs use the OpenAI Responses preset, or pin effort to "
|
|
380
|
+
"'none' here."
|
|
381
|
+
),
|
|
382
|
+
),
|
|
383
|
+
ProfilePreset(
|
|
384
|
+
key="openai-responses",
|
|
385
|
+
provider_key="openai",
|
|
386
|
+
label="OpenAI Responses",
|
|
387
|
+
protocol="openai_responses",
|
|
388
|
+
base_url="https://api.openai.com/v1",
|
|
389
|
+
api_key_env="OPENAI_API_KEY",
|
|
390
|
+
suggested_models=(
|
|
391
|
+
"gpt-5.6-terra",
|
|
392
|
+
"gpt-5.6-sol",
|
|
393
|
+
"gpt-5.6-luna",
|
|
394
|
+
"gpt-5.3-codex",
|
|
395
|
+
"gpt-5.4-mini",
|
|
396
|
+
"gpt-5.4-nano",
|
|
397
|
+
),
|
|
398
|
+
suggested_model_descriptions={
|
|
399
|
+
"gpt-5.6-terra": "default - balanced 5.6 tier, 1.05M context",
|
|
400
|
+
"gpt-5.6-sol": "advanced - flagship 5.6 tier, 1.05M context",
|
|
401
|
+
"gpt-5.6-luna": "fast - low-cost 5.6 tier, full 1.05M context",
|
|
402
|
+
"gpt-5.3-codex": "coding - agentic codex model, 400K context",
|
|
403
|
+
"gpt-5.4-mini": "fallback - cheap tier for subagents, 400K",
|
|
404
|
+
"gpt-5.4-nano": "economy - cheapest live id, 400K context",
|
|
405
|
+
},
|
|
406
|
+
model_aliases={
|
|
407
|
+
"gpt-5.6": "gpt-5.6-sol",
|
|
408
|
+
"gpt-5-nano": "gpt-5.4-nano",
|
|
409
|
+
# 2026-07-23 shutdowns from OpenAI's deprecations page: codex and
|
|
410
|
+
# chat-latest ids remap to the still-callable gpt-5.5 tier.
|
|
411
|
+
"gpt-5-codex": "gpt-5.5",
|
|
412
|
+
"gpt-5.1-codex": "gpt-5.5",
|
|
413
|
+
"gpt-5.1-codex-max": "gpt-5.5",
|
|
414
|
+
"gpt-5.2-codex": "gpt-5.5",
|
|
415
|
+
"gpt-5.1-codex-mini": "gpt-5.4-mini",
|
|
416
|
+
"gpt-5-chat-latest": "gpt-5.5",
|
|
417
|
+
"gpt-5.1-chat-latest": "gpt-5.5",
|
|
418
|
+
},
|
|
419
|
+
validation_model="gpt-5.4-nano",
|
|
420
|
+
web_search_adapter=OPENAI_RESPONSES_ADAPTER,
|
|
421
|
+
cache_capability=_OPENAI_PROMPT_CACHE_CAPABILITY,
|
|
422
|
+
notes=(
|
|
423
|
+
"Native OpenAI Responses API chat with SSE streaming support. Use the OpenAI compat "
|
|
424
|
+
"preset to keep Chat Completions-compatible behavior."
|
|
425
|
+
),
|
|
426
|
+
),
|
|
427
|
+
ProfilePreset(
|
|
428
|
+
key="anthropic",
|
|
429
|
+
provider_key="anthropic",
|
|
430
|
+
label="Anthropic Claude",
|
|
431
|
+
protocol="anthropic_messages",
|
|
432
|
+
base_url="https://api.anthropic.com/v1",
|
|
433
|
+
api_key_env="ANTHROPIC_API_KEY",
|
|
434
|
+
suggested_models=(
|
|
435
|
+
"claude-sonnet-5",
|
|
436
|
+
"claude-opus-5",
|
|
437
|
+
"claude-fable-5",
|
|
438
|
+
"claude-haiku-4-5",
|
|
439
|
+
"claude-opus-4-8",
|
|
440
|
+
"claude-opus-4-7",
|
|
441
|
+
),
|
|
442
|
+
suggested_model_descriptions={
|
|
443
|
+
"claude-sonnet-5": "default - 1M context, best speed/intelligence mix",
|
|
444
|
+
"claude-opus-5": "advanced - agentic coding + deep reasoning, 1M ctx",
|
|
445
|
+
"claude-fable-5": "reasoning - adaptive thinking always on, 1M ctx",
|
|
446
|
+
"claude-haiku-4-5": "fast - 200K context, lowest cost tier",
|
|
447
|
+
"claude-opus-4-8": "fallback - previous-generation opus, 1M context",
|
|
448
|
+
"claude-opus-4-7": "legacy - prior opus generation, 1M context",
|
|
449
|
+
},
|
|
450
|
+
model_aliases={
|
|
451
|
+
# claude-sonnet-4-6 moved to Anthropic's Legacy table; Sonnet 5 is
|
|
452
|
+
# newer and cheaper. Retired haiku ids remap to the 4.5 bare alias.
|
|
453
|
+
"claude-sonnet-4": "claude-sonnet-5",
|
|
454
|
+
"claude-sonnet-4-5": "claude-sonnet-5",
|
|
455
|
+
"claude-sonnet-4-6": "claude-sonnet-5",
|
|
456
|
+
"claude-4-sonnet": "claude-sonnet-5",
|
|
457
|
+
"claude-3-5-haiku-latest": "claude-haiku-4-5",
|
|
458
|
+
"claude-3-5-haiku-20241022": "claude-haiku-4-5",
|
|
459
|
+
"claude-opus-4.8": "claude-opus-4-8",
|
|
460
|
+
"claude-opus-4.7": "claude-opus-4-7",
|
|
461
|
+
"claude-opus-4-1": "claude-opus-4-8",
|
|
462
|
+
"claude-opus-4-6": "claude-opus-4-8",
|
|
463
|
+
},
|
|
464
|
+
validation_model="claude-haiku-4-5",
|
|
465
|
+
web_search_adapter=ANTHROPIC_MESSAGES_ADAPTER,
|
|
466
|
+
cache_capability=_ANTHROPIC_CACHE_CONTROL_CAPABILITY,
|
|
467
|
+
notes=(
|
|
468
|
+
"Native Anthropic Messages API chat with SSE streaming support. Compatibility mode "
|
|
469
|
+
"remains available as anthropic-compat for legacy OpenAI-compatible fallback."
|
|
470
|
+
),
|
|
471
|
+
),
|
|
472
|
+
ProfilePreset(
|
|
473
|
+
key="anthropic-compat",
|
|
474
|
+
provider_key="anthropic",
|
|
475
|
+
label="Anthropic Claude compatibility",
|
|
476
|
+
protocol="openai_compat",
|
|
477
|
+
base_url="https://api.anthropic.com/v1/",
|
|
478
|
+
api_key_env="ANTHROPIC_API_KEY",
|
|
479
|
+
suggested_models=(
|
|
480
|
+
"claude-sonnet-5",
|
|
481
|
+
"claude-opus-5",
|
|
482
|
+
"claude-fable-5",
|
|
483
|
+
"claude-haiku-4-5",
|
|
484
|
+
"claude-opus-4-8",
|
|
485
|
+
"claude-opus-4-7",
|
|
486
|
+
),
|
|
487
|
+
suggested_model_descriptions={
|
|
488
|
+
"claude-sonnet-5": "default - 1M context, best speed/intelligence mix",
|
|
489
|
+
"claude-opus-5": "advanced - agentic coding + deep reasoning, 1M ctx",
|
|
490
|
+
"claude-fable-5": "reasoning - adaptive thinking always on, 1M ctx",
|
|
491
|
+
"claude-haiku-4-5": "fast - 200K context, lowest cost tier",
|
|
492
|
+
"claude-opus-4-8": "fallback - previous-generation opus, 1M context",
|
|
493
|
+
"claude-opus-4-7": "legacy - prior opus generation, 1M context",
|
|
494
|
+
},
|
|
495
|
+
model_aliases={
|
|
496
|
+
# claude-sonnet-4-6 moved to Anthropic's Legacy table; Sonnet 5 is
|
|
497
|
+
# newer and cheaper. Retired haiku ids remap to the 4.5 bare alias.
|
|
498
|
+
"claude-sonnet-4": "claude-sonnet-5",
|
|
499
|
+
"claude-sonnet-4-5": "claude-sonnet-5",
|
|
500
|
+
"claude-sonnet-4-6": "claude-sonnet-5",
|
|
501
|
+
"claude-4-sonnet": "claude-sonnet-5",
|
|
502
|
+
"claude-3-5-haiku-latest": "claude-haiku-4-5",
|
|
503
|
+
"claude-3-5-haiku-20241022": "claude-haiku-4-5",
|
|
504
|
+
"claude-opus-4.8": "claude-opus-4-8",
|
|
505
|
+
"claude-opus-4.7": "claude-opus-4-7",
|
|
506
|
+
"claude-opus-4-1": "claude-opus-4-8",
|
|
507
|
+
"claude-opus-4-6": "claude-opus-4-8",
|
|
508
|
+
},
|
|
509
|
+
validation_model="claude-haiku-4-5",
|
|
510
|
+
web_search_adapter=ANTHROPIC_MESSAGES_ADAPTER,
|
|
511
|
+
setup_warning=(
|
|
512
|
+
"Anthropic labels the OpenAI SDK compatibility layer as a test path; "
|
|
513
|
+
"use the anthropic preset for native Messages API behavior."
|
|
514
|
+
),
|
|
515
|
+
notes=(
|
|
516
|
+
"Chat uses Anthropic OpenAI-compat at /v1; web_search uses the native "
|
|
517
|
+
"Anthropic Messages web_search adapter when the model/account supports it."
|
|
518
|
+
),
|
|
519
|
+
),
|
|
520
|
+
ProfilePreset(
|
|
521
|
+
key="anthropic-native",
|
|
522
|
+
provider_key="anthropic",
|
|
523
|
+
label="Anthropic Claude (native alias)",
|
|
524
|
+
protocol="anthropic_messages",
|
|
525
|
+
base_url="https://api.anthropic.com/v1",
|
|
526
|
+
api_key_env="ANTHROPIC_API_KEY",
|
|
527
|
+
suggested_models=(
|
|
528
|
+
"claude-sonnet-5",
|
|
529
|
+
"claude-opus-5",
|
|
530
|
+
"claude-fable-5",
|
|
531
|
+
"claude-haiku-4-5",
|
|
532
|
+
"claude-opus-4-8",
|
|
533
|
+
"claude-opus-4-7",
|
|
534
|
+
),
|
|
535
|
+
suggested_model_descriptions={
|
|
536
|
+
"claude-sonnet-5": "default - 1M context, best speed/intelligence mix",
|
|
537
|
+
"claude-opus-5": "advanced - agentic coding + deep reasoning, 1M ctx",
|
|
538
|
+
"claude-fable-5": "reasoning - adaptive thinking always on, 1M ctx",
|
|
539
|
+
"claude-haiku-4-5": "fast - 200K context, lowest cost tier",
|
|
540
|
+
"claude-opus-4-8": "fallback - previous-generation opus, 1M context",
|
|
541
|
+
"claude-opus-4-7": "legacy - prior opus generation, 1M context",
|
|
542
|
+
},
|
|
543
|
+
model_aliases={
|
|
544
|
+
# claude-sonnet-4-6 moved to Anthropic's Legacy table; Sonnet 5 is
|
|
545
|
+
# newer and cheaper. Retired haiku ids remap to the 4.5 bare alias.
|
|
546
|
+
"claude-sonnet-4": "claude-sonnet-5",
|
|
547
|
+
"claude-sonnet-4-5": "claude-sonnet-5",
|
|
548
|
+
"claude-sonnet-4-6": "claude-sonnet-5",
|
|
549
|
+
"claude-4-sonnet": "claude-sonnet-5",
|
|
550
|
+
"claude-3-5-haiku-latest": "claude-haiku-4-5",
|
|
551
|
+
"claude-3-5-haiku-20241022": "claude-haiku-4-5",
|
|
552
|
+
"claude-opus-4.8": "claude-opus-4-8",
|
|
553
|
+
"claude-opus-4.7": "claude-opus-4-7",
|
|
554
|
+
"claude-opus-4-1": "claude-opus-4-8",
|
|
555
|
+
"claude-opus-4-6": "claude-opus-4-8",
|
|
556
|
+
},
|
|
557
|
+
validation_model="claude-haiku-4-5",
|
|
558
|
+
web_search_adapter=ANTHROPIC_MESSAGES_ADAPTER,
|
|
559
|
+
cache_capability=_ANTHROPIC_CACHE_CONTROL_CAPABILITY,
|
|
560
|
+
notes=(
|
|
561
|
+
"Legacy alias for the native anthropic preset. Prefer the anthropic preset for new "
|
|
562
|
+
"first-party Claude profiles."
|
|
563
|
+
),
|
|
564
|
+
),
|
|
565
|
+
ProfilePreset(
|
|
566
|
+
key="gemini",
|
|
567
|
+
provider_key="gemini",
|
|
568
|
+
label="Google Gemini",
|
|
569
|
+
protocol="gemini_generate_content",
|
|
570
|
+
base_url="https://generativelanguage.googleapis.com/v1beta",
|
|
571
|
+
api_key_env="GEMINI_API_KEY",
|
|
572
|
+
suggested_models=(
|
|
573
|
+
"gemini-3.7-flash",
|
|
574
|
+
"gemini-3.6-flash",
|
|
575
|
+
"gemini-3.5-flash-lite",
|
|
576
|
+
"gemini-3.1-pro-preview",
|
|
577
|
+
),
|
|
578
|
+
suggested_model_descriptions={
|
|
579
|
+
"gemini-3.7-flash": "default - newest GA coding and agentic model, 1M",
|
|
580
|
+
"gemini-3.6-flash": "fallback - production GA flash model, 1M context",
|
|
581
|
+
"gemini-3.5-flash-lite": "economy - lowest-cost GA tier, 1M context",
|
|
582
|
+
"gemini-3.1-pro-preview": "advanced - pro reasoning preview, 1M context",
|
|
583
|
+
},
|
|
584
|
+
model_aliases={
|
|
585
|
+
# Only shut-down or invalid legacy ids are rewritten. Active stable
|
|
586
|
+
# ids and provider-managed *-latest aliases pass through unchanged.
|
|
587
|
+
"gemini-2.0-flash": "gemini-3.6-flash",
|
|
588
|
+
"gemini-2.0-flash-lite": "gemini-3.1-flash-lite",
|
|
589
|
+
"gemini-3.1-preview": "gemini-3.1-pro-preview",
|
|
590
|
+
"gemini-3-pro-preview": "gemini-3.1-pro-preview",
|
|
591
|
+
"gemini-3.1-flash-lite-preview": "gemini-3.1-flash-lite",
|
|
592
|
+
},
|
|
593
|
+
validation_model="gemini-3.5-flash-lite",
|
|
594
|
+
web_search_adapter=GEMINI_GROUNDING_ADAPTER,
|
|
595
|
+
cache_capability=_GEMINI_EXPLICIT_CACHED_CONTENT_CAPABILITY,
|
|
596
|
+
setup_warning=(
|
|
597
|
+
"Gemini native GenerateContent uses the Google Gemini API v1beta surface and "
|
|
598
|
+
"model availability can vary by account, region, and provider rollout."
|
|
599
|
+
),
|
|
600
|
+
notes=(
|
|
601
|
+
"Native Gemini GenerateContent API chat with streamGenerateContent SSE support. "
|
|
602
|
+
"Compatibility mode remains available as gemini-compat for legacy OpenAI-compatible "
|
|
603
|
+
"fallback."
|
|
604
|
+
),
|
|
605
|
+
),
|
|
606
|
+
ProfilePreset(
|
|
607
|
+
key="gemini-compat",
|
|
608
|
+
provider_key="gemini",
|
|
609
|
+
label="Google Gemini compatibility",
|
|
610
|
+
protocol="openai_compat",
|
|
611
|
+
base_url="https://generativelanguage.googleapis.com/v1beta/openai/",
|
|
612
|
+
api_key_env="GEMINI_API_KEY",
|
|
613
|
+
suggested_models=(
|
|
614
|
+
"gemini-3.7-flash",
|
|
615
|
+
"gemini-3.6-flash",
|
|
616
|
+
"gemini-3.5-flash-lite",
|
|
617
|
+
"gemini-3.1-pro-preview",
|
|
618
|
+
),
|
|
619
|
+
suggested_model_descriptions={
|
|
620
|
+
"gemini-3.7-flash": "default - newest GA coding and agentic model, 1M",
|
|
621
|
+
"gemini-3.6-flash": "fallback - production GA flash model, 1M context",
|
|
622
|
+
"gemini-3.5-flash-lite": "economy - lowest-cost GA tier, 1M context",
|
|
623
|
+
"gemini-3.1-pro-preview": "advanced - pro reasoning preview, 1M context",
|
|
624
|
+
},
|
|
625
|
+
model_aliases={
|
|
626
|
+
# Only shut-down or invalid legacy ids are rewritten. Active stable
|
|
627
|
+
# ids and provider-managed *-latest aliases pass through unchanged.
|
|
628
|
+
"gemini-2.0-flash": "gemini-3.6-flash",
|
|
629
|
+
"gemini-2.0-flash-lite": "gemini-3.1-flash-lite",
|
|
630
|
+
"gemini-3.1-preview": "gemini-3.1-pro-preview",
|
|
631
|
+
"gemini-3-pro-preview": "gemini-3.1-pro-preview",
|
|
632
|
+
"gemini-3.1-flash-lite-preview": "gemini-3.1-flash-lite",
|
|
633
|
+
},
|
|
634
|
+
validation_model="gemini-3.5-flash-lite",
|
|
635
|
+
web_search_adapter=GEMINI_GROUNDING_ADAPTER,
|
|
636
|
+
setup_warning=(
|
|
637
|
+
"Gemini OpenAI compatibility is served from v1beta; use the gemini preset for "
|
|
638
|
+
"native GenerateContent behavior."
|
|
639
|
+
),
|
|
640
|
+
),
|
|
641
|
+
ProfilePreset(
|
|
642
|
+
key="gemini-native",
|
|
643
|
+
provider_key="gemini",
|
|
644
|
+
label="Google Gemini (native alias)",
|
|
645
|
+
protocol="gemini_generate_content",
|
|
646
|
+
base_url="https://generativelanguage.googleapis.com/v1beta",
|
|
647
|
+
api_key_env="GEMINI_API_KEY",
|
|
648
|
+
suggested_models=(
|
|
649
|
+
"gemini-3.7-flash",
|
|
650
|
+
"gemini-3.6-flash",
|
|
651
|
+
"gemini-3.5-flash-lite",
|
|
652
|
+
"gemini-3.1-pro-preview",
|
|
653
|
+
),
|
|
654
|
+
suggested_model_descriptions={
|
|
655
|
+
"gemini-3.7-flash": "default - newest GA coding and agentic model, 1M",
|
|
656
|
+
"gemini-3.6-flash": "fallback - production GA flash model, 1M context",
|
|
657
|
+
"gemini-3.5-flash-lite": "economy - lowest-cost GA tier, 1M context",
|
|
658
|
+
"gemini-3.1-pro-preview": "advanced - pro reasoning preview, 1M context",
|
|
659
|
+
},
|
|
660
|
+
model_aliases={
|
|
661
|
+
# Only shut-down or invalid legacy ids are rewritten. Active stable
|
|
662
|
+
# ids and provider-managed *-latest aliases pass through unchanged.
|
|
663
|
+
"gemini-2.0-flash": "gemini-3.6-flash",
|
|
664
|
+
"gemini-2.0-flash-lite": "gemini-3.1-flash-lite",
|
|
665
|
+
"gemini-3.1-preview": "gemini-3.1-pro-preview",
|
|
666
|
+
"gemini-3-pro-preview": "gemini-3.1-pro-preview",
|
|
667
|
+
"gemini-3.1-flash-lite-preview": "gemini-3.1-flash-lite",
|
|
668
|
+
},
|
|
669
|
+
validation_model="gemini-3.5-flash-lite",
|
|
670
|
+
web_search_adapter=GEMINI_GROUNDING_ADAPTER,
|
|
671
|
+
cache_capability=_GEMINI_EXPLICIT_CACHED_CONTENT_CAPABILITY,
|
|
672
|
+
setup_warning=(
|
|
673
|
+
"Gemini native GenerateContent uses the Google Gemini API v1beta surface and "
|
|
674
|
+
"model availability can vary by account, region, and provider rollout."
|
|
675
|
+
),
|
|
676
|
+
notes=(
|
|
677
|
+
"Legacy alias for the native gemini preset. Prefer the gemini preset for new "
|
|
678
|
+
"first-party Gemini profiles."
|
|
679
|
+
),
|
|
680
|
+
),
|
|
681
|
+
ProfilePreset(
|
|
682
|
+
key="deepseek",
|
|
683
|
+
provider_key="deepseek",
|
|
684
|
+
label="DeepSeek",
|
|
685
|
+
protocol="openai_compat",
|
|
686
|
+
base_url="https://api.deepseek.com",
|
|
687
|
+
api_key_env="DEEPSEEK_API_KEY",
|
|
688
|
+
suggested_models=(
|
|
689
|
+
"deepseek-v4-pro",
|
|
690
|
+
"deepseek-v4-flash",
|
|
691
|
+
"deepseek-v4-flash-vision-exp",
|
|
692
|
+
),
|
|
693
|
+
suggested_model_descriptions={
|
|
694
|
+
"deepseek-v4-pro": "default - flagship coding model, 1M context",
|
|
695
|
+
"deepseek-v4-flash": "fast - cheap high-volume work, 1M context",
|
|
696
|
+
"deepseek-v4-flash-vision-exp": (
|
|
697
|
+
"vision preview - image understanding and tools, 1M context"
|
|
698
|
+
),
|
|
699
|
+
},
|
|
700
|
+
model_aliases={
|
|
701
|
+
# deepseek-chat / deepseek-reasoner are discontinued 2026-07-24;
|
|
702
|
+
# saved configs pinning them keep working via these remaps.
|
|
703
|
+
"deepseek-chat": "deepseek-v4-flash",
|
|
704
|
+
"deepseek-reasoner": "deepseek-v4-flash",
|
|
705
|
+
},
|
|
706
|
+
validation_model="deepseek-v4-flash",
|
|
707
|
+
setup_warning=(
|
|
708
|
+
"Do not use retired legacy aliases deepseek-chat or deepseek-reasoner "
|
|
709
|
+
"for production defaults; use the V4 model IDs. The vision model is "
|
|
710
|
+
"experimental and may change without a stable-release deprecation window."
|
|
711
|
+
),
|
|
712
|
+
),
|
|
713
|
+
ProfilePreset(
|
|
714
|
+
key="nvidia",
|
|
715
|
+
provider_key="nvidia",
|
|
716
|
+
label="NVIDIA NIM (Hosted)",
|
|
717
|
+
protocol="openai_compat",
|
|
718
|
+
base_url="https://integrate.api.nvidia.com/v1",
|
|
719
|
+
api_key_env="NVIDIA_API_KEY",
|
|
720
|
+
suggested_models=(
|
|
721
|
+
"nvidia/nemotron-3-super-120b-a12b",
|
|
722
|
+
"nvidia/nemotron-3-ultra-550b-a55b",
|
|
723
|
+
"nvidia/nemotron-3-nano-30b-a3b",
|
|
724
|
+
"deepseek-ai/deepseek-v4-pro",
|
|
725
|
+
"deepseek-ai/deepseek-v4-flash",
|
|
726
|
+
),
|
|
727
|
+
suggested_model_descriptions={
|
|
728
|
+
"nvidia/nemotron-3-super-120b-a12b": (
|
|
729
|
+
"default - balanced agentic reasoning, 1M context"
|
|
730
|
+
),
|
|
731
|
+
"nvidia/nemotron-3-ultra-550b-a55b": (
|
|
732
|
+
"advanced - frontier agentic reasoning, 1M context"
|
|
733
|
+
),
|
|
734
|
+
"nvidia/nemotron-3-nano-30b-a3b": (
|
|
735
|
+
"fast - efficient reasoning and tool use, 262K hosted context"
|
|
736
|
+
),
|
|
737
|
+
"deepseek-ai/deepseek-v4-pro": (
|
|
738
|
+
"third-party model hosted by NVIDIA - advanced agentic reasoning"
|
|
739
|
+
),
|
|
740
|
+
"deepseek-ai/deepseek-v4-flash": (
|
|
741
|
+
"third-party model hosted by NVIDIA - fast agentic reasoning"
|
|
742
|
+
),
|
|
743
|
+
},
|
|
744
|
+
validation_model="nvidia/nemotron-3-nano-30b-a3b",
|
|
745
|
+
setup_warning=(
|
|
746
|
+
"NVIDIA hosted Free Endpoints are rate-limited development endpoints for "
|
|
747
|
+
"prototyping; availability is not a production SLA and may vary by account."
|
|
748
|
+
),
|
|
749
|
+
notes=(
|
|
750
|
+
"Hosted NVIDIA NIM OpenAI-compatible API. The live catalog includes models "
|
|
751
|
+
"from NVIDIA and third parties; reasoning controls are model-specific."
|
|
752
|
+
),
|
|
753
|
+
),
|
|
754
|
+
ProfilePreset(
|
|
755
|
+
key="qwen-intl",
|
|
756
|
+
provider_key="qwen",
|
|
757
|
+
label="Alibaba Qwen / DashScope (Intl)",
|
|
758
|
+
protocol="openai_compat",
|
|
759
|
+
base_url="https://dashscope-intl.aliyuncs.com/compatible-mode/v1",
|
|
760
|
+
api_key_env="DASHSCOPE_API_KEY",
|
|
761
|
+
suggested_models=(
|
|
762
|
+
"qwen3.7-plus",
|
|
763
|
+
"qwen3.8-max",
|
|
764
|
+
"qwen3.7-max",
|
|
765
|
+
"qwen3-coder-plus",
|
|
766
|
+
"qwen3-coder-next",
|
|
767
|
+
"qwen3.6-flash",
|
|
768
|
+
"qwen-flash",
|
|
769
|
+
),
|
|
770
|
+
suggested_model_descriptions={
|
|
771
|
+
"qwen3.7-plus": "default - 1M context, balanced cost",
|
|
772
|
+
"qwen3.8-max": "advanced - newest multimodal flagship, 1M context",
|
|
773
|
+
"qwen3.7-max": "fallback - previous flagship, 1M context",
|
|
774
|
+
"qwen3-coder-plus": "coding - 1M context, long-repo work",
|
|
775
|
+
"qwen3-coder-next": "agentic - newest coder, 256K context",
|
|
776
|
+
"qwen3.6-flash": "fast - lower-latency, 1M context",
|
|
777
|
+
"qwen-flash": "economy - cheapest 1M-context option",
|
|
778
|
+
},
|
|
779
|
+
validation_model="qwen-flash",
|
|
780
|
+
web_search_adapter=DASHSCOPE_CHAT_ADAPTER,
|
|
781
|
+
web_search_model="qwen3.7-plus",
|
|
782
|
+
cache_capability=_QWEN_DIAGNOSTIC_CACHE_CAPABILITY,
|
|
783
|
+
setup_warning=(
|
|
784
|
+
"DashScope API keys are region-specific; use a key from the Singapore region."
|
|
785
|
+
),
|
|
786
|
+
),
|
|
787
|
+
ProfilePreset(
|
|
788
|
+
key="qwen-us",
|
|
789
|
+
provider_key="qwen",
|
|
790
|
+
label="Alibaba Qwen / DashScope (US)",
|
|
791
|
+
protocol="openai_compat",
|
|
792
|
+
base_url="https://dashscope-us.aliyuncs.com/compatible-mode/v1",
|
|
793
|
+
api_key_env="DASHSCOPE_API_KEY",
|
|
794
|
+
suggested_models=(
|
|
795
|
+
"qwen3.7-plus",
|
|
796
|
+
"qwen3.8-max",
|
|
797
|
+
"qwen3.7-max",
|
|
798
|
+
"qwen3.6-flash",
|
|
799
|
+
"qwen-flash",
|
|
800
|
+
),
|
|
801
|
+
suggested_model_descriptions={
|
|
802
|
+
"qwen3.7-plus": "default - 1M context, balanced cost",
|
|
803
|
+
"qwen3.8-max": "advanced - newest multimodal flagship, 1M context",
|
|
804
|
+
"qwen3.7-max": "fallback - previous flagship, 1M context",
|
|
805
|
+
"qwen3.6-flash": "fast - lower-latency, 1M context",
|
|
806
|
+
"qwen-flash": "economy - cheapest 1M-context option",
|
|
807
|
+
},
|
|
808
|
+
validation_model="qwen-flash",
|
|
809
|
+
web_search_adapter=DASHSCOPE_CHAT_ADAPTER,
|
|
810
|
+
web_search_model="qwen3.7-plus",
|
|
811
|
+
cache_capability=_QWEN_DIAGNOSTIC_CACHE_CAPABILITY,
|
|
812
|
+
setup_warning=(
|
|
813
|
+
"DashScope API keys are region-specific; use a key from the US region. "
|
|
814
|
+
"Qwen coder models are not served from US (Virginia) — use qwen3.7-plus "
|
|
815
|
+
"for code work."
|
|
816
|
+
),
|
|
817
|
+
),
|
|
818
|
+
ProfilePreset(
|
|
819
|
+
key="qwen-cn",
|
|
820
|
+
provider_key="qwen",
|
|
821
|
+
label="Alibaba Qwen / DashScope (China)",
|
|
822
|
+
protocol="openai_compat",
|
|
823
|
+
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
|
|
824
|
+
api_key_env="DASHSCOPE_API_KEY",
|
|
825
|
+
suggested_models=(
|
|
826
|
+
"qwen3.7-plus",
|
|
827
|
+
"qwen3.8-max",
|
|
828
|
+
"qwen3.7-max",
|
|
829
|
+
"qwen3-coder-plus",
|
|
830
|
+
"qwen3-coder-next",
|
|
831
|
+
"qwen3.6-flash",
|
|
832
|
+
"qwen-flash",
|
|
833
|
+
),
|
|
834
|
+
suggested_model_descriptions={
|
|
835
|
+
"qwen3.7-plus": "default - 1M context, balanced cost",
|
|
836
|
+
"qwen3.8-max": "advanced - newest multimodal flagship, 1M context",
|
|
837
|
+
"qwen3.7-max": "fallback - previous flagship, 1M context",
|
|
838
|
+
"qwen3-coder-plus": "coding - 1M context, long-repo work",
|
|
839
|
+
"qwen3-coder-next": "agentic - newest coder, 256K context",
|
|
840
|
+
"qwen3.6-flash": "fast - lower-latency, 1M context",
|
|
841
|
+
"qwen-flash": "economy - cheapest 1M-context option",
|
|
842
|
+
},
|
|
843
|
+
validation_model="qwen-flash",
|
|
844
|
+
web_search_adapter=DASHSCOPE_CHAT_ADAPTER,
|
|
845
|
+
web_search_model="qwen3.7-plus",
|
|
846
|
+
cache_capability=_QWEN_DIAGNOSTIC_CACHE_CAPABILITY,
|
|
847
|
+
setup_warning="DashScope API keys are region-specific; use a key from the China region.",
|
|
848
|
+
),
|
|
849
|
+
ProfilePreset(
|
|
850
|
+
key="zhipu",
|
|
851
|
+
provider_key="zhipu",
|
|
852
|
+
label="Zhipu / GLM",
|
|
853
|
+
protocol="openai_compat",
|
|
854
|
+
base_url="https://open.bigmodel.cn/api/paas/v4/",
|
|
855
|
+
api_key_env="ZHIPUAI_API_KEY",
|
|
856
|
+
suggested_models=(
|
|
857
|
+
"glm-5.2",
|
|
858
|
+
"glm-5.1",
|
|
859
|
+
"glm-5-turbo",
|
|
860
|
+
"glm-4.7",
|
|
861
|
+
"glm-4.7-flashx",
|
|
862
|
+
"glm-4.7-flash",
|
|
863
|
+
),
|
|
864
|
+
suggested_model_descriptions={
|
|
865
|
+
"glm-5.2": "default - 1M context, agentic coding",
|
|
866
|
+
"glm-5.1": "advanced - previous flagship, 200K context",
|
|
867
|
+
"glm-5-turbo": "coding - 200K context, cheaper than glm-5.1",
|
|
868
|
+
"glm-4.7": "fallback - cheap 200K context",
|
|
869
|
+
"glm-4.7-flashx": "fast - 200K context, no free-tier rate caps",
|
|
870
|
+
"glm-4.7-flash": "economy - free tier, 200K context, rate limited",
|
|
871
|
+
},
|
|
872
|
+
# No aliases on purpose: glm-5, glm-4.6 etc. remain individually priced
|
|
873
|
+
# and callable — remapping would silently change what users are billed.
|
|
874
|
+
validation_model="glm-4.7-flash",
|
|
875
|
+
web_search_adapter=ZHIPU_WEB_SEARCH_ADAPTER,
|
|
876
|
+
web_search_model="glm-5.1",
|
|
877
|
+
),
|
|
878
|
+
ProfilePreset(
|
|
879
|
+
key="zai-coding-plan",
|
|
880
|
+
provider_key="zai_coding_plan",
|
|
881
|
+
label="Z.AI GLM Coding Plan",
|
|
882
|
+
protocol="openai_compat",
|
|
883
|
+
base_url="https://api.z.ai/api/coding/paas/v4",
|
|
884
|
+
api_key_env="ZAI_API_KEY",
|
|
885
|
+
suggested_models=(
|
|
886
|
+
"glm-5.3",
|
|
887
|
+
"glm-5-turbo",
|
|
888
|
+
"glm-4.7",
|
|
889
|
+
),
|
|
890
|
+
suggested_model_descriptions={
|
|
891
|
+
"glm-5.3": "default - latest agentic coding model, 1M context",
|
|
892
|
+
"glm-5-turbo": "fast - lower-credit agent model, 200K context",
|
|
893
|
+
"glm-4.7": "fallback - lowest-credit plan model, 200K context",
|
|
894
|
+
},
|
|
895
|
+
# GLM-4.7 consumes fewer plan credits than GLM-5.3 and is available on
|
|
896
|
+
# every Coding Plan tier, so use it for the initial credential probe.
|
|
897
|
+
validation_model="glm-4.7",
|
|
898
|
+
cache_capability=_ZAI_CODING_PLAN_CACHE_CAPABILITY,
|
|
899
|
+
setup_warning=(
|
|
900
|
+
"Requires a Z.AI GLM Coding Plan key; general pay-as-you-go and "
|
|
901
|
+
"open.bigmodel.cn keys use different endpoints. Z.AI limits plan benefits "
|
|
902
|
+
"to supported coding tools, so verify Alysis Code eligibility for your account."
|
|
903
|
+
),
|
|
904
|
+
notes=(
|
|
905
|
+
"Subscription Coding Plan endpoint, not the general Z.AI or China Zhipu API. "
|
|
906
|
+
"All plan tiers currently offer GLM-5.3, GLM-5-Turbo, and GLM-4.7; "
|
|
907
|
+
"GLM-5.2/5.1 requests are routed by the server to GLM-5.3."
|
|
908
|
+
),
|
|
909
|
+
),
|
|
910
|
+
ProfilePreset(
|
|
911
|
+
key="moonshot",
|
|
912
|
+
provider_key="moonshot",
|
|
913
|
+
label="Kimi",
|
|
914
|
+
protocol="openai_compat",
|
|
915
|
+
base_url="https://api.moonshot.ai/v1",
|
|
916
|
+
api_key_env="MOONSHOT_API_KEY",
|
|
917
|
+
suggested_models=(
|
|
918
|
+
"kimi-k2.7-code",
|
|
919
|
+
"kimi-k3",
|
|
920
|
+
"kimi-k2.7-code-highspeed",
|
|
921
|
+
"kimi-k2.6",
|
|
922
|
+
),
|
|
923
|
+
suggested_model_descriptions={
|
|
924
|
+
# k2.7-code is the deliberate default: k3 is always-thinking at
|
|
925
|
+
# pinned max effort and ~3x the input price — escalate to it when a
|
|
926
|
+
# task needs the 1M window, don't route routine turns through it.
|
|
927
|
+
"kimi-k2.7-code": "default - 256K context, long-horizon agentic coding",
|
|
928
|
+
"kimi-k3": "advanced - 1M context, always-thinking at max effort",
|
|
929
|
+
"kimi-k2.7-code-highspeed": "fast - ~180 tok/s coding variant, 256K context",
|
|
930
|
+
"kimi-k2.6": "fallback - 256K context, thinking toggleable",
|
|
931
|
+
},
|
|
932
|
+
model_aliases={
|
|
933
|
+
# Only kimi-k2.6 accepts a thinking-off flag; K2.7/K3 error on it.
|
|
934
|
+
# kimi-k2.5 and the moonshot-v1-* family end 2026-08-31.
|
|
935
|
+
"kimi-k2": "kimi-k2.6",
|
|
936
|
+
"kimi-k2.5": "kimi-k2.6",
|
|
937
|
+
"kimi-k2-thinking": "kimi-k2.6",
|
|
938
|
+
"kimi-k2-thinking-turbo": "kimi-k2.6",
|
|
939
|
+
"kimi-k2-0905-preview": "kimi-k2.6",
|
|
940
|
+
"kimi-k2-0711-preview": "kimi-k2.6",
|
|
941
|
+
"kimi-k2-turbo-preview": "kimi-k2.7-code-highspeed",
|
|
942
|
+
"kimi-latest": "kimi-k2.6",
|
|
943
|
+
"kimi-thinking-preview": "kimi-k2.6",
|
|
944
|
+
"moonshot-v1-8k": "kimi-k2.6",
|
|
945
|
+
"moonshot-v1-32k": "kimi-k2.6",
|
|
946
|
+
"moonshot-v1-128k": "kimi-k2.6",
|
|
947
|
+
"moonshot-v1-auto": "kimi-k2.6",
|
|
948
|
+
},
|
|
949
|
+
validation_model="kimi-k2.6",
|
|
950
|
+
web_search_adapter=MOONSHOT_KIMI_ADAPTER,
|
|
951
|
+
# kimi-k3 cannot disable thinking, which Kimi's $web_search tool requires,
|
|
952
|
+
# so provider-hosted search stays pinned to kimi-k2.6.
|
|
953
|
+
web_search_model="kimi-k2.6",
|
|
954
|
+
cache_capability=_MOONSHOT_AUTOMATIC_CACHE_CAPABILITY,
|
|
955
|
+
setup_warning=(
|
|
956
|
+
"Moonshot API keys are region-scoped; use a key from the international "
|
|
957
|
+
"platform (platform.kimi.ai) with this endpoint."
|
|
958
|
+
),
|
|
959
|
+
),
|
|
960
|
+
ProfilePreset(
|
|
961
|
+
key="kimi-code",
|
|
962
|
+
provider_key="moonshot",
|
|
963
|
+
label="Kimi Code",
|
|
964
|
+
protocol="openai_compat",
|
|
965
|
+
base_url="https://api.kimi.com/coding/v1",
|
|
966
|
+
api_key_env="KIMI_API_KEY",
|
|
967
|
+
suggested_models=("k3", "kimi-for-coding", "kimi-for-coding-highspeed"),
|
|
968
|
+
suggested_model_descriptions={
|
|
969
|
+
# Tier gating: kimi-for-coding = all members; k3 = Moderato+ (256K)
|
|
970
|
+
# and 1M only on Allegretto+; -highspeed = Allegretto+ only.
|
|
971
|
+
# Disabling thinking on this endpoint silently routes to K2.6.
|
|
972
|
+
"k3": "default - 256K context, 1M on Allegretto+",
|
|
973
|
+
"kimi-for-coding": "coding - 256K context, all membership tiers",
|
|
974
|
+
"kimi-for-coding-highspeed": "fast - 256K context, Allegretto tier or above",
|
|
975
|
+
},
|
|
976
|
+
model_aliases={
|
|
977
|
+
# Cross-endpoint remaps: these are live, DIFFERENT ids on
|
|
978
|
+
# platform.moonshot.ai — legal only inside this preset's alias table.
|
|
979
|
+
"kimi-k3": "k3",
|
|
980
|
+
"kimi-k2.7-code": "kimi-for-coding",
|
|
981
|
+
"kimi-k2.7-code-highspeed": "kimi-for-coding-highspeed",
|
|
982
|
+
},
|
|
983
|
+
# Validation is a billed call against metered membership quota — no
|
|
984
|
+
# /models endpoint exists on this surface.
|
|
985
|
+
validation_model="kimi-for-coding",
|
|
986
|
+
setup_warning=(
|
|
987
|
+
"Requires a Kimi membership key from the kimi.com console; "
|
|
988
|
+
"platform.kimi.ai pay-as-you-go keys are not valid here. "
|
|
989
|
+
"Turning reasoning off routes requests to K2.6 (a different model)."
|
|
990
|
+
),
|
|
991
|
+
),
|
|
992
|
+
ProfilePreset(
|
|
993
|
+
key="moonshot-cn",
|
|
994
|
+
provider_key="moonshot",
|
|
995
|
+
label="Kimi (China)",
|
|
996
|
+
protocol="openai_compat",
|
|
997
|
+
base_url="https://api.moonshot.cn/v1",
|
|
998
|
+
api_key_env="MOONSHOT_API_KEY",
|
|
999
|
+
suggested_models=(
|
|
1000
|
+
"kimi-k2.7-code",
|
|
1001
|
+
"kimi-k3",
|
|
1002
|
+
"kimi-k2.7-code-highspeed",
|
|
1003
|
+
"kimi-k2.6",
|
|
1004
|
+
),
|
|
1005
|
+
suggested_model_descriptions={
|
|
1006
|
+
# k2.7-code is the deliberate default: k3 is always-thinking at
|
|
1007
|
+
# pinned max effort and ~3x the input price — escalate to it when a
|
|
1008
|
+
# task needs the 1M window, don't route routine turns through it.
|
|
1009
|
+
"kimi-k2.7-code": "default - 256K context, long-horizon agentic coding",
|
|
1010
|
+
"kimi-k3": "advanced - 1M context, always-thinking at max effort",
|
|
1011
|
+
"kimi-k2.7-code-highspeed": "fast - ~180 tok/s coding variant, 256K context",
|
|
1012
|
+
"kimi-k2.6": "fallback - 256K context, thinking toggleable",
|
|
1013
|
+
},
|
|
1014
|
+
model_aliases={
|
|
1015
|
+
# Only kimi-k2.6 accepts a thinking-off flag; K2.7/K3 error on it.
|
|
1016
|
+
# kimi-k2.5 and the moonshot-v1-* family end 2026-08-31.
|
|
1017
|
+
"kimi-k2": "kimi-k2.6",
|
|
1018
|
+
"kimi-k2.5": "kimi-k2.6",
|
|
1019
|
+
"kimi-k2-thinking": "kimi-k2.6",
|
|
1020
|
+
"kimi-k2-thinking-turbo": "kimi-k2.6",
|
|
1021
|
+
"kimi-k2-0905-preview": "kimi-k2.6",
|
|
1022
|
+
"kimi-k2-0711-preview": "kimi-k2.6",
|
|
1023
|
+
"kimi-k2-turbo-preview": "kimi-k2.7-code-highspeed",
|
|
1024
|
+
"kimi-latest": "kimi-k2.6",
|
|
1025
|
+
"kimi-thinking-preview": "kimi-k2.6",
|
|
1026
|
+
"moonshot-v1-8k": "kimi-k2.6",
|
|
1027
|
+
"moonshot-v1-32k": "kimi-k2.6",
|
|
1028
|
+
"moonshot-v1-128k": "kimi-k2.6",
|
|
1029
|
+
"moonshot-v1-auto": "kimi-k2.6",
|
|
1030
|
+
},
|
|
1031
|
+
validation_model="kimi-k2.6",
|
|
1032
|
+
web_search_adapter=MOONSHOT_KIMI_ADAPTER,
|
|
1033
|
+
# kimi-k3 cannot disable thinking, which Kimi's $web_search tool requires,
|
|
1034
|
+
# so provider-hosted search stays pinned to kimi-k2.6.
|
|
1035
|
+
web_search_model="kimi-k2.6",
|
|
1036
|
+
cache_capability=_MOONSHOT_AUTOMATIC_CACHE_CAPABILITY,
|
|
1037
|
+
setup_warning=(
|
|
1038
|
+
"Moonshot API keys are region-scoped; use a key from the mainland-China "
|
|
1039
|
+
"platform (platform.moonshot.cn) with this endpoint."
|
|
1040
|
+
),
|
|
1041
|
+
),
|
|
1042
|
+
ProfilePreset(
|
|
1043
|
+
key="minimax",
|
|
1044
|
+
provider_key="minimax",
|
|
1045
|
+
label="MiniMax",
|
|
1046
|
+
protocol="openai_compat",
|
|
1047
|
+
base_url="https://api.minimax.io/v1",
|
|
1048
|
+
api_key_env="MINIMAX_API_KEY",
|
|
1049
|
+
suggested_models=(
|
|
1050
|
+
"MiniMax-M3",
|
|
1051
|
+
"MiniMax-M2.7",
|
|
1052
|
+
"MiniMax-M2.7-highspeed",
|
|
1053
|
+
"MiniMax-M2.5",
|
|
1054
|
+
),
|
|
1055
|
+
suggested_model_descriptions={
|
|
1056
|
+
# No thinking/reasoning toggle is documented for any MiniMax model —
|
|
1057
|
+
# send no reasoning-control parameter on this preset. M3 input above
|
|
1058
|
+
# 512K bills at a higher long-context rate.
|
|
1059
|
+
"MiniMax-M3": "default - 1M context, multimodal agentic coding",
|
|
1060
|
+
"MiniMax-M2.7": "coding - 200K context, prior flagship",
|
|
1061
|
+
"MiniMax-M2.7-highspeed": "fast - same weights as M2.7, latency-tuned",
|
|
1062
|
+
"MiniMax-M2.5": "fallback - stable prior generation",
|
|
1063
|
+
},
|
|
1064
|
+
model_aliases={
|
|
1065
|
+
"MiniMax-M2": "MiniMax-M2.7",
|
|
1066
|
+
},
|
|
1067
|
+
validation_model="MiniMax-M2.5",
|
|
1068
|
+
web_search_adapter=MINIMAX_CODING_PLAN_ADAPTER,
|
|
1069
|
+
setup_warning=(
|
|
1070
|
+
"MiniMax hosted web search requires a Token Plan key; pay-as-you-go model keys "
|
|
1071
|
+
"cannot call the Token Plan search endpoint."
|
|
1072
|
+
),
|
|
1073
|
+
notes=(
|
|
1074
|
+
"Chat uses the OpenAI-compatible MiniMax API. Web search uses MiniMax's Token Plan "
|
|
1075
|
+
"search endpoint when the configured key has Token Plan access."
|
|
1076
|
+
),
|
|
1077
|
+
),
|
|
1078
|
+
ProfilePreset(
|
|
1079
|
+
key="xiaomi-mimo",
|
|
1080
|
+
provider_key="xiaomi",
|
|
1081
|
+
label="Xiaomi MiMo",
|
|
1082
|
+
protocol="openai_compat",
|
|
1083
|
+
base_url="https://api.xiaomimimo.com/v1",
|
|
1084
|
+
api_key_env="XIAOMI_API_KEY",
|
|
1085
|
+
suggested_models=("mimo-v2.5-pro", "mimo-v2-flash", "mimo-v2.5"),
|
|
1086
|
+
suggested_model_descriptions={
|
|
1087
|
+
"mimo-v2.5-pro": "default - flagship reasoning, coding & agents (1M context)",
|
|
1088
|
+
"mimo-v2-flash": "faster & lighter (256K context)",
|
|
1089
|
+
"mimo-v2.5": "omni - text + image understanding (1M context)",
|
|
1090
|
+
},
|
|
1091
|
+
validation_model="mimo-v2.5-pro",
|
|
1092
|
+
# Migrate the legacy bare "mimo" placeholder up to the flagship model.
|
|
1093
|
+
model_aliases={"mimo": "mimo-v2.5-pro"},
|
|
1094
|
+
),
|
|
1095
|
+
ProfilePreset(
|
|
1096
|
+
key="bytedance",
|
|
1097
|
+
provider_key="bytedance",
|
|
1098
|
+
label="ByteDance Doubao",
|
|
1099
|
+
protocol="openai_compat",
|
|
1100
|
+
base_url="https://ark.cn-beijing.volces.com/api/v3",
|
|
1101
|
+
api_key_env="ARK_API_KEY",
|
|
1102
|
+
suggested_models=(
|
|
1103
|
+
"doubao-seed-2-0-pro-260215",
|
|
1104
|
+
"doubao-seed-2-0-code-preview-260215",
|
|
1105
|
+
"doubao-seed-2-0-lite-260215",
|
|
1106
|
+
"doubao-seed-2-0-mini-260215",
|
|
1107
|
+
),
|
|
1108
|
+
suggested_model_descriptions={
|
|
1109
|
+
"doubao-seed-2-0-pro-260215": "default - flagship seed 2.0, agentic tasks",
|
|
1110
|
+
"doubao-seed-2-0-code-preview-260215": "coding - 256K context, preview snapshot",
|
|
1111
|
+
"doubao-seed-2-0-lite-260215": "fast - balanced quality and latency",
|
|
1112
|
+
"doubao-seed-2-0-mini-260215": "economy - cheapest seed 2.0, high concurrency",
|
|
1113
|
+
},
|
|
1114
|
+
validation_model="doubao-seed-2-0-mini-260215",
|
|
1115
|
+
web_search_adapter=VOLCENGINE_WEB_SEARCH_ADAPTER,
|
|
1116
|
+
setup_warning=(
|
|
1117
|
+
"Model ids rest on registry evidence only (Ark docs are not "
|
|
1118
|
+
"machine-readable) — verify with a live Ark key; Ark may require "
|
|
1119
|
+
"endpoint ids (ep-...) instead of bare model names."
|
|
1120
|
+
),
|
|
1121
|
+
),
|
|
1122
|
+
ProfilePreset(
|
|
1123
|
+
key="groq",
|
|
1124
|
+
provider_key="groq",
|
|
1125
|
+
label="Groq",
|
|
1126
|
+
protocol="openai_compat",
|
|
1127
|
+
base_url="https://api.groq.com/openai/v1",
|
|
1128
|
+
api_key_env="GROQ_API_KEY",
|
|
1129
|
+
suggested_models=(
|
|
1130
|
+
"openai/gpt-oss-120b",
|
|
1131
|
+
"qwen/qwen3.6-27b",
|
|
1132
|
+
"openai/gpt-oss-20b",
|
|
1133
|
+
"groq/compound",
|
|
1134
|
+
),
|
|
1135
|
+
suggested_model_descriptions={
|
|
1136
|
+
# groq/compound runs server-side built-in tools and does NOT accept
|
|
1137
|
+
# client tool_call — never route normal agent tool loops to it.
|
|
1138
|
+
"openai/gpt-oss-120b": "default - 131K context, adjustable reasoning",
|
|
1139
|
+
"qwen/qwen3.6-27b": "coding - thinking modes and vision, preview tier",
|
|
1140
|
+
"openai/gpt-oss-20b": "fast - cheapest non-deprecated production id",
|
|
1141
|
+
"groq/compound": "agentic - server-side web search and code exec",
|
|
1142
|
+
},
|
|
1143
|
+
model_aliases={
|
|
1144
|
+
# Both llama ids shut down 2026-08-16 (Groq deprecations table);
|
|
1145
|
+
# the other retired ids remap per the same table.
|
|
1146
|
+
"llama-3.3-70b-versatile": "openai/gpt-oss-120b",
|
|
1147
|
+
"llama-3.1-8b-instant": "openai/gpt-oss-20b",
|
|
1148
|
+
"qwen/qwen3-32b": "openai/gpt-oss-120b",
|
|
1149
|
+
"meta-llama/llama-4-scout-17b-16e-instruct": "openai/gpt-oss-120b",
|
|
1150
|
+
"meta-llama/llama-4-maverick-17b-128e-instruct": "openai/gpt-oss-120b",
|
|
1151
|
+
"moonshotai/kimi-k2-instruct": "openai/gpt-oss-120b",
|
|
1152
|
+
"moonshotai/kimi-k2-instruct-0905": "openai/gpt-oss-120b",
|
|
1153
|
+
},
|
|
1154
|
+
validation_model="openai/gpt-oss-20b",
|
|
1155
|
+
web_search_adapter=GROQ_COMPOUND_ADAPTER,
|
|
1156
|
+
web_search_model="groq/compound-mini",
|
|
1157
|
+
setup_warning=(
|
|
1158
|
+
"Groq is mostly OpenAI-compatible; avoid preview-only models as production "
|
|
1159
|
+
"defaults (qwen/qwen3.6-27b is preview and may be pulled without notice)."
|
|
1160
|
+
),
|
|
1161
|
+
),
|
|
1162
|
+
ProfilePreset(
|
|
1163
|
+
key="cerebras",
|
|
1164
|
+
provider_key="cerebras",
|
|
1165
|
+
label="Cerebras",
|
|
1166
|
+
protocol="openai_compat",
|
|
1167
|
+
base_url="https://api.cerebras.ai/v1",
|
|
1168
|
+
api_key_env="CEREBRAS_API_KEY",
|
|
1169
|
+
suggested_models=(
|
|
1170
|
+
"gpt-oss-120b",
|
|
1171
|
+
"zai-glm-4.7",
|
|
1172
|
+
"gemma-4-31b",
|
|
1173
|
+
),
|
|
1174
|
+
suggested_model_descriptions={
|
|
1175
|
+
# Context values are the free-tier floor (65K); paid keys get 131K.
|
|
1176
|
+
# gpt-oss-120b cannot disable reasoning (effort low|medium|high).
|
|
1177
|
+
"gpt-oss-120b": "default - only GA public model, ~3000 tok/s",
|
|
1178
|
+
"zai-glm-4.7": "coding - strongest here, deprecates 2026-08-17",
|
|
1179
|
+
"gemma-4-31b": "fallback - only image-input model, preview tier",
|
|
1180
|
+
},
|
|
1181
|
+
model_aliases={
|
|
1182
|
+
# The llama family left Cerebras public endpoints 2026-02-16 (and
|
|
1183
|
+
# "llama3.3-70b" was never a valid spelling of the id).
|
|
1184
|
+
"llama3.3-70b": "gpt-oss-120b",
|
|
1185
|
+
"llama-3.3-70b": "gpt-oss-120b",
|
|
1186
|
+
"llama3.1-70b": "gpt-oss-120b",
|
|
1187
|
+
"llama3.1-8b": "gpt-oss-120b",
|
|
1188
|
+
"qwen-3-32b": "gpt-oss-120b",
|
|
1189
|
+
"qwen-3-coder-480b": "zai-glm-4.7",
|
|
1190
|
+
"zai-glm-4.6": "zai-glm-4.7",
|
|
1191
|
+
"deepseek-r1-distill-llama-70b": "gpt-oss-120b",
|
|
1192
|
+
},
|
|
1193
|
+
validation_model="gpt-oss-120b",
|
|
1194
|
+
),
|
|
1195
|
+
ProfilePreset(
|
|
1196
|
+
key="mistral",
|
|
1197
|
+
provider_key="mistral",
|
|
1198
|
+
label="Mistral AI",
|
|
1199
|
+
protocol="openai_compat",
|
|
1200
|
+
base_url="https://api.mistral.ai/v1",
|
|
1201
|
+
api_key_env="MISTRAL_API_KEY",
|
|
1202
|
+
suggested_models=(
|
|
1203
|
+
"mistral-medium-3-5",
|
|
1204
|
+
"mistral-large-2512",
|
|
1205
|
+
"mistral-small-2603",
|
|
1206
|
+
"codestral-2508",
|
|
1207
|
+
"ministral-8b-2512",
|
|
1208
|
+
),
|
|
1209
|
+
suggested_model_descriptions={
|
|
1210
|
+
# codestral is FIM/completion-oriented with ~4K max output — routers
|
|
1211
|
+
# should prefer the default for multi-file agentic patch turns.
|
|
1212
|
+
"mistral-medium-3-5": "default - agentic and coding flagship, 256K",
|
|
1213
|
+
"mistral-large-2512": "advanced - mistral large 3, 675B MoE, 256K",
|
|
1214
|
+
"mistral-small-2603": "fast - mistral small 4, low latency",
|
|
1215
|
+
"codestral-2508": "coding - FIM and completion, 4K max output",
|
|
1216
|
+
"ministral-8b-2512": "economy - small tool-capable model",
|
|
1217
|
+
},
|
|
1218
|
+
model_aliases={
|
|
1219
|
+
# Mistral documents mistral-medium-3-5 as the primary API id. Keep
|
|
1220
|
+
# the former Alysis Code default as a compatibility alias, while the
|
|
1221
|
+
# provider-managed -latest alias passes through unchanged.
|
|
1222
|
+
"mistral-medium-2604": "mistral-medium-3-5",
|
|
1223
|
+
"mistral-medium-3": "mistral-medium-3-5",
|
|
1224
|
+
"mistral-medium-2508": "mistral-medium-3-5",
|
|
1225
|
+
"mistral-medium-2505": "mistral-medium-3-5",
|
|
1226
|
+
"mistral-small-latest": "mistral-small-2603",
|
|
1227
|
+
"mistral-small-2506": "mistral-small-2603",
|
|
1228
|
+
"mistral-large-latest": "mistral-large-2512",
|
|
1229
|
+
"mistral-large-2411": "mistral-medium-3-5",
|
|
1230
|
+
"mistral-large-2407": "mistral-large-2512",
|
|
1231
|
+
"codestral-latest": "codestral-2508",
|
|
1232
|
+
"devstral-2512": "mistral-medium-3-5",
|
|
1233
|
+
"devstral-latest": "mistral-medium-3-5",
|
|
1234
|
+
"devstral-medium-latest": "mistral-medium-3-5",
|
|
1235
|
+
"devstral-medium-2507": "mistral-medium-3-5",
|
|
1236
|
+
"devstral-small-2507": "mistral-small-2603",
|
|
1237
|
+
"labs-devstral-small-2512": "mistral-medium-3-5",
|
|
1238
|
+
"magistral-medium-latest": "mistral-medium-3-5",
|
|
1239
|
+
"magistral-small-latest": "mistral-small-2603",
|
|
1240
|
+
"ministral-8b-latest": "ministral-8b-2512",
|
|
1241
|
+
"open-mistral-nemo-2407": "ministral-8b-2512",
|
|
1242
|
+
},
|
|
1243
|
+
validation_model="ministral-3b-2512",
|
|
1244
|
+
web_search_adapter=MISTRAL_CONVERSATIONS_ADAPTER,
|
|
1245
|
+
web_search_model="mistral-medium-latest",
|
|
1246
|
+
cache_capability=_MISTRAL_PROMPT_CACHE_CAPABILITY,
|
|
1247
|
+
),
|
|
1248
|
+
ProfilePreset(
|
|
1249
|
+
key="xai",
|
|
1250
|
+
provider_key="xai",
|
|
1251
|
+
label="xAI Grok",
|
|
1252
|
+
protocol="openai_compat",
|
|
1253
|
+
base_url="https://api.x.ai/v1",
|
|
1254
|
+
api_key_env="XAI_API_KEY",
|
|
1255
|
+
suggested_models=(
|
|
1256
|
+
"grok-4.6",
|
|
1257
|
+
"grok-4.5",
|
|
1258
|
+
"grok-build-0.1",
|
|
1259
|
+
"grok-4.3",
|
|
1260
|
+
"grok-4.20-0309-reasoning",
|
|
1261
|
+
"grok-4.20-0309-non-reasoning",
|
|
1262
|
+
),
|
|
1263
|
+
suggested_model_descriptions={
|
|
1264
|
+
# grok-build-0.1 is served from us-east-1/us-west-2 only. Max output
|
|
1265
|
+
# is unpublished for the 4.20 family — clamp conservatively.
|
|
1266
|
+
"grok-4.6": "default - newest flagship for coding and agents, 500K",
|
|
1267
|
+
"grok-4.5": "fallback - previous flagship for coding and agents",
|
|
1268
|
+
"grok-build-0.1": "coding - agentic engineering model, 256K",
|
|
1269
|
+
"grok-4.3": "advanced - 1M context window",
|
|
1270
|
+
"grok-4.20-0309-reasoning": "reasoning - dedicated snapshot, 1M context",
|
|
1271
|
+
"grok-4.20-0309-non-reasoning": "fast - no-reasoning snapshot, 1M context",
|
|
1272
|
+
},
|
|
1273
|
+
model_aliases={
|
|
1274
|
+
# Retired 2026-05-15, full shutdown 2026-08-15. The *-non-reasoning
|
|
1275
|
+
# slugs deliberately map to the non-reasoning snapshot (xAI's own
|
|
1276
|
+
# redirect lands them on grok-4.3 with effort=none, which the alias
|
|
1277
|
+
# table cannot express).
|
|
1278
|
+
"grok-code-fast-1": "grok-build-0.1",
|
|
1279
|
+
"grok-4": "grok-4.3",
|
|
1280
|
+
"grok-4-0709": "grok-4.3",
|
|
1281
|
+
"grok-4-fast": "grok-4.3",
|
|
1282
|
+
"grok-4.3-latest": "grok-4.3",
|
|
1283
|
+
"grok-4-fast-reasoning": "grok-4.3",
|
|
1284
|
+
"grok-4-1-fast-reasoning": "grok-4.3",
|
|
1285
|
+
"grok-4-fast-non-reasoning": "grok-4.20-0309-non-reasoning",
|
|
1286
|
+
"grok-4-1-fast-non-reasoning": "grok-4.20-0309-non-reasoning",
|
|
1287
|
+
"grok-3": "grok-4.3",
|
|
1288
|
+
},
|
|
1289
|
+
validation_model="grok-4.20-0309-non-reasoning",
|
|
1290
|
+
web_search_adapter=XAI_RESPONSES_ADAPTER,
|
|
1291
|
+
cache_capability=_XAI_CONVERSATION_HEADER_CACHE_CAPABILITY,
|
|
1292
|
+
setup_warning=(
|
|
1293
|
+
"Retired slugs (grok-4, grok-4-fast, grok-3, grok-code-fast-1) shut down "
|
|
1294
|
+
"fully 2026-08-15 and are billed at grok-4.3 rates until then; migrate "
|
|
1295
|
+
"pinned configs explicitly. Ids use dots, not dashes (grok-4.6)."
|
|
1296
|
+
),
|
|
1297
|
+
),
|
|
1298
|
+
ProfilePreset(
|
|
1299
|
+
key="cohere",
|
|
1300
|
+
provider_key="cohere",
|
|
1301
|
+
label="Cohere (compat)",
|
|
1302
|
+
protocol="openai_compat",
|
|
1303
|
+
base_url="https://api.cohere.ai/compatibility/v1",
|
|
1304
|
+
api_key_env="COHERE_API_KEY",
|
|
1305
|
+
suggested_models=(
|
|
1306
|
+
"command-a-plus-05-2026",
|
|
1307
|
+
"command-a-reasoning-08-2025",
|
|
1308
|
+
"command-a-03-2025",
|
|
1309
|
+
"command-r7b-12-2024",
|
|
1310
|
+
),
|
|
1311
|
+
suggested_model_descriptions={
|
|
1312
|
+
# Reasoning toggle (thinking=disabled) is a native Chat V2 param and
|
|
1313
|
+
# may not pass through /compatibility/v1 — treat as thinking-on.
|
|
1314
|
+
"command-a-plus-05-2026": "default - newest command a+, 128K context",
|
|
1315
|
+
"command-a-reasoning-08-2025": "reasoning - 256K context, thinking is a toggle",
|
|
1316
|
+
"command-a-03-2025": "advanced - 256K context, prior flagship",
|
|
1317
|
+
"command-r7b-12-2024": "economy - cheapest live chat model, 128K",
|
|
1318
|
+
},
|
|
1319
|
+
model_aliases={
|
|
1320
|
+
"command": "command-a-03-2025",
|
|
1321
|
+
"command-light": "command-r-08-2024",
|
|
1322
|
+
"command-r": "command-r-08-2024",
|
|
1323
|
+
"command-r-plus": "command-r-plus-08-2024",
|
|
1324
|
+
},
|
|
1325
|
+
validation_model="command-r7b-12-2024",
|
|
1326
|
+
web_search_adapter=COHERE_WEB_SEARCH_ADAPTER,
|
|
1327
|
+
setup_warning=(
|
|
1328
|
+
"Cohere shut down the v1 hosted web-search connector on 2025-09-15; "
|
|
1329
|
+
"hosted web search on this preset needs migration to an external "
|
|
1330
|
+
"search adapter."
|
|
1331
|
+
),
|
|
1332
|
+
notes=(
|
|
1333
|
+
"Chat uses Cohere's OpenAI compatibility API (api.cohere.ai/compatibility/v1 — "
|
|
1334
|
+
"documented and correct; do not migrate to v2/chat). The v1 hosted web-search "
|
|
1335
|
+
"connector this preset's adapter targeted was shut down 2025-09-15."
|
|
1336
|
+
),
|
|
1337
|
+
),
|
|
1338
|
+
ProfilePreset(
|
|
1339
|
+
key="openrouter",
|
|
1340
|
+
provider_key="openrouter",
|
|
1341
|
+
label="OpenRouter (gateway)",
|
|
1342
|
+
protocol="openai_compat",
|
|
1343
|
+
base_url="https://openrouter.ai/api/v1",
|
|
1344
|
+
api_key_env="OPENROUTER_API_KEY",
|
|
1345
|
+
suggested_models=(
|
|
1346
|
+
"anthropic/claude-sonnet-5",
|
|
1347
|
+
"anthropic/claude-opus-4.8",
|
|
1348
|
+
"openai/gpt-5.6-terra",
|
|
1349
|
+
"openai/gpt-5.6-luna",
|
|
1350
|
+
"z-ai/glm-5.2",
|
|
1351
|
+
"deepseek/deepseek-v4-pro-0813",
|
|
1352
|
+
"deepseek/deepseek-v4-flash-0731",
|
|
1353
|
+
"deepseek/deepseek-v4-flash-vision-exp",
|
|
1354
|
+
"qwen/qwen3.8-max",
|
|
1355
|
+
),
|
|
1356
|
+
suggested_model_descriptions={
|
|
1357
|
+
# Vendor prefixes are exact: z-ai/ (not zai/), x-ai/, moonshotai/.
|
|
1358
|
+
# Avoid '-latest' floating aliases and rate-limited :free variants
|
|
1359
|
+
# for agent loops.
|
|
1360
|
+
"anthropic/claude-sonnet-5": "default - coding and agents, 1M context",
|
|
1361
|
+
"anthropic/claude-opus-4.8": "advanced - long-horizon autonomous work",
|
|
1362
|
+
"openai/gpt-5.6-terra": "coding - balanced gpt-5.6 tier, 1.05M context",
|
|
1363
|
+
"openai/gpt-5.6-luna": "fast - cost-efficient gpt-5.6 tier",
|
|
1364
|
+
"z-ai/glm-5.2": "economy - cheap 1M-context tool caller",
|
|
1365
|
+
"deepseek/deepseek-v4-pro-0813": "agentic - current reasoning MoE, 1M context",
|
|
1366
|
+
"deepseek/deepseek-v4-flash-0731": "fast - current low-cost 1M release",
|
|
1367
|
+
"deepseek/deepseek-v4-flash-vision-exp": (
|
|
1368
|
+
"vision preview - image understanding and tools, 1M context"
|
|
1369
|
+
),
|
|
1370
|
+
"qwen/qwen3.8-max": "multimodal - flagship Qwen agent model, 1M context",
|
|
1371
|
+
},
|
|
1372
|
+
validation_model="deepseek/deepseek-v4-flash-0731",
|
|
1373
|
+
web_search_adapter=OPENROUTER_WEB_ADAPTER,
|
|
1374
|
+
cache_capability=_OPENROUTER_STICKY_SESSION_CACHE_CAPABILITY,
|
|
1375
|
+
setup_warning=(
|
|
1376
|
+
"OpenRouter routes through upstream providers; availability, pricing, privacy, "
|
|
1377
|
+
"and parameter support can vary by route."
|
|
1378
|
+
),
|
|
1379
|
+
notes="Single API to many providers' models.",
|
|
1380
|
+
),
|
|
1381
|
+
ProfilePreset(
|
|
1382
|
+
key="perplexity",
|
|
1383
|
+
provider_key="perplexity",
|
|
1384
|
+
label="Perplexity Sonar",
|
|
1385
|
+
protocol="openai_compat",
|
|
1386
|
+
base_url="https://api.perplexity.ai",
|
|
1387
|
+
api_key_env="PERPLEXITY_API_KEY",
|
|
1388
|
+
suggested_models=("sonar-pro", "sonar"),
|
|
1389
|
+
web_search_adapter=PERPLEXITY_SONAR_ADAPTER,
|
|
1390
|
+
web_search_model="sonar",
|
|
1391
|
+
setup_warning=(
|
|
1392
|
+
"Search-only: sonar models reject tool definitions (HTTP 400), so this "
|
|
1393
|
+
"preset cannot run agentic tool loops. Perplexity's coding models live "
|
|
1394
|
+
"on the Agent API (/v1/agent), which needs a Responses-style client "
|
|
1395
|
+
"Alysis Code does not ship yet."
|
|
1396
|
+
),
|
|
1397
|
+
notes="Sonar models include web-grounded answers and citations.",
|
|
1398
|
+
),
|
|
1399
|
+
ProfilePreset(
|
|
1400
|
+
key="together",
|
|
1401
|
+
provider_key="together",
|
|
1402
|
+
label="Together AI",
|
|
1403
|
+
protocol="openai_compat",
|
|
1404
|
+
base_url="https://api.together.ai/v1",
|
|
1405
|
+
api_key_env="TOGETHER_API_KEY",
|
|
1406
|
+
suggested_models=(
|
|
1407
|
+
"zai-org/GLM-5.2",
|
|
1408
|
+
"moonshotai/Kimi-K2.7-Code",
|
|
1409
|
+
"deepseek-ai/DeepSeek-V4-Pro-0813",
|
|
1410
|
+
"deepseek-ai/DeepSeek-V4-Flash-0731",
|
|
1411
|
+
"MiniMaxAI/MiniMax-M3",
|
|
1412
|
+
"openai/gpt-oss-120b",
|
|
1413
|
+
"openai/gpt-oss-20b",
|
|
1414
|
+
),
|
|
1415
|
+
suggested_model_descriptions={
|
|
1416
|
+
# Ids are case-sensitive and vendor-prefixed. Kimi-K2.7-Code and
|
|
1417
|
+
# MiniMax-M3 reason unconditionally — never emit a reasoning-off or
|
|
1418
|
+
# effort param for them.
|
|
1419
|
+
"zai-org/GLM-5.2": "default - general coding, 256K context",
|
|
1420
|
+
"moonshotai/Kimi-K2.7-Code": "coding - code specialist, 256K context",
|
|
1421
|
+
"deepseek-ai/DeepSeek-V4-Pro-0813": "reasoning - current flagship, 1M context",
|
|
1422
|
+
"deepseek-ai/DeepSeek-V4-Flash-0731": "fast - current 1M-context release",
|
|
1423
|
+
"MiniMaxAI/MiniMax-M3": "economy - cheapest 512K-context option",
|
|
1424
|
+
"openai/gpt-oss-120b": "open - larger tool-capable GPT-OSS model, 128K context",
|
|
1425
|
+
"openai/gpt-oss-20b": "fallback - cheapest tool-capable id",
|
|
1426
|
+
},
|
|
1427
|
+
model_aliases={
|
|
1428
|
+
# Fallback policy, NOT vendor renames: Together retires serverless
|
|
1429
|
+
# models with a blank successor column. Two are cross-vendor
|
|
1430
|
+
# substitutions — surface the swap to the user at resolution time.
|
|
1431
|
+
"zai-org/GLM-5.1": "zai-org/GLM-5.2",
|
|
1432
|
+
"Qwen/Qwen3-Coder-480B-A35B-Instruct-FP8": "moonshotai/Kimi-K2.7-Code",
|
|
1433
|
+
"Qwen/Qwen3-Coder-Next-FP8": "moonshotai/Kimi-K2.7-Code",
|
|
1434
|
+
},
|
|
1435
|
+
validation_model="openai/gpt-oss-20b",
|
|
1436
|
+
setup_warning=(
|
|
1437
|
+
"Together retires serverless models on a published schedule with no "
|
|
1438
|
+
"successor mapping — expect id churn; verify access with Together's "
|
|
1439
|
+
"Models API."
|
|
1440
|
+
),
|
|
1441
|
+
),
|
|
1442
|
+
ProfilePreset(
|
|
1443
|
+
key="fireworks",
|
|
1444
|
+
provider_key="fireworks",
|
|
1445
|
+
label="Fireworks AI",
|
|
1446
|
+
protocol="openai_compat",
|
|
1447
|
+
base_url="https://api.fireworks.ai/inference/v1",
|
|
1448
|
+
api_key_env="FIREWORKS_API_KEY",
|
|
1449
|
+
suggested_models=(
|
|
1450
|
+
"accounts/fireworks/models/glm-5p2",
|
|
1451
|
+
"accounts/fireworks/models/kimi-k2p7-code",
|
|
1452
|
+
"accounts/fireworks/models/deepseek-v4-pro-0813",
|
|
1453
|
+
"accounts/fireworks/models/deepseek-v4-flash-0731",
|
|
1454
|
+
"accounts/fireworks/models/minimax-m3",
|
|
1455
|
+
"accounts/fireworks/models/qwen3p7-plus",
|
|
1456
|
+
),
|
|
1457
|
+
suggested_model_descriptions={
|
|
1458
|
+
# 'p' is the decimal convention (5p2 = 5.2). Catalog membership does
|
|
1459
|
+
# NOT imply serverless availability on Fireworks — every id here is
|
|
1460
|
+
# confirmed serverless-capable.
|
|
1461
|
+
"accounts/fireworks/models/glm-5p2": "default - general agentic coding, 1M context",
|
|
1462
|
+
"accounts/fireworks/models/kimi-k2p7-code": "coding - 262K context, tool calling",
|
|
1463
|
+
"accounts/fireworks/models/deepseek-v4-pro-0813": (
|
|
1464
|
+
"reasoning - current 1M-context production release"
|
|
1465
|
+
),
|
|
1466
|
+
"accounts/fireworks/models/deepseek-v4-flash-0731": (
|
|
1467
|
+
"fast - current lowest-cost 1M-context release"
|
|
1468
|
+
),
|
|
1469
|
+
"accounts/fireworks/models/minimax-m3": "economy - 512K context, effort control",
|
|
1470
|
+
"accounts/fireworks/models/qwen3p7-plus": "fallback - 262K context, standard tier only",
|
|
1471
|
+
},
|
|
1472
|
+
model_aliases={
|
|
1473
|
+
# qwen2p5-coder is not serverless-capable at all (on-demand GPU
|
|
1474
|
+
# only); the other two are superseded snapshots.
|
|
1475
|
+
"accounts/fireworks/models/qwen2p5-coder-32b-instruct": (
|
|
1476
|
+
"accounts/fireworks/models/kimi-k2p7-code"
|
|
1477
|
+
),
|
|
1478
|
+
"accounts/fireworks/models/kimi-k2p6": "accounts/fireworks/models/kimi-k2p7-code",
|
|
1479
|
+
"accounts/fireworks/models/glm-5p1": "accounts/fireworks/models/glm-5p2",
|
|
1480
|
+
},
|
|
1481
|
+
validation_model="accounts/fireworks/models/deepseek-v4-flash-0731",
|
|
1482
|
+
),
|
|
1483
|
+
# Account-gated hosted preset — registered after the hosted third-party
|
|
1484
|
+
# vendors so listings that read PROFILE_PRESETS order do not headline it.
|
|
1485
|
+
ProfilePreset(
|
|
1486
|
+
key="alysis",
|
|
1487
|
+
provider_key="alysis",
|
|
1488
|
+
label="Alysis Code Pro",
|
|
1489
|
+
protocol="openai_compat",
|
|
1490
|
+
# The Alysis Code hosted proxy (`llm` Supabase Edge Function). It
|
|
1491
|
+
# authenticates the user's slk_ key, meters the free daily allowance /
|
|
1492
|
+
# Pro credits server-side, and forwards to DeepSeek. The login flow
|
|
1493
|
+
# overrides this from alysis_cloud at runtime (env-configurable), so
|
|
1494
|
+
# this literal is just the default.
|
|
1495
|
+
base_url="https://vzigujbcjjmpntxhmyvr.supabase.co/functions/v1/llm/v1",
|
|
1496
|
+
api_key_env=None,
|
|
1497
|
+
# The models the subscription offers. Live availability is discovered
|
|
1498
|
+
# from the gateway's /v1/models at runtime; this static list is the
|
|
1499
|
+
# offline fallback and the menu shown before a model is chosen.
|
|
1500
|
+
suggested_models=("deepseek-v4-flash", "deepseek-v4-pro"),
|
|
1501
|
+
suggested_model_descriptions={
|
|
1502
|
+
"deepseek-v4-flash": "default - fast high-volume coding (1M context, free daily allowance)",
|
|
1503
|
+
"deepseek-v4-pro": "flagship - deeper reasoning (1M context, requires Alysis Code Pro)",
|
|
1504
|
+
},
|
|
1505
|
+
validation_model="deepseek-v4-flash",
|
|
1506
|
+
# Migrate ids from the retired Xiaomi MiMo trial to the Pro default so
|
|
1507
|
+
# old sessions keep working after upgrade.
|
|
1508
|
+
model_aliases={
|
|
1509
|
+
"mimo": "deepseek-v4-flash",
|
|
1510
|
+
"mimo-v2.5-pro": "deepseek-v4-flash",
|
|
1511
|
+
"mimo-v2-flash": "deepseek-v4-flash",
|
|
1512
|
+
"mimo-v2.5": "deepseek-v4-flash",
|
|
1513
|
+
},
|
|
1514
|
+
setup_warning=("Requires an Alysis Code Pro subscription — run `alysis login` to connect."),
|
|
1515
|
+
notes="Hosted models via your Alysis Code Pro subscription. Authenticate with `alysis login`.",
|
|
1516
|
+
),
|
|
1517
|
+
ProfilePreset(
|
|
1518
|
+
key="ollama",
|
|
1519
|
+
provider_key="ollama",
|
|
1520
|
+
label="Ollama (local)",
|
|
1521
|
+
protocol="openai_compat",
|
|
1522
|
+
base_url="http://localhost:11434/v1",
|
|
1523
|
+
api_key_env=None,
|
|
1524
|
+
suggested_models=("llama3.3",),
|
|
1525
|
+
notes="Local Ollama server. No API key required.",
|
|
1526
|
+
),
|
|
1527
|
+
ProfilePreset(
|
|
1528
|
+
key="lm-studio",
|
|
1529
|
+
provider_key="lm-studio",
|
|
1530
|
+
label="LM Studio (local)",
|
|
1531
|
+
protocol="openai_compat",
|
|
1532
|
+
base_url="http://localhost:1234/v1",
|
|
1533
|
+
api_key_env=None,
|
|
1534
|
+
suggested_models=("local-model",),
|
|
1535
|
+
notes="Local LM Studio server. No API key required.",
|
|
1536
|
+
),
|
|
1537
|
+
ProfilePreset(
|
|
1538
|
+
key="vllm",
|
|
1539
|
+
provider_key="vllm",
|
|
1540
|
+
label="vLLM (self-hosted)",
|
|
1541
|
+
protocol="openai_compat",
|
|
1542
|
+
base_url="http://localhost:8000/v1",
|
|
1543
|
+
api_key_env=None,
|
|
1544
|
+
suggested_models=("local-model",),
|
|
1545
|
+
),
|
|
1546
|
+
ProfilePreset(
|
|
1547
|
+
key="custom",
|
|
1548
|
+
label="Custom (specify URL manually)",
|
|
1549
|
+
protocol="openai_compat",
|
|
1550
|
+
base_url="",
|
|
1551
|
+
api_key_env=None,
|
|
1552
|
+
suggested_models=(),
|
|
1553
|
+
notes="Use for unlisted endpoints. Type the URL during setup.",
|
|
1554
|
+
),
|
|
1555
|
+
)
|
|
1556
|
+
|
|
1557
|
+
PRESET_BY_KEY: dict[str, ProfilePreset] = {preset.key: preset for preset in PROFILE_PRESETS}
|
|
1558
|
+
|
|
1559
|
+
|
|
1560
|
+
def get_preset(key: str) -> ProfilePreset | None:
|
|
1561
|
+
return PRESET_BY_KEY.get(str(key or "").strip().lower())
|
|
1562
|
+
|
|
1563
|
+
|
|
1564
|
+
def model_options_for_preset(preset: ProfilePreset) -> tuple[tuple[str, str, str], ...]:
|
|
1565
|
+
"""Return picker rows for the models this preset intentionally supports."""
|
|
1566
|
+
rows: list[tuple[str, str, str]] = []
|
|
1567
|
+
seen: set[str] = set()
|
|
1568
|
+
for model in preset.suggested_models:
|
|
1569
|
+
model_id = str(model or "").strip()
|
|
1570
|
+
if not model_id or model_id in seen:
|
|
1571
|
+
continue
|
|
1572
|
+
seen.add(model_id)
|
|
1573
|
+
description = str(preset.suggested_model_descriptions.get(model_id) or "").strip()
|
|
1574
|
+
rows.append((model_id, model_id, description or "suggested by provider preset"))
|
|
1575
|
+
return tuple(rows)
|
|
1576
|
+
|
|
1577
|
+
|
|
1578
|
+
def canonical_model_alias_for_preset(preset: ProfilePreset, model: str) -> str:
|
|
1579
|
+
"""Map explicit stale provider aliases to the preset's current model ID."""
|
|
1580
|
+
raw = str(model or "").strip()
|
|
1581
|
+
if not raw:
|
|
1582
|
+
return raw
|
|
1583
|
+
for alias, canonical in preset.model_aliases.items():
|
|
1584
|
+
if str(alias or "").strip().casefold() == raw.casefold():
|
|
1585
|
+
normalized = str(canonical or "").strip()
|
|
1586
|
+
return normalized or raw
|
|
1587
|
+
return raw
|
|
1588
|
+
|
|
1589
|
+
|
|
1590
|
+
def find_preset_for_profile(profile: ProfileSpec) -> ProfilePreset | None:
|
|
1591
|
+
"""Best-effort mapping from a persisted profile back to a known provider preset."""
|
|
1592
|
+
name_match = get_preset(profile.name)
|
|
1593
|
+
if name_match is not None and _profile_matches_preset(profile, name_match):
|
|
1594
|
+
return name_match
|
|
1595
|
+
|
|
1596
|
+
for preset in PROFILE_PRESETS:
|
|
1597
|
+
if preset.key == "custom":
|
|
1598
|
+
continue
|
|
1599
|
+
if _profile_matches_preset(profile, preset):
|
|
1600
|
+
return preset
|
|
1601
|
+
|
|
1602
|
+
if profile.protocol != OPENAI_COMPAT_PROTOCOL:
|
|
1603
|
+
return None
|
|
1604
|
+
return find_preset_for_base_url(profile.base_url)
|
|
1605
|
+
|
|
1606
|
+
|
|
1607
|
+
def find_preset_for_base_url(base_url: str) -> ProfilePreset | None:
|
|
1608
|
+
normalized = _normalized_base_url(base_url)
|
|
1609
|
+
if not normalized:
|
|
1610
|
+
return None
|
|
1611
|
+
matches: list[ProfilePreset] = []
|
|
1612
|
+
for preset in PROFILE_PRESETS:
|
|
1613
|
+
if preset.key == "custom":
|
|
1614
|
+
continue
|
|
1615
|
+
if _normalized_base_url(preset.base_url) == normalized:
|
|
1616
|
+
matches.append(preset)
|
|
1617
|
+
if not matches:
|
|
1618
|
+
return None
|
|
1619
|
+
compatibility = next(
|
|
1620
|
+
(preset for preset in matches if preset.protocol == OPENAI_COMPAT_PROTOCOL),
|
|
1621
|
+
None,
|
|
1622
|
+
)
|
|
1623
|
+
return compatibility or matches[0]
|
|
1624
|
+
|
|
1625
|
+
|
|
1626
|
+
def _profile_matches_preset(profile: ProfileSpec, preset: ProfilePreset) -> bool:
|
|
1627
|
+
if str(profile.protocol or OPENAI_COMPAT_PROTOCOL).strip() != preset.protocol:
|
|
1628
|
+
return False
|
|
1629
|
+
profile_url = _normalized_base_url(profile.base_url)
|
|
1630
|
+
preset_url = _normalized_base_url(preset.base_url)
|
|
1631
|
+
if not profile_url or not preset_url or profile_url != preset_url:
|
|
1632
|
+
return False
|
|
1633
|
+
return True
|
|
1634
|
+
|
|
1635
|
+
|
|
1636
|
+
def profile_provider_family(profile: ProfileSpec) -> str | None:
|
|
1637
|
+
"""Resolve a profile to a first-party family for protocol conversion and diagnostics."""
|
|
1638
|
+
protocol = str(profile.protocol or OPENAI_COMPAT_PROTOCOL).strip()
|
|
1639
|
+
if protocol == OPENAI_RESPONSES_PROTOCOL:
|
|
1640
|
+
return "openai"
|
|
1641
|
+
if protocol == ANTHROPIC_MESSAGES_PROTOCOL:
|
|
1642
|
+
return "anthropic"
|
|
1643
|
+
if protocol == GEMINI_GENERATE_CONTENT_PROTOCOL:
|
|
1644
|
+
return "gemini"
|
|
1645
|
+
if protocol == GEMINI_INTERACTIONS_PROTOCOL:
|
|
1646
|
+
return "gemini"
|
|
1647
|
+
|
|
1648
|
+
preset = get_preset(profile.name)
|
|
1649
|
+
if preset is not None:
|
|
1650
|
+
if preset.key in {"openai", "openai-responses"}:
|
|
1651
|
+
return "openai"
|
|
1652
|
+
if preset.key in {"anthropic", "anthropic-compat", "anthropic-native"}:
|
|
1653
|
+
return "anthropic"
|
|
1654
|
+
if preset.key in {"gemini", "gemini-compat", "gemini-native"}:
|
|
1655
|
+
return "gemini"
|
|
1656
|
+
|
|
1657
|
+
normalized_name = str(profile.name or "").strip().lower()
|
|
1658
|
+
if "openai" in normalized_name:
|
|
1659
|
+
return "openai"
|
|
1660
|
+
if "anthropic" in normalized_name or "claude" in normalized_name:
|
|
1661
|
+
return "anthropic"
|
|
1662
|
+
if "gemini" in normalized_name or "google" in normalized_name:
|
|
1663
|
+
return "gemini"
|
|
1664
|
+
|
|
1665
|
+
parsed = _split_base_url(profile.base_url)
|
|
1666
|
+
if parsed[0] == "api.openai.com":
|
|
1667
|
+
return "openai"
|
|
1668
|
+
if parsed[0] == "api.anthropic.com":
|
|
1669
|
+
return "anthropic"
|
|
1670
|
+
if parsed[0] == "generativelanguage.googleapis.com":
|
|
1671
|
+
return "gemini"
|
|
1672
|
+
return None
|
|
1673
|
+
|
|
1674
|
+
|
|
1675
|
+
def target_preset_for_profile_conversion(
|
|
1676
|
+
profile: ProfileSpec,
|
|
1677
|
+
*,
|
|
1678
|
+
target: str,
|
|
1679
|
+
) -> ProfilePreset | None:
|
|
1680
|
+
normalized_target = normalize_conversion_target(target)
|
|
1681
|
+
family = profile_provider_family(profile)
|
|
1682
|
+
if family is None:
|
|
1683
|
+
return None
|
|
1684
|
+
preset_key = _CONVERSION_PRESET_BY_FAMILY.get(family, {}).get(normalized_target)
|
|
1685
|
+
if preset_key is None:
|
|
1686
|
+
return None
|
|
1687
|
+
return get_preset(preset_key)
|
|
1688
|
+
|
|
1689
|
+
|
|
1690
|
+
def normalize_conversion_target(value: str) -> str:
|
|
1691
|
+
target = str(value or "").strip().lower().replace("_", "-")
|
|
1692
|
+
if target in {"native", "first-party", "firstparty"}:
|
|
1693
|
+
return "native"
|
|
1694
|
+
if target in {"compat", "compatibility", "openai-compatible", "gateway"}:
|
|
1695
|
+
return "compatibility"
|
|
1696
|
+
raise ValueError("conversion target must be 'native' or 'compatibility'")
|
|
1697
|
+
|
|
1698
|
+
|
|
1699
|
+
def convert_profile_to_preset(profile: ProfileSpec, preset: ProfilePreset) -> ProfileSpec:
|
|
1700
|
+
current_model = str(profile.default_model or "").strip()
|
|
1701
|
+
default_model = canonical_model_alias_for_preset(preset, current_model)
|
|
1702
|
+
target_family = _preset_provider_family(preset)
|
|
1703
|
+
if not default_model or _model_known_incompatible_with_family(default_model, target_family):
|
|
1704
|
+
default_model = preset.suggested_models[0] if preset.suggested_models else ""
|
|
1705
|
+
notes = _converted_profile_notes(profile, preset)
|
|
1706
|
+
|
|
1707
|
+
return ProfileSpec(
|
|
1708
|
+
name=profile.name,
|
|
1709
|
+
protocol=preset.protocol,
|
|
1710
|
+
base_url=preset.base_url,
|
|
1711
|
+
api_key_env=profile.api_key_env or preset.api_key_env,
|
|
1712
|
+
extra_headers=dict(profile.extra_headers),
|
|
1713
|
+
default_model=default_model,
|
|
1714
|
+
reasoning_effort=profile.reasoning_effort,
|
|
1715
|
+
web_search_adapter=preset.web_search_adapter,
|
|
1716
|
+
web_search_model=preset.web_search_model,
|
|
1717
|
+
notes=notes,
|
|
1718
|
+
)
|
|
1719
|
+
|
|
1720
|
+
|
|
1721
|
+
def _converted_profile_notes(profile: ProfileSpec, preset: ProfilePreset) -> str:
|
|
1722
|
+
notes = str(profile.notes or "").strip()
|
|
1723
|
+
if not notes:
|
|
1724
|
+
return preset.notes
|
|
1725
|
+
source_preset = find_preset_for_profile(profile)
|
|
1726
|
+
if source_preset is not None and notes == str(source_preset.notes or "").strip():
|
|
1727
|
+
return preset.notes
|
|
1728
|
+
|
|
1729
|
+
lowered = notes.lower()
|
|
1730
|
+
target_is_native = preset.protocol in NATIVE_PROFILE_PROTOCOLS
|
|
1731
|
+
if target_is_native and (
|
|
1732
|
+
"openai-compat" in lowered
|
|
1733
|
+
or "openai compatible" in lowered
|
|
1734
|
+
or "openai-compatible" in lowered
|
|
1735
|
+
or "compatibility mode" in lowered
|
|
1736
|
+
):
|
|
1737
|
+
return preset.notes
|
|
1738
|
+
if not target_is_native and "native" in lowered:
|
|
1739
|
+
return preset.notes
|
|
1740
|
+
return notes
|
|
1741
|
+
|
|
1742
|
+
|
|
1743
|
+
def _split_base_url(value: str | None) -> tuple[str, str]:
|
|
1744
|
+
try:
|
|
1745
|
+
parsed = urlsplit(str(value or "").strip())
|
|
1746
|
+
except ValueError:
|
|
1747
|
+
return "", ""
|
|
1748
|
+
path = parsed.path.rstrip("/").lower()
|
|
1749
|
+
return (parsed.hostname or "").rstrip(".").lower(), path
|
|
1750
|
+
|
|
1751
|
+
|
|
1752
|
+
def _preset_provider_family(preset: ProfilePreset) -> str | None:
|
|
1753
|
+
for family, targets in _CONVERSION_PRESET_BY_FAMILY.items():
|
|
1754
|
+
if preset.key in targets.values():
|
|
1755
|
+
return family
|
|
1756
|
+
return None
|
|
1757
|
+
|
|
1758
|
+
|
|
1759
|
+
def _model_known_incompatible_with_family(model: str, family: str | None) -> bool:
|
|
1760
|
+
if family is None:
|
|
1761
|
+
return False
|
|
1762
|
+
normalized = model.strip().lower()
|
|
1763
|
+
model_family = _known_model_family(normalized)
|
|
1764
|
+
if model_family is None:
|
|
1765
|
+
return False
|
|
1766
|
+
if model_family != family:
|
|
1767
|
+
return True
|
|
1768
|
+
return _has_known_provider_namespace(normalized)
|
|
1769
|
+
|
|
1770
|
+
|
|
1771
|
+
def known_model_family(model: str) -> str | None:
|
|
1772
|
+
"""Best-effort model-family classifier for static diagnostics.
|
|
1773
|
+
|
|
1774
|
+
This is intentionally conservative. Unknown custom gateway models return None so doctor
|
|
1775
|
+
diagnostics do not over-warn on valid provider-specific names Alysis Code cannot know offline.
|
|
1776
|
+
"""
|
|
1777
|
+
return _known_model_family(str(model or "").strip().lower())
|
|
1778
|
+
|
|
1779
|
+
|
|
1780
|
+
def model_known_incompatible_with_family(model: str, family: str | None) -> bool:
|
|
1781
|
+
"""Public wrapper used by diagnostics and tests."""
|
|
1782
|
+
return _model_known_incompatible_with_family(model, family)
|
|
1783
|
+
|
|
1784
|
+
|
|
1785
|
+
def _known_model_family(model: str) -> str | None:
|
|
1786
|
+
known_prefixes: dict[str, tuple[str, ...]] = {
|
|
1787
|
+
"openai": ("gpt-", "chatgpt-", "o1", "o3", "o4", "o5"),
|
|
1788
|
+
"anthropic": ("claude-",),
|
|
1789
|
+
"gemini": ("gemini-",),
|
|
1790
|
+
}
|
|
1791
|
+
known_namespaces: dict[str, tuple[str, ...]] = {
|
|
1792
|
+
"openai": ("openai",),
|
|
1793
|
+
"anthropic": ("anthropic", "anthropic-ai"),
|
|
1794
|
+
"gemini": ("google", "gemini"),
|
|
1795
|
+
}
|
|
1796
|
+
parts = [part for part in model.split("/") if part]
|
|
1797
|
+
for known_family, namespaces in known_namespaces.items():
|
|
1798
|
+
if parts and parts[0] in namespaces:
|
|
1799
|
+
return known_family
|
|
1800
|
+
model_id = parts[-1] if parts else model
|
|
1801
|
+
for known_family, prefixes in known_prefixes.items():
|
|
1802
|
+
if model_id.startswith(prefixes):
|
|
1803
|
+
return known_family
|
|
1804
|
+
return None
|
|
1805
|
+
|
|
1806
|
+
|
|
1807
|
+
def _has_known_provider_namespace(model: str) -> bool:
|
|
1808
|
+
if "/" not in model:
|
|
1809
|
+
return False
|
|
1810
|
+
namespace = model.split("/", 1)[0]
|
|
1811
|
+
return namespace in {"openai", "anthropic", "anthropic-ai", "google", "gemini"}
|
|
1812
|
+
|
|
1813
|
+
|
|
1814
|
+
def _normalized_base_url(value: str | None) -> str:
|
|
1815
|
+
return str(value or "").strip().rstrip("/")
|
|
1816
|
+
|
|
1817
|
+
|
|
1818
|
+
def make_profile_from_preset(
|
|
1819
|
+
preset: ProfilePreset,
|
|
1820
|
+
*,
|
|
1821
|
+
name: str | None = None,
|
|
1822
|
+
) -> ProfileSpec:
|
|
1823
|
+
profile_name = str(name or preset.key).strip().lower()
|
|
1824
|
+
return ProfileSpec(
|
|
1825
|
+
name=profile_name,
|
|
1826
|
+
protocol=preset.protocol,
|
|
1827
|
+
base_url=preset.base_url,
|
|
1828
|
+
api_key_env=preset.api_key_env,
|
|
1829
|
+
extra_headers=dict(preset.extra_headers),
|
|
1830
|
+
default_model=preset.suggested_models[0] if preset.suggested_models else "",
|
|
1831
|
+
web_search_adapter=preset.web_search_adapter,
|
|
1832
|
+
web_search_model=preset.web_search_model,
|
|
1833
|
+
notes=preset.notes,
|
|
1834
|
+
)
|