coderouter-cli 2.9.4__tar.gz → 2.11.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/CHANGELOG.md +193 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/PKG-INFO +5 -1
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/README.en.md +3 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/README.md +4 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/cli.py +125 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/config/schemas.py +144 -10
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/ingress/launcher_routes.py +289 -22
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/launcher_devices.py +188 -4
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/launcher_speculative.py +5 -1
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/launcher_swap.py +11 -2
- coderouter_cli-2.11.0/coderouter/vscode_init.py +575 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/README.md +2 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/backends/launcher-quickstart.en.md +2 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/backends/launcher-quickstart.md +2 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/backends/launcher.en.md +114 -1
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/backends/launcher.md +179 -1
- coderouter_cli-2.11.0/docs/designs/launcher-multi-build.md +464 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/guides/troubleshooting.md +47 -0
- coderouter_cli-2.11.0/docs/guides/vscode.md +163 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/examples/README.md +1 -1
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/examples/providers.llamacpp-vllm.yaml +31 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/pyproject.toml +1 -1
- coderouter_cli-2.11.0/tests/test_launcher_backend_variants.py +403 -0
- coderouter_cli-2.11.0/tests/test_launcher_variant_config.py +387 -0
- coderouter_cli-2.11.0/tests/test_launcher_variant_gui.py +222 -0
- coderouter_cli-2.11.0/tests/test_launcher_variant_routes.py +411 -0
- coderouter_cli-2.11.0/tests/test_launcher_variant_sweep.py +270 -0
- coderouter_cli-2.11.0/tests/test_vscode_init.py +558 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/.gitignore +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/LICENSE +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/__init__.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/__main__.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/adapters/__init__.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/adapters/anthropic_native.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/adapters/base.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/adapters/openai_compat.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/adapters/registry.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/cli_stats.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/config/__init__.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/config/capability_registry.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/config/env_file.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/config/loader.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/cost.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/data/__init__.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/data/model-capabilities.yaml +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/doctor.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/doctor_apply.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/env_security.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/errors.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/gguf_introspect.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/guards/__init__.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/guards/_fingerprint.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/guards/backend_health.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/guards/context_budget.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/guards/continuous_probe.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/guards/drift_actions.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/guards/drift_detection.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/guards/memory_budget.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/guards/memory_pressure.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/guards/self_healing.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/guards/tool_loop.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/hardware.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/ingress/__init__.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/ingress/anthropic_routes.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/ingress/app.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/ingress/dashboard_routes.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/ingress/metrics_routes.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/ingress/openai_routes.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/language_tax.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/logging.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/metrics/__init__.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/metrics/collector.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/metrics/prometheus.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/output_filters.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/plugins/__init__.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/plugins/base.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/plugins/loader.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/plugins/registry.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/routing/__init__.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/routing/adaptive.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/routing/auto_router.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/routing/budget.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/routing/capability.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/routing/fallback.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/state/__init__.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/state/audit_log.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/state/replay.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/state/request_log.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/state/store.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/state/suggest_rules.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/token_estimation.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/token_estimation_accurate.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/translation/__init__.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/translation/anthropic.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/translation/convert.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/coderouter/translation/tool_repair.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/README.en.md +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/assets/dashboard-demo.png +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/backends/claude-code-llamacpp-vllm.en.md +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/backends/claude-code-llamacpp-vllm.md +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/backends/external-agents.en.md +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/backends/external-agents.md +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/backends/gguf_dl.en.md +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/backends/gguf_dl.md +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/backends/hf-ollama-models.en.md +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/backends/hf-ollama-models.md +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/backends/install-backends.en.md +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/backends/install-backends.md +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/backends/llamacpp-direct.en.md +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/backends/llamacpp-direct.md +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/backends/lmstudio-direct.en.md +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/backends/lmstudio-direct.md +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/backends/verify-ollama-0.23.1.md +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/concepts/architecture.en.md +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/concepts/architecture.md +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/concepts/context-budget.en.md +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/concepts/context-budget.md +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/concepts/continuous-probing.en.md +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/concepts/continuous-probing.md +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/concepts/drift-detection.en.md +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/concepts/drift-detection.md +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/concepts/partial-stitch.en.md +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/concepts/partial-stitch.md +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/designs/agent-cli-plugin-extraction.md +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/designs/external-agents-adapter.md +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/designs/launcher-model-swap.md +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/designs/orchestration-companion.md +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/designs/v1.5-dashboard-mockup.html +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/designs/v1.6-auto-router-verification.md +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/designs/v1.6-auto-router.md +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/guides/free-tier-guide.en.md +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/guides/free-tier-guide.md +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/guides/language-tax.en.md +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/guides/language-tax.md +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/guides/remote-access.en.md +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/guides/remote-access.md +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/guides/security.en.md +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/guides/security.md +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/guides/subagent-routing.en.md +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/guides/subagent-routing.md +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/guides/troubleshooting.en.md +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/guides/usage-guide.en.md +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/guides/usage-guide.md +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/low-memory-integration.en.md +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/low-memory-integration.md +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/openrouter-roster/CHANGES.md +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/openrouter-roster/README.md +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/openrouter-roster/latest.json +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/retrospectives/v0.4.md +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/retrospectives/v0.5-verify.md +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/retrospectives/v0.5.md +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/retrospectives/v0.6.md +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/retrospectives/v0.7.md +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/retrospectives/v1.0-verify.md +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/retrospectives/v1.0.md +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/start/quickstart.en.md +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/start/quickstart.md +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/start/when-do-i-need-coderouter.en.md +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/docs/start/when-do-i-need-coderouter.md +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/examples/.env.example +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/examples/providers-agent-cli.yaml +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/examples/providers-multiagent.yaml +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/examples/providers.context-budget-test.yaml +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/examples/providers.nvidia-nim.yaml +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/examples/providers.ollama-auto-custom.yaml +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/examples/providers.ollama-auto.yaml +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/examples/providers.ollama-free-chain.yaml +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/examples/providers.raspberrypi.yaml +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/examples/providers.swap.yaml +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/examples/providers.yaml +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/scripts/demo_traffic.sh +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/scripts/openrouter_roster_diff.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/scripts/smoke_v2_2.sh +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/scripts/verify-providers.yaml +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/scripts/verify_ollama_0_23.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/scripts/verify_v0_5.sh +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/scripts/verify_v1_0.sh +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/__init__.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/conftest.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_adapter_anthropic.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_agent_cli.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_audit_log.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_auto_router.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_auto_router_cjk.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_backend_health.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_budget.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_capability.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_capability_degraded_payload.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_capability_registry.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_capability_registry_cache_control.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_capability_tool_choice.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_claude_code_suitability.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_cli.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_cli_bind_warning.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_cli_stats.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_config.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_config_shim_actions.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_context_budget.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_continuous_probe.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_dashboard_endpoint.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_doctor.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_doctor_apply.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_doctor_cache_probe.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_drift_actions.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_drift_detection.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_drift_detection_integration.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_env_file.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_env_security.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_errors.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_examples_yaml.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_fallback.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_fallback_anthropic.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_fallback_cache_control.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_fallback_cache_observed.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_fallback_cache_strip.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_fallback_empty_response.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_fallback_misconfig_warn.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_fallback_paid_gate.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_fallback_thinking.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_fallback_tool_choice_emulate.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_fix_h1_prometheus_drift.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_fix_h2_h6_translation.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_fix_h3_client_reuse.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_fix_h4_h5_guards.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_fix_h7_probe_restore.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_fix_h8_launcher_auth.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_fix_mA_routing.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_fix_mB_adapters.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_fix_mC_convert.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_fix_mD_logging_metrics.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_fix_mE_config_validation.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_fix_mF_ingress.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_gguf_introspect.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_guards_tool_loop.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_hardware.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_ingress_anthropic.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_ingress_count_tokens.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_ingress_profile.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_language_tax.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_language_tax_integration.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_launcher_config_bench.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_launcher_devices.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_launcher_devices_detect.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_launcher_devices_routes.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_launcher_gui_devices.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_launcher_gui_readiness.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_launcher_mtp.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_launcher_mtp_fallback.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_launcher_provider_sync.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_launcher_readiness_restart.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_launcher_swap.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_launcher_swap_review.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_memory_budget.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_memory_pressure.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_metrics_cache.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_metrics_collector.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_metrics_cost.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_metrics_endpoint.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_metrics_jsonl.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_metrics_prometheus.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_metrics_prometheus_cache.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_models_passthrough.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_openai_compat.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_openrouter_roster_diff.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_output_filters.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_output_filters_adapters.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_partial_stitch.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_plugin_adapter.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_plugins_integration.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_plugins_loader.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_plugins_registry.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_reasoning_strip.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_repair_byte_fallback.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_request_log.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_role_normalization.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_routing_adaptive.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_self_healing.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_setup_sh.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_state_store.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_token_estimation.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_token_estimation_accurate.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_tokens_saved_metric.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_tool_repair.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_tool_repair_lenient.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_tool_repair_r4.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_toolrepair_bench.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_translation_anthropic.py +0 -0
- {coderouter_cli-2.9.4 → coderouter_cli-2.11.0}/tests/test_translation_reverse.py +0 -0
|
@@ -9,6 +9,199 @@ are kept verbatim where the Japanese text itself is the subject).
|
|
|
9
9
|
|
|
10
10
|
---
|
|
11
11
|
|
|
12
|
+
## [v2.11.0] — 2026-07-28 (launcher backend variants)
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
- **Backend variants — pick which llama.cpp build to launch.**
|
|
17
|
+
`launcher.backends` now accepts keys of the form `<base>-<variant>`
|
|
18
|
+
(`llama.cpp-cuda`, `llama.cpp-vulkan`, `llama.cpp-rocm`), each naming
|
|
19
|
+
an additional build of the same backend with its own `binary` path.
|
|
20
|
+
Declared variants appear as extra entries in the Launcher's backend
|
|
21
|
+
select (GUI and Web) marked `⚙`, and each one gets its own
|
|
22
|
+
`--list-devices` probe, its own `option_profiles`, and can be pinned
|
|
23
|
+
per model in `launcher.swap`. Motivation: on a machine with mixed
|
|
24
|
+
GPUs the visible devices differ per build — the CUDA build enumerates
|
|
25
|
+
`CUDA0`/`CUDA1` (RTX 5090 + 3090) while the Vulkan build also
|
|
26
|
+
enumerates `Vulkan2` (Radeon 8060S) and the ROCm build only the
|
|
27
|
+
Radeon — so the best build varies by model. Previously `binary` held
|
|
28
|
+
a single path and switching meant editing `providers.yaml` and
|
|
29
|
+
restarting. Docs: `docs/backends/launcher.md` "特化ビルドの切り替え",
|
|
30
|
+
design: `docs/designs/launcher-multi-build.md`.
|
|
31
|
+
- **`option_profiles` inheritance for variants.** A variant key
|
|
32
|
+
inherits the base backend's presets and appends its own; a preset
|
|
33
|
+
whose `name` collides replaces the inherited one *in place* (order
|
|
34
|
+
stays stable, no duplicate at the tail). Shared presets no longer
|
|
35
|
+
need duplicating under every variant key. Shared implementation:
|
|
36
|
+
`launcher_devices.resolve_option_profiles` (used by the Web routes,
|
|
37
|
+
the Tk GUI and `launcher_swap`).
|
|
38
|
+
- **Cross-build bench sweep.** With two or more llama.cpp builds
|
|
39
|
+
declared, the sweep panel shows a "⚙ ビルド横断" button that probes
|
|
40
|
+
every build and generates configurations labelled
|
|
41
|
+
`cuda / CUDA0 単体`, `vulkan / Vulkan2 単体`, … Running the sweep
|
|
42
|
+
launches the same model on each build in turn, so one sweep answers
|
|
43
|
+
"which build is fastest for this model". `SweepStep.backend` /
|
|
44
|
+
`SweepConfigItem.backend` carry the per-step build; `None` keeps the
|
|
45
|
+
previous plan-wide behaviour. New
|
|
46
|
+
`launcher_devices.build_cross_variant_sweep_configs`. Configurations
|
|
47
|
+
never mix devices across builds — one process runs one executable.
|
|
48
|
+
- **Device-id namespace guard.** Device ids are build-specific
|
|
49
|
+
(`CUDA0` and `Vulkan0` are not the same GPU). Switching backend in
|
|
50
|
+
either launcher now clears the device selection, and
|
|
51
|
+
`POST /api/launcher/start` / `sweep/start` reject ids that do not
|
|
52
|
+
exist in the chosen build with a 400 instead of letting
|
|
53
|
+
`--device CUDA0` reach a Vulkan build and fail at startup. Skipped
|
|
54
|
+
when `--list-devices` itself fails (best-effort, per the
|
|
55
|
+
`hardware.py` invariant). New `launcher_devices.unknown_device_ids`.
|
|
56
|
+
|
|
57
|
+
### Changed
|
|
58
|
+
|
|
59
|
+
- **BREAKING: `launcher.backends` keys are now validated.** A key must
|
|
60
|
+
be `llama.cpp` / `vllm` / `mlx` or one of those with a
|
|
61
|
+
`-<variant>` suffix (variant matching `[a-z0-9][a-z0-9._-]*`).
|
|
62
|
+
Previously any key was accepted and silently ignored, because the
|
|
63
|
+
backend list was a hard-coded set of three; a typo such as
|
|
64
|
+
`llamacpp:` therefore had no effect and no warning. It is now a
|
|
65
|
+
config-load error. Check key spelling if startup fails after
|
|
66
|
+
upgrading.
|
|
67
|
+
- **A backend variant must set `binary`.** Allowing it to be omitted
|
|
68
|
+
would fall back to the base default on PATH, meaning an operator who
|
|
69
|
+
selected `llama.cpp-cuda` could silently get the plain build — the
|
|
70
|
+
hardest failure of this feature to notice. Rejected at config load.
|
|
71
|
+
Base keys keep `binary` optional (PATH resolution), unchanged.
|
|
72
|
+
- **The Launcher's backend list is now config-derived.** Both launchers
|
|
73
|
+
build the select from the three base backends plus whatever variants
|
|
74
|
+
`launcher.backends` declares, instead of a hard-coded list. Declaring
|
|
75
|
+
no variants yields exactly the previous three entries, so specialized
|
|
76
|
+
builds stay invisible to operators who have not opted in.
|
|
77
|
+
- `SwapModelSpec.backend` relaxed from
|
|
78
|
+
`Literal["llama.cpp","vllm","mlx"]` to a validated `str` so it can
|
|
79
|
+
name a variant; the three previous values still validate unchanged.
|
|
80
|
+
When a variant is named, config load verifies it is declared in
|
|
81
|
+
`launcher.backends`.
|
|
82
|
+
- `GET /api/launcher/backends` entries gained `base` and `variant`
|
|
83
|
+
keys. All pre-existing keys (`resolved` / `configured` / `default` /
|
|
84
|
+
`is_custom` / `found`) are unchanged.
|
|
85
|
+
|
|
86
|
+
### Fixed
|
|
87
|
+
|
|
88
|
+
- **Backend-name branches are normalized through a single helper.**
|
|
89
|
+
Backend name drove behaviour in ten places, several of which would
|
|
90
|
+
have failed *open* for a variant name rather than raising. Two
|
|
91
|
+
mattered: `_MODEL_FLAGS.get(backend, frozenset())` would have
|
|
92
|
+
returned an empty set and **disabled the H8 model-override guard**
|
|
93
|
+
(letting `options` / `extra_args` re-specify `-m` and load an
|
|
94
|
+
arbitrary model), and `_backend_ready`'s
|
|
95
|
+
`backend in ("llama.cpp","vllm")` would have degraded readiness to a
|
|
96
|
+
bare TCP connect — re-introducing the bug readiness gating was added
|
|
97
|
+
to fix (provider registered before the model finished loading). All
|
|
98
|
+
branches now go through `launcher_devices.base_backend()`, in
|
|
99
|
+
`launcher_routes.py`, `launcher_speculative.py`, `launcher_gui.py`
|
|
100
|
+
and the inline SPA JS. `_assert_no_model_override` additionally
|
|
101
|
+
became fail-closed: an unrecognized base uses the union of every
|
|
102
|
+
banned flag set rather than an empty one.
|
|
103
|
+
|
|
104
|
+
### Tests
|
|
105
|
+
|
|
106
|
+
- 4 new files, 150 new cases (`test_launcher_backend_variants.py`,
|
|
107
|
+
`test_launcher_variant_config.py`, `test_launcher_variant_routes.py`,
|
|
108
|
+
`test_launcher_variant_sweep.py`, `test_launcher_variant_gui.py`).
|
|
109
|
+
The fail-open branches above each have a 1:1 regression test, plus
|
|
110
|
+
byte-identical-argv and unchanged-API-payload tests for configs
|
|
111
|
+
without variants. Suite: 2098 passed, ruff clean.
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## [v2.10.0] — 2026-07-20 (VSCode workspace scaffolder)
|
|
116
|
+
|
|
117
|
+
### Added
|
|
118
|
+
|
|
119
|
+
- **`coderouter vscode-init` — one-shot VSCode workspace scaffolder.**
|
|
120
|
+
Writes `.vscode/settings.json` with `terminal.integrated.env.osx` /
|
|
121
|
+
`.linux` / `.windows` populated so a Claude Code session launched
|
|
122
|
+
from VSCode's integrated terminal auto-points at CodeRouter with no
|
|
123
|
+
manual `ANTHROPIC_BASE_URL` juggling. Optionally emits a direnv
|
|
124
|
+
`.envrc` (`--with-envrc`). The command is **idempotent** (re-running
|
|
125
|
+
with the same arguments is a no-op) and **conflict-aware**: if an
|
|
126
|
+
existing `settings.json` has different values for one of our managed
|
|
127
|
+
keys, the file is left untouched and a unified diff is printed —
|
|
128
|
+
operators re-run with `--force` to overwrite. Unrelated top-level
|
|
129
|
+
keys (`editor.fontSize`, `python.testing.pytestEnabled`, etc.) and
|
|
130
|
+
unrelated env keys inside the terminal blocks (a user's `PATH`
|
|
131
|
+
tweak) are preserved verbatim on merge. All writes are atomic
|
|
132
|
+
(temp file + `os.replace`) so a partial write cannot corrupt an
|
|
133
|
+
existing `settings.json`. Non-Claude-Code extensions (Cline / Roo
|
|
134
|
+
Code / Kilo Code / Continue.dev) are handled by a cheat sheet
|
|
135
|
+
printed at end of run plus the fuller `docs/guides/vscode.md` —
|
|
136
|
+
`vscode-init` deliberately does NOT reach into those extensions'
|
|
137
|
+
own config schemas (each ships its own release cadence, so any
|
|
138
|
+
automation would need continuous maintenance to follow). The
|
|
139
|
+
Continue.dev cheat-sheet snippet is built via `json.dumps` rather
|
|
140
|
+
than hand-formatted concatenation, so it is guaranteed to be
|
|
141
|
+
syntactically valid JSON (an early hand-formatted version leaked
|
|
142
|
+
an extra `}` from mismatched f-string / plain-string brace
|
|
143
|
+
escaping; a test round-trips the snippet through `json.loads` to
|
|
144
|
+
pin the invariant). Options: `--target PATH` (default cwd),
|
|
145
|
+
`--port PORT` (default **8088**, matching every docs / quickstart
|
|
146
|
+
example — note that `coderouter serve` alone still defaults to
|
|
147
|
+
4000, so if you serve on 4000 pass `--port 4000` here too),
|
|
148
|
+
`--profile NAME` (adds `CODEROUTER_MODE=<profile>` to the terminal
|
|
149
|
+
env for header-less profile routing), `--with-envrc` (also emit
|
|
150
|
+
`.envrc`), `--dry-run` (compute diffs but write nothing —
|
|
151
|
+
byte-identical to the write path minus the final `os.replace`),
|
|
152
|
+
and `--force` (overwrite conflicting values). Exit codes: 0 clean,
|
|
153
|
+
2 conflicts (nothing was written for the conflicting file), 1
|
|
154
|
+
hard error (unparseable JSON, missing target directory, write
|
|
155
|
+
failure). Implementation lives in `coderouter/vscode_init.py`
|
|
156
|
+
(stdlib only — no new runtime deps, keeping the strict-5-package
|
|
157
|
+
rule in `pyproject.toml` intact); the CLI wrapper
|
|
158
|
+
(`_run_vscode_init` in `coderouter/cli.py`) mirrors the existing
|
|
159
|
+
`stats` / `audit` / `replay` "thin argparse plumbing + logic in a
|
|
160
|
+
sibling module" pattern. See `tests/test_vscode_init.py` (33 cases
|
|
161
|
+
across happy paths, merge preservation, conflict detection,
|
|
162
|
+
`--force`, `--dry-run` byte parity, `.envrc`, malformed inputs,
|
|
163
|
+
JSON validity of the Continue.dev snippet, and CLI wrapper
|
|
164
|
+
plumbing) and the new `docs/guides/vscode.md` for the full Cline /
|
|
165
|
+
Roo / Continue.dev cheat sheet.
|
|
166
|
+
|
|
167
|
+
### Documentation
|
|
168
|
+
|
|
169
|
+
- **Launcher port ↔ `providers.yaml` mismatch, three ways to prevent
|
|
170
|
+
it.** New section
|
|
171
|
+
["providers.yaml とのポート整合"](docs/backends/launcher.md#providersyaml-とのポート整合食い違いを構造的に防ぐ)
|
|
172
|
+
in the Launcher guide walks through the three coexisting patterns
|
|
173
|
+
— (A) hardcoded `providers.yaml` with matching Launcher port
|
|
174
|
+
(traditional), (B) v2.7.4 Launcher auto-sync
|
|
175
|
+
(`launcher-<backend>-<port>` provider names, no `providers.yaml`
|
|
176
|
+
edit needed), and (C) the recommended hybrid where
|
|
177
|
+
`option_profiles` pins the port so the Launcher UI and
|
|
178
|
+
`providers.yaml` cannot drift. Includes a copy-paste `cr-check`
|
|
179
|
+
shell function that runs `coderouter doctor --check-model <name>`
|
|
180
|
+
against every hand-declared provider before work begins so
|
|
181
|
+
operators catch a port mismatch in seconds rather than after a
|
|
182
|
+
session of quiet fallback churn. The symptom side (dashboard's
|
|
183
|
+
`unhealthy` badge + half-and-half `provider-failed` events in the
|
|
184
|
+
ring buffer while requests still succeed via fallback) is
|
|
185
|
+
documented as a new
|
|
186
|
+
[troubleshooting §1-7](docs/guides/troubleshooting.md#1-7-transport-error-all-connections-failed--ポート不一致の疑い)
|
|
187
|
+
entry, cross-linked back to the Launcher guide for the fix. Both
|
|
188
|
+
additions are Japanese-side only (English counterpart will follow
|
|
189
|
+
in a later docs-sync commit).
|
|
190
|
+
|
|
191
|
+
### Fixed
|
|
192
|
+
|
|
193
|
+
- **`ProviderConfig.timeout_s` upper bound raised from 600s (10 min) to
|
|
194
|
+
86400s (24h)** (#76, contributed by @firelzrd). The previous 10-minute
|
|
195
|
+
ceiling was too restrictive for long-running local model inference —
|
|
196
|
+
configurations that legitimately need multi-hour timeouts (heavy
|
|
197
|
+
reasoning models, large-context sweeps, batch operations) were being
|
|
198
|
+
rejected by the Pydantic `le=600` validator before the request could
|
|
199
|
+
even leave the router. The default (30s) and lower bound (1s) are
|
|
200
|
+
unchanged, so existing configs are unaffected; only users who were
|
|
201
|
+
hitting the ceiling gain the new headroom.
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
12
205
|
## [v2.9.4] — 2026-07-19 (launcher device selection & bench sweep, cache-stable system prompt)
|
|
13
206
|
|
|
14
207
|
### Added
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: coderouter-cli
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.11.0
|
|
4
4
|
Summary: Local-first, free-first, fallback-built-in LLM router. Claude Code / OpenAI compatible.
|
|
5
5
|
Project-URL: Homepage, https://github.com/zephel01/CodeRouter
|
|
6
6
|
Project-URL: Repository, https://github.com/zephel01/CodeRouter
|
|
@@ -132,6 +132,8 @@ ANTHROPIC_BASE_URL=http://localhost:8088 ANTHROPIC_AUTH_TOKEN=dummy claude
|
|
|
132
132
|
|
|
133
133
|
これだけ。Claude Code はいつも通り動きますが、裏ではローカルの Ollama が答えています。
|
|
134
134
|
|
|
135
|
+
**VSCode の統合ターミナルから使う場合** は、環境変数の書き忘れを避けるため `coderouter vscode-init` が便利です。プロジェクトルートで 1 回叩くと `.vscode/settings.json` に `terminal.integrated.env.*` をマージ書き込みするので、以後 VSCode のターミナルで `claude` と打つだけで通ります。Cline / Roo Code / Continue.dev の設定コピペも含めて → [VSCode 連携ガイド](./docs/guides/vscode.md)
|
|
136
|
+
|
|
135
137
|
---
|
|
136
138
|
|
|
137
139
|
## 自分に必要?
|
|
@@ -222,6 +224,7 @@ providers:
|
|
|
222
224
|
| **ログビューア** | 各プロセスの stdout/stderr をブラウザ内でリアルタイム確認 |
|
|
223
225
|
| **provider 自動同期** (v2.7.4) | 起動したバックエンドを provider として自動登録(`launcher-llamacpp-8085` 等)。providers.yaml 無編集で `X-CodeRouter-Profile: launcher` からルーティング可能。メモリ内のみ・serve と同寿命 |
|
|
224
226
|
| **モデル名パススルー** (v2.7.4) | `model: ""` の provider は `/v1/models` が上流のロード中モデル ID(gguf 名)をそのまま返す。gguf を差し替えても config 編集不要 — 外部ベンチからモデルを識別できる |
|
|
227
|
+
| **特化ビルドの切り替え** (v2.11.0) | `llama.cpp-cuda` / `-vulkan` / `-rocm` を `backends` に登録すると、起動ごとにどのビルドの `llama-server` を使うか選べる。ビルド別にデバイス検出・option_profiles・ベンチスイープが独立(書かなければ従来どおり) |
|
|
225
228
|
|
|
226
229
|
```yaml
|
|
227
230
|
# providers.yaml に追記するだけで有効になる
|
|
@@ -281,6 +284,7 @@ providers:
|
|
|
281
284
|
| 無料で回す | [無料枠ガイド](./docs/guides/free-tier-guide.md) |
|
|
282
285
|
| llama.cpp / vllm を GUI で起動 | [Launcher ガイド](./docs/backends/launcher.md) |
|
|
283
286
|
| 言語税を計測・回避する | [言語税ガイド](./docs/guides/language-tax.md) |
|
|
287
|
+
| VSCode / Cline / Continue から使う | [VSCode 連携ガイド](./docs/guides/vscode.md) |
|
|
284
288
|
| 別の PC から安全に繋ぐ | [リモートアクセスガイド](./docs/guides/remote-access.md) |
|
|
285
289
|
| 詰まった | [トラブルシューティング](./docs/guides/troubleshooting.md) |
|
|
286
290
|
| 設計を知りたい | [アーキテクチャ詳細](./docs/concepts/architecture.md) |
|
|
@@ -69,6 +69,8 @@ ANTHROPIC_BASE_URL=http://localhost:8088 ANTHROPIC_AUTH_TOKEN=dummy claude
|
|
|
69
69
|
|
|
70
70
|
That's it. Claude Code works as usual, but your local Ollama is answering behind the scenes.
|
|
71
71
|
|
|
72
|
+
**From VSCode's integrated terminal**, avoid the env-var footgun with `coderouter vscode-init`. Run it once at your project root and it merges `terminal.integrated.env.*` into `.vscode/settings.json`, so `claude` in VSCode's terminal just works from then on. Cheat-sheet snippets for Cline / Roo Code / Continue.dev are printed at the end of the same run → [VSCode integration guide](./docs/guides/vscode.md) (JP only for now).
|
|
73
|
+
|
|
72
74
|
---
|
|
73
75
|
|
|
74
76
|
## Do you need it?
|
|
@@ -217,6 +219,7 @@ More detail → [Usage guide](./docs/guides/usage-guide.en.md) · [Architecture]
|
|
|
217
219
|
| Run for free | [Free-tier guide](./docs/guides/free-tier-guide.en.md) |
|
|
218
220
|
| Launch llama.cpp / vllm via GUI | [Launcher guide](./docs/backends/launcher.md) |
|
|
219
221
|
| Measure & avoid the language tax | [Language Tax guide](./docs/guides/language-tax.en.md) |
|
|
222
|
+
| Use from VSCode / Cline / Continue | [VSCode integration guide](./docs/guides/vscode.md) (JP) |
|
|
220
223
|
| Reach it safely from another machine | [Remote access guide](./docs/guides/remote-access.en.md) |
|
|
221
224
|
| Stuck? | [Troubleshooting](./docs/guides/troubleshooting.en.md) |
|
|
222
225
|
| Understand the design | [Architecture](./docs/concepts/architecture.md) |
|
|
@@ -87,6 +87,8 @@ ANTHROPIC_BASE_URL=http://localhost:8088 ANTHROPIC_AUTH_TOKEN=dummy claude
|
|
|
87
87
|
|
|
88
88
|
これだけ。Claude Code はいつも通り動きますが、裏ではローカルの Ollama が答えています。
|
|
89
89
|
|
|
90
|
+
**VSCode の統合ターミナルから使う場合** は、環境変数の書き忘れを避けるため `coderouter vscode-init` が便利です。プロジェクトルートで 1 回叩くと `.vscode/settings.json` に `terminal.integrated.env.*` をマージ書き込みするので、以後 VSCode のターミナルで `claude` と打つだけで通ります。Cline / Roo Code / Continue.dev の設定コピペも含めて → [VSCode 連携ガイド](./docs/guides/vscode.md)
|
|
91
|
+
|
|
90
92
|
---
|
|
91
93
|
|
|
92
94
|
## 自分に必要?
|
|
@@ -177,6 +179,7 @@ providers:
|
|
|
177
179
|
| **ログビューア** | 各プロセスの stdout/stderr をブラウザ内でリアルタイム確認 |
|
|
178
180
|
| **provider 自動同期** (v2.7.4) | 起動したバックエンドを provider として自動登録(`launcher-llamacpp-8085` 等)。providers.yaml 無編集で `X-CodeRouter-Profile: launcher` からルーティング可能。メモリ内のみ・serve と同寿命 |
|
|
179
181
|
| **モデル名パススルー** (v2.7.4) | `model: ""` の provider は `/v1/models` が上流のロード中モデル ID(gguf 名)をそのまま返す。gguf を差し替えても config 編集不要 — 外部ベンチからモデルを識別できる |
|
|
182
|
+
| **特化ビルドの切り替え** (v2.11.0) | `llama.cpp-cuda` / `-vulkan` / `-rocm` を `backends` に登録すると、起動ごとにどのビルドの `llama-server` を使うか選べる。ビルド別にデバイス検出・option_profiles・ベンチスイープが独立(書かなければ従来どおり) |
|
|
180
183
|
|
|
181
184
|
```yaml
|
|
182
185
|
# providers.yaml に追記するだけで有効になる
|
|
@@ -236,6 +239,7 @@ providers:
|
|
|
236
239
|
| 無料で回す | [無料枠ガイド](./docs/guides/free-tier-guide.md) |
|
|
237
240
|
| llama.cpp / vllm を GUI で起動 | [Launcher ガイド](./docs/backends/launcher.md) |
|
|
238
241
|
| 言語税を計測・回避する | [言語税ガイド](./docs/guides/language-tax.md) |
|
|
242
|
+
| VSCode / Cline / Continue から使う | [VSCode 連携ガイド](./docs/guides/vscode.md) |
|
|
239
243
|
| 別の PC から安全に繋ぐ | [リモートアクセスガイド](./docs/guides/remote-access.md) |
|
|
240
244
|
| 詰まった | [トラブルシューティング](./docs/guides/troubleshooting.md) |
|
|
241
245
|
| 設計を知りたい | [アーキテクチャ詳細](./docs/concepts/architecture.md) |
|
|
@@ -336,6 +336,78 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
336
336
|
),
|
|
337
337
|
)
|
|
338
338
|
|
|
339
|
+
# v2.10-A: `coderouter vscode-init` — scaffold a VSCode workspace so
|
|
340
|
+
# Claude Code launched from the integrated terminal auto-points at
|
|
341
|
+
# CodeRouter (no manual env-var juggling). Optionally writes .envrc
|
|
342
|
+
# for direnv users. Cline / Roo / Continue are covered by the cheat
|
|
343
|
+
# sheet printed on completion and docs/guides/vscode.md — this
|
|
344
|
+
# command deliberately does NOT touch those extensions' settings
|
|
345
|
+
# (their schemas change with their own release cadence).
|
|
346
|
+
vscode_init = sub.add_parser(
|
|
347
|
+
"vscode-init",
|
|
348
|
+
help="Scaffold VSCode workspace settings for CodeRouter (v2.10-A).",
|
|
349
|
+
description=(
|
|
350
|
+
"Write .vscode/settings.json (terminal.integrated.env.*) so a "
|
|
351
|
+
"Claude Code session launched from VSCode's integrated terminal "
|
|
352
|
+
"auto-points at CodeRouter. Optionally emit a direnv .envrc. "
|
|
353
|
+
"Idempotent: safe to re-run. Conflict-aware: refuses to overwrite "
|
|
354
|
+
"differing existing values without --force."
|
|
355
|
+
),
|
|
356
|
+
)
|
|
357
|
+
vscode_init.add_argument(
|
|
358
|
+
"--target",
|
|
359
|
+
default=".",
|
|
360
|
+
metavar="PATH",
|
|
361
|
+
help="Workspace root (default: current directory).",
|
|
362
|
+
)
|
|
363
|
+
vscode_init.add_argument(
|
|
364
|
+
"--port",
|
|
365
|
+
type=int,
|
|
366
|
+
default=None,
|
|
367
|
+
metavar="PORT",
|
|
368
|
+
help=(
|
|
369
|
+
"CodeRouter port for ANTHROPIC_BASE_URL. Defaults to 8088 "
|
|
370
|
+
"(matches every docs / quickstart example). Note that "
|
|
371
|
+
"`coderouter serve` alone defaults to 4000; if you serve on "
|
|
372
|
+
"4000, pass --port 4000 here too."
|
|
373
|
+
),
|
|
374
|
+
)
|
|
375
|
+
vscode_init.add_argument(
|
|
376
|
+
"--profile",
|
|
377
|
+
default=None,
|
|
378
|
+
metavar="NAME",
|
|
379
|
+
help=(
|
|
380
|
+
"Preload CODEROUTER_MODE=<profile> so the VSCode terminal "
|
|
381
|
+
"routes to a non-default profile without a per-request header."
|
|
382
|
+
),
|
|
383
|
+
)
|
|
384
|
+
vscode_init.add_argument(
|
|
385
|
+
"--with-envrc",
|
|
386
|
+
action="store_true",
|
|
387
|
+
help=(
|
|
388
|
+
"Also write .envrc (direnv). Run `direnv allow` once after "
|
|
389
|
+
"generation. Tip: keep secrets in a separate .envrc.local."
|
|
390
|
+
),
|
|
391
|
+
)
|
|
392
|
+
vscode_init.add_argument(
|
|
393
|
+
"--dry-run",
|
|
394
|
+
action="store_true",
|
|
395
|
+
help=(
|
|
396
|
+
"Compute all changes and print unified diffs, but do not write "
|
|
397
|
+
"any files. Byte-identical to the write path minus the final "
|
|
398
|
+
"os.replace."
|
|
399
|
+
),
|
|
400
|
+
)
|
|
401
|
+
vscode_init.add_argument(
|
|
402
|
+
"--force",
|
|
403
|
+
action="store_true",
|
|
404
|
+
help=(
|
|
405
|
+
"Overwrite existing conflicting values. Without this flag, a "
|
|
406
|
+
"conflict is reported with a diff and the file is left "
|
|
407
|
+
"untouched (exit 2)."
|
|
408
|
+
),
|
|
409
|
+
)
|
|
410
|
+
|
|
339
411
|
return parser
|
|
340
412
|
|
|
341
413
|
|
|
@@ -432,6 +504,9 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
432
504
|
if args.command == "replay":
|
|
433
505
|
return _run_replay(args)
|
|
434
506
|
|
|
507
|
+
if args.command == "vscode-init":
|
|
508
|
+
return _run_vscode_init(args)
|
|
509
|
+
|
|
435
510
|
print(f"unknown command: {args.command}", file=sys.stderr)
|
|
436
511
|
return 2
|
|
437
512
|
|
|
@@ -765,6 +840,56 @@ def _run_replay(args: argparse.Namespace) -> int:
|
|
|
765
840
|
return 0
|
|
766
841
|
|
|
767
842
|
|
|
843
|
+
def _run_vscode_init(args: argparse.Namespace) -> int:
|
|
844
|
+
"""v2.10-A: drive :func:`coderouter.vscode_init.run_vscode_init`.
|
|
845
|
+
|
|
846
|
+
Kept small and testable — the actual scaffolding logic lives in
|
|
847
|
+
:mod:`coderouter.vscode_init` so tests can exercise it without
|
|
848
|
+
argparse in the way. This wrapper's job is:
|
|
849
|
+
|
|
850
|
+
* resolve the ``--target`` argument to a real directory
|
|
851
|
+
* map ``--port`` (default None) to the module's ``DEFAULT_PORT``
|
|
852
|
+
* translate exceptions (missing target directory) to a friendly
|
|
853
|
+
stderr message + exit 1
|
|
854
|
+
* print the formatted result and propagate the module's exit code
|
|
855
|
+
"""
|
|
856
|
+
from coderouter.vscode_init import (
|
|
857
|
+
DEFAULT_PORT,
|
|
858
|
+
exit_code_for,
|
|
859
|
+
format_result,
|
|
860
|
+
run_vscode_init,
|
|
861
|
+
)
|
|
862
|
+
|
|
863
|
+
target = Path(args.target).expanduser()
|
|
864
|
+
if not target.is_dir():
|
|
865
|
+
print(
|
|
866
|
+
f"vscode-init: target directory does not exist: {target}",
|
|
867
|
+
file=sys.stderr,
|
|
868
|
+
)
|
|
869
|
+
return 1
|
|
870
|
+
|
|
871
|
+
port = args.port if args.port is not None else DEFAULT_PORT
|
|
872
|
+
|
|
873
|
+
try:
|
|
874
|
+
result = run_vscode_init(
|
|
875
|
+
target,
|
|
876
|
+
port=port,
|
|
877
|
+
profile=args.profile,
|
|
878
|
+
with_envrc=args.with_envrc,
|
|
879
|
+
dry_run=args.dry_run,
|
|
880
|
+
force=args.force,
|
|
881
|
+
)
|
|
882
|
+
except FileNotFoundError as exc:
|
|
883
|
+
# Raised only when target vanishes between the pre-check above
|
|
884
|
+
# and the module's own check — unlikely in practice, but map
|
|
885
|
+
# it to the same shape as the pre-check for consistency.
|
|
886
|
+
print(f"vscode-init: {exc}", file=sys.stderr)
|
|
887
|
+
return 1
|
|
888
|
+
|
|
889
|
+
print(format_result(result, dry_run=args.dry_run, port=port))
|
|
890
|
+
return exit_code_for(result)
|
|
891
|
+
|
|
892
|
+
|
|
768
893
|
def _run_check_env(arg_value: str) -> int:
|
|
769
894
|
"""v1.6.3: filesystem / git security checks for `.env`.
|
|
770
895
|
|
|
@@ -17,7 +17,14 @@ import re
|
|
|
17
17
|
import warnings
|
|
18
18
|
from typing import Any, Literal, Self
|
|
19
19
|
|
|
20
|
-
from pydantic import
|
|
20
|
+
from pydantic import (
|
|
21
|
+
BaseModel,
|
|
22
|
+
ConfigDict,
|
|
23
|
+
Field,
|
|
24
|
+
HttpUrl,
|
|
25
|
+
field_validator,
|
|
26
|
+
model_validator,
|
|
27
|
+
)
|
|
21
28
|
|
|
22
29
|
|
|
23
30
|
class Capabilities(BaseModel):
|
|
@@ -394,7 +401,7 @@ class ProviderConfig(BaseModel):
|
|
|
394
401
|
default=False,
|
|
395
402
|
description="If true, only used when ALLOW_PAID=true (plan.md §2.3).",
|
|
396
403
|
)
|
|
397
|
-
timeout_s: float = Field(default=30.0, ge=1.0, le=
|
|
404
|
+
timeout_s: float = Field(default=30.0, ge=1.0, le=86400.0)
|
|
398
405
|
|
|
399
406
|
# v2.6 language-tax track: path to a LOCAL ``tokenizer.json`` for this
|
|
400
407
|
# provider's model, used to measure the CJK over-count vs the char/4
|
|
@@ -1414,6 +1421,29 @@ class LauncherBackendConfig(BaseModel):
|
|
|
1414
1421
|
binary: ~/llama.cpp/build/bin/llama-server
|
|
1415
1422
|
vllm:
|
|
1416
1423
|
binary: ~/.venv/bin/python
|
|
1424
|
+
|
|
1425
|
+
**Backend variants** (v2.11.0+, docs/designs/launcher-multi-build.md):
|
|
1426
|
+
a key may also be ``<base>-<variant>`` to register an additional build of
|
|
1427
|
+
the same backend — typically llama.cpp compiled for a specific GPU
|
|
1428
|
+
runtime. Each variant appears as its own entry in the Launcher's backend
|
|
1429
|
+
select, gets its own ``--list-devices`` probe (device IDs differ per
|
|
1430
|
+
build: ``CUDA0`` and ``Vulkan0`` are not the same GPU) and can carry its
|
|
1431
|
+
own ``option_profiles``. ``binary`` is **required** for a variant::
|
|
1432
|
+
|
|
1433
|
+
backends:
|
|
1434
|
+
llama.cpp: # 素のビルド (binary 省略可 = PATH)
|
|
1435
|
+
binary: ~/llm/apps/llama.cpp/build/bin/llama-server
|
|
1436
|
+
llama.cpp-cuda:
|
|
1437
|
+
binary: ~/llm/apps/llama.cpp/build-cuda/bin/llama-server
|
|
1438
|
+
llama.cpp-vulkan:
|
|
1439
|
+
binary: ~/llm/apps/llama.cpp/build-vulkan/bin/llama-server
|
|
1440
|
+
llama.cpp-rocm:
|
|
1441
|
+
binary: ~/llm/apps/llama.cpp/build-rocm/bin/llama-server
|
|
1442
|
+
|
|
1443
|
+
Variants are an advanced option: the matching GPU runtime (CUDA Toolkit /
|
|
1444
|
+
Vulkan runtime + ICD / ROCm) must already be installed by the operator.
|
|
1445
|
+
CodeRouter never selects a variant implicitly — omit them and both the UI
|
|
1446
|
+
and the resulting argv are identical to before.
|
|
1417
1447
|
"""
|
|
1418
1448
|
|
|
1419
1449
|
model_config = ConfigDict(extra="forbid")
|
|
@@ -1544,9 +1574,39 @@ class SwapModelSpec(BaseModel):
|
|
|
1544
1574
|
"only widens *catalog* matching for ``SwapManager.match``."
|
|
1545
1575
|
),
|
|
1546
1576
|
)
|
|
1547
|
-
backend:
|
|
1548
|
-
...,
|
|
1577
|
+
backend: str = Field(
|
|
1578
|
+
...,
|
|
1579
|
+
description=(
|
|
1580
|
+
"Same backend set as the manual launcher UI / _build_cmd: "
|
|
1581
|
+
"'llama.cpp' / 'vllm' / 'mlx', optionally with a '-<variant>' "
|
|
1582
|
+
"suffix naming a specific build declared in launcher.backends "
|
|
1583
|
+
"(e.g. 'llama.cpp-cuda' to pin this model to the CUDA build). "
|
|
1584
|
+
"Validated by the field validator below plus "
|
|
1585
|
+
"LauncherConfig._check_swap_backends_declared."
|
|
1586
|
+
),
|
|
1549
1587
|
)
|
|
1588
|
+
|
|
1589
|
+
@field_validator("backend")
|
|
1590
|
+
@classmethod
|
|
1591
|
+
def _check_backend_name(cls, v: str) -> str:
|
|
1592
|
+
"""基底名 or 既知基底名 + 妥当なバリアントのみ許す。
|
|
1593
|
+
|
|
1594
|
+
以前は ``Literal["llama.cpp","vllm","mlx"]`` だった。バリアント
|
|
1595
|
+
(``llama.cpp-cuda``) を通すため str に緩めたので、代わりに形式検証を
|
|
1596
|
+
ここで行う。既存の 3 値はそのまま通る (後方互換)。
|
|
1597
|
+
"""
|
|
1598
|
+
from coderouter.launcher_devices import (
|
|
1599
|
+
KNOWN_BASE_BACKENDS,
|
|
1600
|
+
is_valid_backend_name,
|
|
1601
|
+
)
|
|
1602
|
+
|
|
1603
|
+
if not is_valid_backend_name(v):
|
|
1604
|
+
raise ValueError(
|
|
1605
|
+
f"backend {v!r} is not valid. Expected one of "
|
|
1606
|
+
f"{list(KNOWN_BASE_BACKENDS)} or '<base>-<variant>' "
|
|
1607
|
+
"(e.g. 'llama.cpp-cuda')."
|
|
1608
|
+
)
|
|
1609
|
+
return v
|
|
1550
1610
|
model_path: str = Field(
|
|
1551
1611
|
...,
|
|
1552
1612
|
description=(
|
|
@@ -1802,10 +1862,13 @@ class LauncherConfig(BaseModel):
|
|
|
1802
1862
|
default_factory=dict,
|
|
1803
1863
|
description=(
|
|
1804
1864
|
"Per-backend binary path overrides. "
|
|
1805
|
-
"Keys are backend names ('llama.cpp', 'vllm')
|
|
1806
|
-
"
|
|
1807
|
-
"
|
|
1808
|
-
"
|
|
1865
|
+
"Keys are backend names ('llama.cpp', 'vllm', 'mlx') or backend "
|
|
1866
|
+
"variants ('llama.cpp-cuda', 'llama.cpp-vulkan', ...) naming an "
|
|
1867
|
+
"additional build of the same backend — see "
|
|
1868
|
+
"LauncherBackendConfig. When a base key is absent, the default "
|
|
1869
|
+
"executable is used ('llama-server' / 'python') and resolved via "
|
|
1870
|
+
"PATH. Variants must set 'binary' explicitly and additionally "
|
|
1871
|
+
"appear in the Launcher's backend select."
|
|
1809
1872
|
),
|
|
1810
1873
|
)
|
|
1811
1874
|
option_profiles: dict[str, list[LauncherOptionProfile]] = Field(
|
|
@@ -1813,6 +1876,10 @@ class LauncherConfig(BaseModel):
|
|
|
1813
1876
|
description=(
|
|
1814
1877
|
"Named option presets per backend. "
|
|
1815
1878
|
"Keys should be backend names: 'llama.cpp', 'vllm'. "
|
|
1879
|
+
"A backend-variant key ('llama.cpp-cuda') is also accepted: its "
|
|
1880
|
+
"presets are appended to the base backend's list, and a preset "
|
|
1881
|
+
"whose 'name' collides replaces the inherited one in place "
|
|
1882
|
+
"(see launcher_devices.resolve_option_profiles). "
|
|
1816
1883
|
"Each key maps to an ordered list of named presets. "
|
|
1817
1884
|
"A free-form 'extra args' field is always available in the UI "
|
|
1818
1885
|
"for one-off overrides without touching this config."
|
|
@@ -1929,15 +1996,82 @@ class LauncherConfig(BaseModel):
|
|
|
1929
1996
|
)
|
|
1930
1997
|
return self
|
|
1931
1998
|
|
|
1999
|
+
@model_validator(mode="after")
|
|
2000
|
+
def _check_backend_names_and_variant_binaries(self) -> LauncherConfig:
|
|
2001
|
+
"""``backends`` のキー形式と、バリアントの ``binary`` 必須を検証する。
|
|
2002
|
+
|
|
2003
|
+
設計: docs/designs/launcher-multi-build.md §5.2。
|
|
2004
|
+
|
|
2005
|
+
1. キーは既知基底名 (``llama.cpp`` / ``vllm`` / ``mlx``) そのもの、
|
|
2006
|
+
または ``<既知基底名>-<バリアント>`` (``llama.cpp-cuda`` 等) のみ。
|
|
2007
|
+
**破壊的変更**: これまで ``llamacpp:`` のような typo は黙って無視
|
|
2008
|
+
されていた (バックエンド一覧が固定 3 キーだったため)。今後は
|
|
2009
|
+
ロード時エラーになる。
|
|
2010
|
+
2. **バリアントは ``binary`` 必須**。``llama.cpp-cuda: {}`` を許すと
|
|
2011
|
+
既定名フォールバックで PATH の ``llama-server`` が使われ、CUDA
|
|
2012
|
+
ビルドを指定したつもりで素のビルドが静かに動く —— 本機能で最も
|
|
2013
|
+
気づきにくい事故なのでロード時に殺す。基底名は従来どおり
|
|
2014
|
+
``binary`` 省略可 (PATH 解決)。
|
|
2015
|
+
"""
|
|
2016
|
+
from coderouter.launcher_devices import (
|
|
2017
|
+
KNOWN_BASE_BACKENDS,
|
|
2018
|
+
is_valid_backend_name,
|
|
2019
|
+
is_variant,
|
|
2020
|
+
)
|
|
2021
|
+
|
|
2022
|
+
for name, bc in self.backends.items():
|
|
2023
|
+
if not is_valid_backend_name(name):
|
|
2024
|
+
raise ValueError(
|
|
2025
|
+
f"launcher.backends: invalid backend key {name!r}. "
|
|
2026
|
+
f"Expected one of {list(KNOWN_BASE_BACKENDS)} or "
|
|
2027
|
+
"'<base>-<variant>' where variant matches "
|
|
2028
|
+
"[a-z0-9][a-z0-9._-]* (e.g. 'llama.cpp-cuda')."
|
|
2029
|
+
)
|
|
2030
|
+
if is_variant(name) and not bc.binary:
|
|
2031
|
+
raise ValueError(
|
|
2032
|
+
f"launcher.backends[{name!r}]: 'binary' is required for a "
|
|
2033
|
+
"backend variant. Without it the launcher would fall back "
|
|
2034
|
+
"to the base default on PATH and silently run a different "
|
|
2035
|
+
"build than the one you selected."
|
|
2036
|
+
)
|
|
2037
|
+
return self
|
|
2038
|
+
|
|
2039
|
+
@model_validator(mode="after")
|
|
2040
|
+
def _check_swap_backends_declared(self) -> LauncherConfig:
|
|
2041
|
+
"""swap のモデルがバリアントを指すなら ``backends`` に実在すること。
|
|
2042
|
+
|
|
2043
|
+
設計 §5.2-3。基底名 (``llama.cpp`` 等) は ``backends`` に書かなくても
|
|
2044
|
+
PATH 解決で動くので従来どおり不要。バリアントは実行ファイルパスが
|
|
2045
|
+
``backends`` にしか無いので、宣言漏れをロード時に弾く。
|
|
2046
|
+
"""
|
|
2047
|
+
if self.swap is None:
|
|
2048
|
+
return self
|
|
2049
|
+
from coderouter.launcher_devices import is_variant
|
|
2050
|
+
|
|
2051
|
+
for spec in self.swap.models:
|
|
2052
|
+
if is_variant(spec.backend) and spec.backend not in self.backends:
|
|
2053
|
+
raise ValueError(
|
|
2054
|
+
f"launcher.swap.models[{spec.name!r}]: backend "
|
|
2055
|
+
f"{spec.backend!r} is a variant but is not declared in "
|
|
2056
|
+
"launcher.backends (its binary path is unknown)."
|
|
2057
|
+
)
|
|
2058
|
+
return self
|
|
2059
|
+
|
|
1932
2060
|
@model_validator(mode="after")
|
|
1933
2061
|
def _check_swap_option_profiles_exist(self) -> LauncherConfig:
|
|
1934
|
-
"""§5.4 #2: a swap model's ``option_profile`` must be a real preset.
|
|
2062
|
+
"""§5.4 #2: a swap model's ``option_profile`` must be a real preset.
|
|
2063
|
+
|
|
2064
|
+
バリアント backend の場合は基底名のプロファイルも継承されるので
|
|
2065
|
+
(:func:`resolve_option_profiles`)、マージ後の一覧で判定する。
|
|
2066
|
+
"""
|
|
1935
2067
|
if self.swap is None:
|
|
1936
2068
|
return self
|
|
2069
|
+
from coderouter.launcher_devices import resolve_option_profiles
|
|
2070
|
+
|
|
1937
2071
|
for spec in self.swap.models:
|
|
1938
2072
|
if spec.option_profile is None:
|
|
1939
2073
|
continue
|
|
1940
|
-
profiles = self.option_profiles
|
|
2074
|
+
profiles = resolve_option_profiles(self.option_profiles, spec.backend)
|
|
1941
2075
|
if not any(p.name == spec.option_profile for p in profiles):
|
|
1942
2076
|
raise ValueError(
|
|
1943
2077
|
f"launcher.swap.models[{spec.name!r}]: option_profile "
|