coderouter-cli 2.3.0a4__tar.gz → 2.5.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.3.0a4 → coderouter_cli-2.5.0}/.gitignore +5 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/CHANGELOG.md +124 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/PKG-INFO +36 -4
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/README.en.md +35 -3
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/README.md +35 -3
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/coderouter/cli.py +31 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/coderouter/config/schemas.py +157 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/coderouter/guards/__init__.py +2 -0
- coderouter_cli-2.5.0/coderouter/guards/_fingerprint.py +125 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/coderouter/guards/drift_detection.py +55 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/coderouter/ingress/app.py +11 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/coderouter/ingress/dashboard_routes.py +1 -0
- coderouter_cli-2.5.0/coderouter/ingress/launcher_routes.py +1176 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/coderouter/routing/fallback.py +33 -3
- coderouter_cli-2.5.0/coderouter/state/__init__.py +19 -0
- coderouter_cli-2.5.0/coderouter/state/suggest_rules.py +413 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/docs/architecture.md +82 -2
- coderouter_cli-2.5.0/docs/launcher-gui.md +200 -0
- coderouter_cli-2.5.0/docs/launcher-quickstart.md +187 -0
- coderouter_cli-2.5.0/docs/launcher.md +288 -0
- coderouter_cli-2.5.0/docs/openrouter-roster/CHANGES.md +50 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/docs/openrouter-roster/latest.json +11 -41
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/docs/quickstart.en.md +22 -3
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/docs/quickstart.md +23 -3
- coderouter_cli-2.5.0/docs/verify-ollama-0.23.1.md +243 -0
- coderouter_cli-2.5.0/examples/providers.llama-cpp-vllm.yaml +151 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/pyproject.toml +1 -1
- coderouter_cli-2.5.0/scripts/verify-providers.yaml +161 -0
- coderouter_cli-2.5.0/scripts/verify_ollama_0_23.py +679 -0
- coderouter_cli-2.3.0a4/coderouter/state/__init__.py +0 -15
- coderouter_cli-2.3.0a4/docs/openrouter-roster/CHANGES.md +0 -24
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/LICENSE +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/coderouter/__init__.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/coderouter/__main__.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/coderouter/adapters/__init__.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/coderouter/adapters/anthropic_native.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/coderouter/adapters/base.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/coderouter/adapters/openai_compat.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/coderouter/adapters/registry.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/coderouter/cli_stats.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/coderouter/config/__init__.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/coderouter/config/capability_registry.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/coderouter/config/env_file.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/coderouter/config/loader.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/coderouter/cost.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/coderouter/data/__init__.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/coderouter/data/model-capabilities.yaml +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/coderouter/doctor.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/coderouter/doctor_apply.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/coderouter/env_security.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/coderouter/errors.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/coderouter/guards/backend_health.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/coderouter/guards/context_budget.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/coderouter/guards/continuous_probe.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/coderouter/guards/drift_actions.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/coderouter/guards/memory_pressure.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/coderouter/guards/self_healing.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/coderouter/guards/tool_loop.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/coderouter/ingress/__init__.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/coderouter/ingress/anthropic_routes.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/coderouter/ingress/metrics_routes.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/coderouter/ingress/openai_routes.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/coderouter/logging.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/coderouter/metrics/__init__.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/coderouter/metrics/collector.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/coderouter/metrics/prometheus.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/coderouter/output_filters.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/coderouter/plugins/__init__.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/coderouter/plugins/base.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/coderouter/plugins/loader.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/coderouter/plugins/registry.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/coderouter/routing/__init__.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/coderouter/routing/adaptive.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/coderouter/routing/auto_router.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/coderouter/routing/budget.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/coderouter/routing/capability.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/coderouter/state/audit_log.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/coderouter/state/replay.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/coderouter/state/request_log.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/coderouter/state/store.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/coderouter/token_estimation.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/coderouter/translation/__init__.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/coderouter/translation/anthropic.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/coderouter/translation/convert.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/coderouter/translation/tool_repair.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/docs/assets/dashboard-demo.png +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/docs/context-budget.md +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/docs/continuous-probing.md +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/docs/designs/v1.5-dashboard-mockup.html +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/docs/designs/v1.6-auto-router-verification.md +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/docs/designs/v1.6-auto-router.md +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/docs/drift-detection.md +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/docs/free-tier-guide.en.md +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/docs/free-tier-guide.md +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/docs/gguf_dl.md +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/docs/hf-ollama-models.md +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/docs/llamacpp-direct.en.md +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/docs/llamacpp-direct.md +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/docs/lmstudio-direct.en.md +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/docs/lmstudio-direct.md +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/docs/openrouter-roster/README.md +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/docs/partial-stitch.md +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/docs/retrospectives/v0.4.md +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/docs/retrospectives/v0.5-verify.md +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/docs/retrospectives/v0.5.md +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/docs/retrospectives/v0.6.md +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/docs/retrospectives/v0.7.md +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/docs/retrospectives/v1.0-verify.md +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/docs/retrospectives/v1.0.md +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/docs/security.en.md +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/docs/security.md +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/docs/troubleshooting.en.md +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/docs/troubleshooting.md +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/docs/usage-guide.en.md +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/docs/usage-guide.md +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/docs/when-do-i-need-coderouter.en.md +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/docs/when-do-i-need-coderouter.md +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/examples/.env.example +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/examples/providers.auto-custom.yaml +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/examples/providers.auto.yaml +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/examples/providers.note-2026.yaml +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/examples/providers.nvidia-nim.yaml +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/examples/providers.raspberrypi.yaml +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/examples/providers.v2-context-budget.yaml +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/examples/providers.yaml +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/scripts/demo_traffic.sh +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/scripts/openrouter_roster_diff.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/scripts/smoke_v2_2.sh +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/scripts/verify_v0_5.sh +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/scripts/verify_v1_0.sh +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/tests/__init__.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/tests/conftest.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/tests/test_adapter_anthropic.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/tests/test_audit_log.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/tests/test_auto_router.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/tests/test_backend_health.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/tests/test_budget.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/tests/test_capability.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/tests/test_capability_degraded_payload.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/tests/test_capability_registry.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/tests/test_capability_registry_cache_control.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/tests/test_claude_code_suitability.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/tests/test_cli.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/tests/test_cli_stats.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/tests/test_config.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/tests/test_context_budget.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/tests/test_continuous_probe.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/tests/test_dashboard_endpoint.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/tests/test_doctor.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/tests/test_doctor_apply.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/tests/test_doctor_cache_probe.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/tests/test_drift_actions.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/tests/test_drift_detection.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/tests/test_drift_detection_integration.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/tests/test_env_file.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/tests/test_env_security.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/tests/test_errors.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/tests/test_examples_yaml.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/tests/test_fallback.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/tests/test_fallback_anthropic.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/tests/test_fallback_cache_control.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/tests/test_fallback_cache_observed.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/tests/test_fallback_misconfig_warn.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/tests/test_fallback_paid_gate.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/tests/test_fallback_thinking.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/tests/test_guards_tool_loop.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/tests/test_ingress_anthropic.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/tests/test_ingress_profile.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/tests/test_memory_pressure.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/tests/test_metrics_cache.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/tests/test_metrics_collector.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/tests/test_metrics_cost.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/tests/test_metrics_endpoint.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/tests/test_metrics_jsonl.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/tests/test_metrics_prometheus.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/tests/test_metrics_prometheus_cache.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/tests/test_openai_compat.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/tests/test_openrouter_roster_diff.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/tests/test_output_filters.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/tests/test_output_filters_adapters.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/tests/test_partial_stitch.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/tests/test_plugins_integration.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/tests/test_plugins_loader.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/tests/test_plugins_registry.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/tests/test_reasoning_strip.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/tests/test_request_log.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/tests/test_routing_adaptive.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/tests/test_self_healing.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/tests/test_setup_sh.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/tests/test_state_store.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/tests/test_token_estimation.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/tests/test_tool_repair.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/tests/test_translation_anthropic.py +0 -0
- {coderouter_cli-2.3.0a4 → coderouter_cli-2.5.0}/tests/test_translation_reverse.py +0 -0
|
@@ -32,6 +32,11 @@ env/
|
|
|
32
32
|
ENV/
|
|
33
33
|
.python-version-local
|
|
34
34
|
|
|
35
|
+
# ============================================================
|
|
36
|
+
# _OUTPUTS
|
|
37
|
+
# ============================================================
|
|
38
|
+
_OUTPUTS/
|
|
39
|
+
|
|
35
40
|
# uv
|
|
36
41
|
# Note: uv.lock SHOULD be committed (per plan.md §5.4)
|
|
37
42
|
# Do NOT add uv.lock here.
|
|
@@ -6,6 +6,130 @@ versioning follows [SemVer](https://semver.org/).
|
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
+
## [v2.5.0] — 2026-05-22 (Launcher — llama.cpp / vllm GUI)
|
|
10
|
+
|
|
11
|
+
Browser-based process manager for local inference backends, integrated
|
|
12
|
+
into the existing CodeRouter web UI at `/launcher`.
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
- **`coderouter/ingress/launcher_routes.py`**: New route module providing
|
|
17
|
+
the Launcher UI and its backing API.
|
|
18
|
+
|
|
19
|
+
- `GET /launcher` — Single-page HTML UI (Tailwind CDN + inline JS,
|
|
20
|
+
same dark-theme aesthetic as `/dashboard`).
|
|
21
|
+
- `GET /api/launcher/models` — Recursively scans `launcher.model_dirs`
|
|
22
|
+
and returns discovered model files with name, path, size (GB), and
|
|
23
|
+
extension.
|
|
24
|
+
- `GET /api/launcher/option-profiles` — Returns named option presets
|
|
25
|
+
from `providers.yaml` keyed by backend (`llama.cpp`, `vllm`).
|
|
26
|
+
- `GET /api/launcher/processes` — Lists all managed processes.
|
|
27
|
+
- `POST /api/launcher/start` — Starts a backend process. Accepts name,
|
|
28
|
+
backend, model_path, port, options dict, and extra_args free-text.
|
|
29
|
+
- `POST /api/launcher/stop/{id}` — SIGTERM → SIGKILL (5 s timeout).
|
|
30
|
+
- `DELETE /api/launcher/processes/{id}` — Removes a stopped process.
|
|
31
|
+
- `GET /api/launcher/logs/{id}` — Returns last N lines from the
|
|
32
|
+
process's 200-line stdout/stderr ring buffer.
|
|
33
|
+
|
|
34
|
+
- **`LauncherOptionProfile` / `LauncherConfig`** (`config/schemas.py`):
|
|
35
|
+
New Pydantic models for the `launcher:` block in `providers.yaml`.
|
|
36
|
+
Adding new CLI flags requires only a YAML edit — no code change.
|
|
37
|
+
|
|
38
|
+
- **`launcher_profiles.yaml.example`**: Template with 7 llama.cpp
|
|
39
|
+
presets and 7 vllm presets. For GitHub distribution and community
|
|
40
|
+
profile contributions.
|
|
41
|
+
|
|
42
|
+
- **`/dashboard` header**: Added a "Launcher" navigation link.
|
|
43
|
+
|
|
44
|
+
### Design notes
|
|
45
|
+
|
|
46
|
+
- **YAML-driven**: option profiles live entirely in `providers.yaml`.
|
|
47
|
+
No code changes needed to add new backend flags.
|
|
48
|
+
- **Multi-process**: each launched process gets a UUID-based ID and is
|
|
49
|
+
tracked independently. llama.cpp and vllm can run side by side.
|
|
50
|
+
- **Zero new dependencies**: uses `asyncio.create_subprocess_exec`
|
|
51
|
+
(stdlib only). The 5-dep invariant is maintained.
|
|
52
|
+
- **In-memory registry**: does not persist across CodeRouter restarts
|
|
53
|
+
(intentional — avoids zombie GPU allocations on restart).
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## [v2.4.0] — 2026-05-15 (Goal-session awareness — P1-4/5/6)
|
|
58
|
+
|
|
59
|
+
Stable release following v2.3.0a4. Promotes the Plugin SDK to stable,
|
|
60
|
+
adds three goal-session features, and ships a rule-suggestion CLI.
|
|
61
|
+
|
|
62
|
+
### Added
|
|
63
|
+
|
|
64
|
+
- **`coderouter/guards/_fingerprint.py`** (P1-4): Response fingerprinting
|
|
65
|
+
helper. `fingerprint_response(text)` returns a 12-hex SHA-256 digest
|
|
66
|
+
of the top-N content words (stop-word-filtered, order-independent).
|
|
67
|
+
Used by the new `goal_progress_stall` drift signal to detect when a
|
|
68
|
+
model repeats itself without making progress.
|
|
69
|
+
|
|
70
|
+
- **Signal 6 — `goal_progress_stall`** (`drift_detection.py`, P1-4):
|
|
71
|
+
Sixth drift signal added to `detect_drift()`. Fires (mild) when the
|
|
72
|
+
fraction of fingerprinted responses that repeat an already-seen
|
|
73
|
+
fingerprint exceeds `repetition_rate_threshold` (default 0.4).
|
|
74
|
+
Requires `response_fingerprint` to be populated on observations; when
|
|
75
|
+
absent the signal is silently skipped (backward-compatible).
|
|
76
|
+
|
|
77
|
+
- **`DriftThresholds.repetition_rate_threshold`** (P1-4): New field on
|
|
78
|
+
`DriftThresholds`, present on all three presets. `THRESHOLDS_GOAL`
|
|
79
|
+
preset added (`min_window_fill=4`, `repetition_rate_threshold=0.2`,
|
|
80
|
+
tighter across the board) and exposed via `SENSITIVITY_PRESETS["goal"]`.
|
|
81
|
+
|
|
82
|
+
- **`FallbackChain.goal_mode: bool = False`** (`config/schemas.py`, P1-5):
|
|
83
|
+
Profile-level flag. When `True`, the drift detector ignores
|
|
84
|
+
`drift_detection_sensitivity` and uses `THRESHOLDS_GOAL` instead
|
|
85
|
+
(stricter thresholds + `min_window_fill=4`). Designed for `/goal`
|
|
86
|
+
agent sessions where forward-progress stalls are more actionable.
|
|
87
|
+
|
|
88
|
+
- **`coderouter/state/suggest_rules.py`** (P1-6): Statistical rule
|
|
89
|
+
suggestion engine. `suggest_rules(WindowSummary) → list[RuleSuggestion]`
|
|
90
|
+
analyses the request journal and emits copy-paste YAML snippets.
|
|
91
|
+
Five rules: `provider_reorder` (cost rank), `enable_prompt_cache`
|
|
92
|
+
(high-token / low-hit providers), `enable_drift_detection` (reminder),
|
|
93
|
+
`low_sensitivity_small_window` (sparse-traffic guard), `goal_profile`
|
|
94
|
+
(output-divergence → `goal_mode: true`). Pure statistics — no LLM.
|
|
95
|
+
|
|
96
|
+
- **`coderouter replay --suggest-rules`** (`cli.py`, P1-6): New flag on
|
|
97
|
+
the existing `replay` subcommand. Reads the full request journal,
|
|
98
|
+
runs `suggest_rules`, and prints a formatted terminal report with
|
|
99
|
+
confidence badges and YAML snippets.
|
|
100
|
+
|
|
101
|
+
### Changed
|
|
102
|
+
|
|
103
|
+
- **`ResponseObservation.response_fingerprint: str | None = None`**
|
|
104
|
+
(`drift_detection.py`): New optional field (slots-safe, defaults to
|
|
105
|
+
`None`). Fully backward-compatible — existing callers that don't
|
|
106
|
+
populate it get the same five-signal behaviour as before.
|
|
107
|
+
|
|
108
|
+
- **`FallbackEngine._observe_drift_signal`** (`fallback.py`): Accepts
|
|
109
|
+
new `response_fingerprint` kwarg. Non-streaming and streaming success
|
|
110
|
+
paths now compute and pass a fingerprint for the `goal_progress_stall`
|
|
111
|
+
signal. `goal_mode` check applies `THRESHOLDS_GOAL` when the profile
|
|
112
|
+
flag is set.
|
|
113
|
+
|
|
114
|
+
### Files touched
|
|
115
|
+
|
|
116
|
+
```
|
|
117
|
+
A coderouter/guards/_fingerprint.py
|
|
118
|
+
M coderouter/guards/__init__.py — module registry comment
|
|
119
|
+
M coderouter/guards/drift_detection.py — Signal 6, THRESHOLDS_GOAL, new fields
|
|
120
|
+
M coderouter/config/schemas.py — FallbackChain.goal_mode
|
|
121
|
+
M coderouter/routing/fallback.py — fingerprint wiring, goal_mode dispatch
|
|
122
|
+
A coderouter/state/suggest_rules.py
|
|
123
|
+
M coderouter/state/__init__.py — module registry comment
|
|
124
|
+
M coderouter/cli.py — replay --suggest-rules
|
|
125
|
+
A docs/articles/v1-saga/note-14-v0-4-goal-mode.md
|
|
126
|
+
M docs/articles/v1-saga/INDEX.md
|
|
127
|
+
M docs/inside/future.md
|
|
128
|
+
M CHANGELOG.md, pyproject.toml — 2.3.0a4 → 2.4.0
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
9
133
|
## [v2.3.0a4] — 2026-05-08 (Plugin SDK — ruff cleanup)
|
|
10
134
|
|
|
11
135
|
Patch over `v2.3.0a3`. CI's `ruff check .` job surfaced six lint
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: coderouter-cli
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.5.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
|
|
@@ -47,7 +47,7 @@ Description-Content-Type: text/markdown
|
|
|
47
47
|
|
|
48
48
|
<p align="center">
|
|
49
49
|
<a href="https://github.com/zephel01/CodeRouter/actions/workflows/ci.yml"><img src="https://github.com/zephel01/CodeRouter/actions/workflows/ci.yml/badge.svg?branch=main" alt="CI"></a>
|
|
50
|
-
<a href=""><img src="https://img.shields.io/
|
|
50
|
+
<a href="https://pypi.org/project/coderouter-cli/"><img src="https://img.shields.io/pypi/v/coderouter-cli?include_prereleases&color=blue&label=pypi" alt="pypi"></a>
|
|
51
51
|
<a href=""><img src="https://img.shields.io/badge/python-3.12%2B-blue" alt="python"></a>
|
|
52
52
|
<a href=""><img src="https://img.shields.io/badge/deps-5-brightgreen" alt="deps"></a>
|
|
53
53
|
<a href=""><img src="https://img.shields.io/badge/license-MIT-yellow" alt="license"></a>
|
|
@@ -141,7 +141,7 @@ ANTHROPIC_BASE_URL=http://localhost:8088 ANTHROPIC_AUTH_TOKEN=dummy claude
|
|
|
141
141
|
| ガード | 何から守るか |
|
|
142
142
|
|---|---|
|
|
143
143
|
| **Context Budget** | メッセージが溜まりすぎて context window 溢れ → 自動 trim |
|
|
144
|
-
| **Drift Detection** | モデルの応答品質が徐々に劣化 → 別 provider に切替 or KV cache flush |
|
|
144
|
+
| **Drift Detection** | モデルの応答品質が徐々に劣化 → 別 provider に切替 or KV cache flush (6 シグナル、`goal_mode` で目標達成停滞も検知) |
|
|
145
145
|
| **Self-healing** | backend が落ちた → 自動除外 + restart + 回復 probe で自動復帰 |
|
|
146
146
|
| **Tool Loop Guard** | 同じツールを無限に呼び続ける → 検知して停止 |
|
|
147
147
|
| **Memory Pressure** | GPU メモリ不足を検知 → 軽量モデルに切替 |
|
|
@@ -154,9 +154,40 @@ ANTHROPIC_BASE_URL=http://localhost:8088 ANTHROPIC_AUTH_TOKEN=dummy claude
|
|
|
154
154
|
| **`coderouter doctor`** | プロバイダの問題を 6 プローブで即診断 + 修正パッチ出力 |
|
|
155
155
|
| **`/dashboard`** | ブラウザで今何が起きてるかリアルタイム確認 |
|
|
156
156
|
| **`coderouter audit`** | guard 発火履歴を検索 |
|
|
157
|
-
| **`coderouter replay`** | provider 切替の効果を統計比較 (A/B 分析) |
|
|
157
|
+
| **`coderouter replay`** | provider 切替の効果を統計比較 (A/B 分析) / `--suggest-rules` でルール最適化提案 |
|
|
158
158
|
| **Continuous Probe** | idle 時も定期的に backend を監視 |
|
|
159
159
|
|
|
160
|
+
### Launcher — llama.cpp / vllm 起動 UI
|
|
161
|
+
|
|
162
|
+
`http://localhost:8088/launcher` で開けるブラウザ UI。llama.cpp や vllm を GUI で起動・管理できます。
|
|
163
|
+
|
|
164
|
+
| 機能 | 詳細 |
|
|
165
|
+
|---|---|
|
|
166
|
+
| **モデルスキャン** | `model_dirs` に指定したフォルダを再帰スキャンして `.gguf` / `.safetensors` をリスト化 |
|
|
167
|
+
| **オプションプロファイル** | `providers.yaml` に名前付きプリセットを定義 → ドロップダウンで選択するだけ |
|
|
168
|
+
| **複数プロセス管理** | llama.cpp と vllm を同時に起動し、ポートごとに独立管理 |
|
|
169
|
+
| **ログビューア** | 各プロセスの stdout/stderr をブラウザ内でリアルタイム確認 |
|
|
170
|
+
|
|
171
|
+
```yaml
|
|
172
|
+
# providers.yaml に追記するだけで有効になる
|
|
173
|
+
launcher:
|
|
174
|
+
model_dirs:
|
|
175
|
+
- ~/models
|
|
176
|
+
option_profiles:
|
|
177
|
+
llama.cpp:
|
|
178
|
+
- name: "GPU フル活用"
|
|
179
|
+
args:
|
|
180
|
+
"-ngl": 99
|
|
181
|
+
"--ctx-size": 4096
|
|
182
|
+
vllm:
|
|
183
|
+
- name: "標準"
|
|
184
|
+
args:
|
|
185
|
+
"--dtype": "auto"
|
|
186
|
+
"--max-model-len": 4096
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
詳細 → [Launcher ガイド](./docs/launcher.md)
|
|
190
|
+
|
|
160
191
|
---
|
|
161
192
|
|
|
162
193
|
## 設定例 (最小)
|
|
@@ -193,6 +224,7 @@ providers:
|
|
|
193
224
|
| すぐ動かす | [Quickstart](./docs/quickstart.md) |
|
|
194
225
|
| 使いこなす | [利用ガイド](./docs/usage-guide.md) |
|
|
195
226
|
| 無料で回す | [無料枠ガイド](./docs/free-tier-guide.md) |
|
|
227
|
+
| llama.cpp / vllm を GUI で起動 | [Launcher ガイド](./docs/launcher.md) |
|
|
196
228
|
| 詰まった | [トラブルシューティング](./docs/troubleshooting.md) |
|
|
197
229
|
| 設計を知りたい | [アーキテクチャ詳細](./docs/architecture.md) |
|
|
198
230
|
| 全リリース履歴 | [CHANGELOG](./CHANGELOG.md) |
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
<p align="center">
|
|
8
8
|
<a href="https://github.com/zephel01/CodeRouter/actions/workflows/ci.yml"><img src="https://github.com/zephel01/CodeRouter/actions/workflows/ci.yml/badge.svg?branch=main" alt="CI"></a>
|
|
9
|
-
<a href=""><img src="https://img.shields.io/
|
|
9
|
+
<a href="https://pypi.org/project/coderouter-cli/"><img src="https://img.shields.io/pypi/v/coderouter-cli?include_prereleases&color=blue&label=pypi" alt="pypi"></a>
|
|
10
10
|
<a href=""><img src="https://img.shields.io/badge/python-3.12%2B-blue" alt="python"></a>
|
|
11
11
|
<a href=""><img src="https://img.shields.io/badge/deps-5-brightgreen" alt="deps"></a>
|
|
12
12
|
<a href=""><img src="https://img.shields.io/badge/license-MIT-yellow" alt="license"></a>
|
|
@@ -100,7 +100,7 @@ Full decision matrix → [Do I need CodeRouter?](./docs/when-do-i-need-coderoute
|
|
|
100
100
|
| Guard | What it protects against |
|
|
101
101
|
|---|---|
|
|
102
102
|
| **Context Budget** | Messages piling up → context window overflow. Auto-trim at 90% |
|
|
103
|
-
| **Drift Detection** | Model quality degrading over time → switch provider or flush KV cache |
|
|
103
|
+
| **Drift Detection** | Model quality degrading over time → switch provider or flush KV cache (6 signals incl. `goal_progress_stall`; `goal_mode` for tighter thresholds) |
|
|
104
104
|
| **Self-healing** | Backend crashes → auto-exclude + restart + recovery probe → auto-restore |
|
|
105
105
|
| **Tool Loop Guard** | Agent calling the same tool forever → detect and break |
|
|
106
106
|
| **Memory Pressure** | GPU running out of VRAM → switch to lighter model |
|
|
@@ -113,9 +113,40 @@ Full decision matrix → [Do I need CodeRouter?](./docs/when-do-i-need-coderoute
|
|
|
113
113
|
| **`coderouter doctor`** | 6-probe diagnosis of provider issues + copy-paste YAML patches |
|
|
114
114
|
| **`/dashboard`** | Real-time browser view of what's happening |
|
|
115
115
|
| **`coderouter audit`** | Search guard activation history |
|
|
116
|
-
| **`coderouter replay`** | Compare providers statistically (A/B analysis) |
|
|
116
|
+
| **`coderouter replay`** | Compare providers statistically (A/B analysis) / `--suggest-rules` for automated rule suggestions |
|
|
117
117
|
| **Continuous Probe** | Background health monitoring even during idle |
|
|
118
118
|
|
|
119
|
+
### Launcher — llama.cpp / vllm GUI
|
|
120
|
+
|
|
121
|
+
Browser UI at `http://localhost:8088/launcher` for starting and managing local inference backends.
|
|
122
|
+
|
|
123
|
+
| Feature | Detail |
|
|
124
|
+
|---|---|
|
|
125
|
+
| **Model scanner** | Recursively scans `model_dirs` for `.gguf` / `.safetensors` and lists them |
|
|
126
|
+
| **Option profiles** | Name your flag presets in `providers.yaml` — select from a dropdown, no CLI needed |
|
|
127
|
+
| **Multi-process** | Run llama.cpp and vllm side by side on different ports |
|
|
128
|
+
| **Log viewer** | stdout/stderr of each process shown live in the browser |
|
|
129
|
+
|
|
130
|
+
```yaml
|
|
131
|
+
# Add to providers.yaml — no code changes needed
|
|
132
|
+
launcher:
|
|
133
|
+
model_dirs:
|
|
134
|
+
- ~/models
|
|
135
|
+
option_profiles:
|
|
136
|
+
llama.cpp:
|
|
137
|
+
- name: "Full GPU"
|
|
138
|
+
args:
|
|
139
|
+
"-ngl": 99
|
|
140
|
+
"--ctx-size": 4096
|
|
141
|
+
vllm:
|
|
142
|
+
- name: "Standard"
|
|
143
|
+
args:
|
|
144
|
+
"--dtype": "auto"
|
|
145
|
+
"--max-model-len": 4096
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Details → [Launcher guide](./docs/launcher.md)
|
|
149
|
+
|
|
119
150
|
---
|
|
120
151
|
|
|
121
152
|
## Minimal Config
|
|
@@ -152,6 +183,7 @@ More detail → [Usage guide](./docs/usage-guide.en.md) · [Architecture](./docs
|
|
|
152
183
|
| Get running fast | [Quickstart](./docs/quickstart.en.md) |
|
|
153
184
|
| Use it well | [Usage guide](./docs/usage-guide.en.md) |
|
|
154
185
|
| Run for free | [Free-tier guide](./docs/free-tier-guide.en.md) |
|
|
186
|
+
| Launch llama.cpp / vllm via GUI | [Launcher guide](./docs/launcher.md) |
|
|
155
187
|
| Stuck? | [Troubleshooting](./docs/troubleshooting.en.md) |
|
|
156
188
|
| Understand the design | [Architecture](./docs/architecture.md) |
|
|
157
189
|
| Full release history | [CHANGELOG](./CHANGELOG.md) |
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
<p align="center">
|
|
8
8
|
<a href="https://github.com/zephel01/CodeRouter/actions/workflows/ci.yml"><img src="https://github.com/zephel01/CodeRouter/actions/workflows/ci.yml/badge.svg?branch=main" alt="CI"></a>
|
|
9
|
-
<a href=""><img src="https://img.shields.io/
|
|
9
|
+
<a href="https://pypi.org/project/coderouter-cli/"><img src="https://img.shields.io/pypi/v/coderouter-cli?include_prereleases&color=blue&label=pypi" alt="pypi"></a>
|
|
10
10
|
<a href=""><img src="https://img.shields.io/badge/python-3.12%2B-blue" alt="python"></a>
|
|
11
11
|
<a href=""><img src="https://img.shields.io/badge/deps-5-brightgreen" alt="deps"></a>
|
|
12
12
|
<a href=""><img src="https://img.shields.io/badge/license-MIT-yellow" alt="license"></a>
|
|
@@ -100,7 +100,7 @@ ANTHROPIC_BASE_URL=http://localhost:8088 ANTHROPIC_AUTH_TOKEN=dummy claude
|
|
|
100
100
|
| ガード | 何から守るか |
|
|
101
101
|
|---|---|
|
|
102
102
|
| **Context Budget** | メッセージが溜まりすぎて context window 溢れ → 自動 trim |
|
|
103
|
-
| **Drift Detection** | モデルの応答品質が徐々に劣化 → 別 provider に切替 or KV cache flush |
|
|
103
|
+
| **Drift Detection** | モデルの応答品質が徐々に劣化 → 別 provider に切替 or KV cache flush (6 シグナル、`goal_mode` で目標達成停滞も検知) |
|
|
104
104
|
| **Self-healing** | backend が落ちた → 自動除外 + restart + 回復 probe で自動復帰 |
|
|
105
105
|
| **Tool Loop Guard** | 同じツールを無限に呼び続ける → 検知して停止 |
|
|
106
106
|
| **Memory Pressure** | GPU メモリ不足を検知 → 軽量モデルに切替 |
|
|
@@ -113,9 +113,40 @@ ANTHROPIC_BASE_URL=http://localhost:8088 ANTHROPIC_AUTH_TOKEN=dummy claude
|
|
|
113
113
|
| **`coderouter doctor`** | プロバイダの問題を 6 プローブで即診断 + 修正パッチ出力 |
|
|
114
114
|
| **`/dashboard`** | ブラウザで今何が起きてるかリアルタイム確認 |
|
|
115
115
|
| **`coderouter audit`** | guard 発火履歴を検索 |
|
|
116
|
-
| **`coderouter replay`** | provider 切替の効果を統計比較 (A/B 分析) |
|
|
116
|
+
| **`coderouter replay`** | provider 切替の効果を統計比較 (A/B 分析) / `--suggest-rules` でルール最適化提案 |
|
|
117
117
|
| **Continuous Probe** | idle 時も定期的に backend を監視 |
|
|
118
118
|
|
|
119
|
+
### Launcher — llama.cpp / vllm 起動 UI
|
|
120
|
+
|
|
121
|
+
`http://localhost:8088/launcher` で開けるブラウザ UI。llama.cpp や vllm を GUI で起動・管理できます。
|
|
122
|
+
|
|
123
|
+
| 機能 | 詳細 |
|
|
124
|
+
|---|---|
|
|
125
|
+
| **モデルスキャン** | `model_dirs` に指定したフォルダを再帰スキャンして `.gguf` / `.safetensors` をリスト化 |
|
|
126
|
+
| **オプションプロファイル** | `providers.yaml` に名前付きプリセットを定義 → ドロップダウンで選択するだけ |
|
|
127
|
+
| **複数プロセス管理** | llama.cpp と vllm を同時に起動し、ポートごとに独立管理 |
|
|
128
|
+
| **ログビューア** | 各プロセスの stdout/stderr をブラウザ内でリアルタイム確認 |
|
|
129
|
+
|
|
130
|
+
```yaml
|
|
131
|
+
# providers.yaml に追記するだけで有効になる
|
|
132
|
+
launcher:
|
|
133
|
+
model_dirs:
|
|
134
|
+
- ~/models
|
|
135
|
+
option_profiles:
|
|
136
|
+
llama.cpp:
|
|
137
|
+
- name: "GPU フル活用"
|
|
138
|
+
args:
|
|
139
|
+
"-ngl": 99
|
|
140
|
+
"--ctx-size": 4096
|
|
141
|
+
vllm:
|
|
142
|
+
- name: "標準"
|
|
143
|
+
args:
|
|
144
|
+
"--dtype": "auto"
|
|
145
|
+
"--max-model-len": 4096
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
詳細 → [Launcher ガイド](./docs/launcher.md)
|
|
149
|
+
|
|
119
150
|
---
|
|
120
151
|
|
|
121
152
|
## 設定例 (最小)
|
|
@@ -152,6 +183,7 @@ providers:
|
|
|
152
183
|
| すぐ動かす | [Quickstart](./docs/quickstart.md) |
|
|
153
184
|
| 使いこなす | [利用ガイド](./docs/usage-guide.md) |
|
|
154
185
|
| 無料で回す | [無料枠ガイド](./docs/free-tier-guide.md) |
|
|
186
|
+
| llama.cpp / vllm を GUI で起動 | [Launcher ガイド](./docs/launcher.md) |
|
|
155
187
|
| 詰まった | [トラブルシューティング](./docs/troubleshooting.md) |
|
|
156
188
|
| 設計を知りたい | [アーキテクチャ詳細](./docs/architecture.md) |
|
|
157
189
|
| 全リリース履歴 | [CHANGELOG](./CHANGELOG.md) |
|
|
@@ -293,6 +293,18 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
293
293
|
metavar="N",
|
|
294
294
|
help="Use only the last N entries (applied after --since and --provider filters).",
|
|
295
295
|
)
|
|
296
|
+
# P1-6: --suggest-rules — statistical analysis → routing rule proposals.
|
|
297
|
+
replay.add_argument(
|
|
298
|
+
"--suggest-rules",
|
|
299
|
+
action="store_true",
|
|
300
|
+
help=(
|
|
301
|
+
"P1-6: analyse the request journal and print actionable routing "
|
|
302
|
+
"rule suggestions as copy-paste YAML snippets. Suggestions cover "
|
|
303
|
+
"provider reordering by cost, prompt_cache enablement, drift "
|
|
304
|
+
"detection configuration, and goal profile creation. "
|
|
305
|
+
"Can be combined with --since / --limit to scope the analysis window."
|
|
306
|
+
),
|
|
307
|
+
)
|
|
296
308
|
|
|
297
309
|
return parser
|
|
298
310
|
|
|
@@ -684,6 +696,25 @@ def _run_replay(args: argparse.Namespace) -> int:
|
|
|
684
696
|
print("replay: no matching entries found.")
|
|
685
697
|
return 0
|
|
686
698
|
|
|
699
|
+
if getattr(args, "suggest_rules", False):
|
|
700
|
+
# P1-6: statistical rule suggestion mode.
|
|
701
|
+
# Always compute a full window summary (ignores --compare / --provider).
|
|
702
|
+
from coderouter.state.replay import summarize_window as _sw
|
|
703
|
+
from coderouter.state.suggest_rules import format_suggestions, suggest_rules
|
|
704
|
+
|
|
705
|
+
# Re-read without provider filter so we see all providers.
|
|
706
|
+
all_entries = read_request_log(log_path, since=args.since)
|
|
707
|
+
if args.limit is not None and args.limit > 0:
|
|
708
|
+
all_entries = all_entries[-args.limit:]
|
|
709
|
+
full_summary = _sw(all_entries)
|
|
710
|
+
suggestions = suggest_rules(full_summary)
|
|
711
|
+
print(f"Request journal: {len(all_entries)} entries analysed")
|
|
712
|
+
print(f" Window: {full_summary.first_ts} → {full_summary.last_ts}")
|
|
713
|
+
print(f" Providers: {', '.join(sorted(full_summary.providers))}")
|
|
714
|
+
print()
|
|
715
|
+
print(format_suggestions(suggestions))
|
|
716
|
+
return 0
|
|
717
|
+
|
|
687
718
|
if args.compare:
|
|
688
719
|
provider_a, provider_b = args.compare
|
|
689
720
|
comparison = compare_providers(entries, provider_a, provider_b)
|
|
@@ -658,6 +658,28 @@ class FallbackChain(BaseModel):
|
|
|
658
658
|
),
|
|
659
659
|
)
|
|
660
660
|
|
|
661
|
+
# --- P1-5: goal_mode — tighter drift thresholds for /goal sessions -------
|
|
662
|
+
#
|
|
663
|
+
# When True, the drift detector automatically switches to the
|
|
664
|
+
# ``THRESHOLDS_GOAL`` preset regardless of ``drift_detection_sensitivity``,
|
|
665
|
+
# and lowers ``min_window_fill`` to 4 so stall detection fires faster.
|
|
666
|
+
#
|
|
667
|
+
# Intended for profiles routed by the ``/goal`` meta-command where
|
|
668
|
+
# the agent is expected to make steady forward progress. Repetition and
|
|
669
|
+
# length collapse are much more meaningful signals in that context than
|
|
670
|
+
# in a general-purpose chat session.
|
|
671
|
+
goal_mode: bool = Field(
|
|
672
|
+
default=False,
|
|
673
|
+
description=(
|
|
674
|
+
"P1-5: when True, automatically applies the ``goal`` drift "
|
|
675
|
+
"threshold preset (stricter thresholds, lower ``min_window_fill`` "
|
|
676
|
+
"of 4) for this profile. Overrides ``drift_detection_sensitivity`` "
|
|
677
|
+
"when drift_detection_action is not ``off``. Designed for "
|
|
678
|
+
"agent/goal sessions where forward-progress stalls are more "
|
|
679
|
+
"actionable than in ad-hoc chat."
|
|
680
|
+
),
|
|
681
|
+
)
|
|
682
|
+
|
|
661
683
|
# --- v2.0-H (L6): Mid-stream partial stitching --------------------------
|
|
662
684
|
# * ``off`` — discard partial content on mid-stream failure (legacy).
|
|
663
685
|
# * ``surface`` — return partial content as a truncated-but-valid response.
|
|
@@ -852,6 +874,130 @@ class AutoRouterConfig(BaseModel):
|
|
|
852
874
|
)
|
|
853
875
|
|
|
854
876
|
|
|
877
|
+
class LauncherBackendConfig(BaseModel):
|
|
878
|
+
"""Per-backend binary path configuration for the Launcher.
|
|
879
|
+
|
|
880
|
+
When ``binary`` is unset, the Launcher falls back to the default
|
|
881
|
+
executable name (``llama-server`` for llama.cpp, ``python`` for vllm)
|
|
882
|
+
and relies on ``$PATH`` resolution — which works when the tool is
|
|
883
|
+
globally installed. Set ``binary`` when:
|
|
884
|
+
|
|
885
|
+
- llama.cpp was built from source (e.g. ``~/llama.cpp/build/bin/llama-server``)
|
|
886
|
+
- vllm lives in a virtualenv (e.g. ``~/.venv/bin/python``)
|
|
887
|
+
- Multiple builds coexist and you want to pin a specific one
|
|
888
|
+
|
|
889
|
+
Tilde (``~``) and environment variables are expanded at launch time.
|
|
890
|
+
|
|
891
|
+
Example::
|
|
892
|
+
|
|
893
|
+
backends:
|
|
894
|
+
llama.cpp:
|
|
895
|
+
binary: ~/llama.cpp/build/bin/llama-server
|
|
896
|
+
vllm:
|
|
897
|
+
binary: ~/.venv/bin/python
|
|
898
|
+
"""
|
|
899
|
+
|
|
900
|
+
model_config = ConfigDict(extra="forbid")
|
|
901
|
+
|
|
902
|
+
binary: str | None = Field(
|
|
903
|
+
default=None,
|
|
904
|
+
description=(
|
|
905
|
+
"Absolute or ``~``-relative path to the backend executable. "
|
|
906
|
+
"llama.cpp default: ``llama-server`` (PATH). "
|
|
907
|
+
"vllm default: ``python`` (PATH). "
|
|
908
|
+
"Expanded at launch time."
|
|
909
|
+
),
|
|
910
|
+
)
|
|
911
|
+
|
|
912
|
+
|
|
913
|
+
class LauncherOptionProfile(BaseModel):
|
|
914
|
+
"""One named option preset for a launcher backend (e.g. llama.cpp / vllm).
|
|
915
|
+
|
|
916
|
+
``args`` maps CLI flag strings to their values. A bool value of
|
|
917
|
+
``True`` means "include the flag without a value" (e.g. ``--no-mmap``);
|
|
918
|
+
``False`` means "omit the flag entirely". All other value types are
|
|
919
|
+
converted to strings and appended as ``--flag value`` pairs.
|
|
920
|
+
|
|
921
|
+
Example::
|
|
922
|
+
|
|
923
|
+
name: "GPU速度重視"
|
|
924
|
+
args:
|
|
925
|
+
"-ngl": 99
|
|
926
|
+
"--ctx-size": 4096
|
|
927
|
+
"--no-mmap": false
|
|
928
|
+
"""
|
|
929
|
+
|
|
930
|
+
model_config = ConfigDict(extra="forbid")
|
|
931
|
+
|
|
932
|
+
name: str = Field(..., description="Display name shown in the Launcher UI dropdown.")
|
|
933
|
+
args: dict[str, str | int | float | bool] = Field(
|
|
934
|
+
default_factory=dict,
|
|
935
|
+
description=(
|
|
936
|
+
"CLI flag → value mapping. "
|
|
937
|
+
"bool True = flag only (no value). "
|
|
938
|
+
"bool False = omit flag. "
|
|
939
|
+
"All other types are stringified and passed as '--flag value'."
|
|
940
|
+
),
|
|
941
|
+
)
|
|
942
|
+
|
|
943
|
+
|
|
944
|
+
class LauncherConfig(BaseModel):
|
|
945
|
+
"""The ``launcher:`` block in providers.yaml.
|
|
946
|
+
|
|
947
|
+
Controls the Launcher UI available at ``/launcher``.
|
|
948
|
+
|
|
949
|
+
Example::
|
|
950
|
+
|
|
951
|
+
launcher:
|
|
952
|
+
model_dirs:
|
|
953
|
+
- ~/models
|
|
954
|
+
- /data/gguf
|
|
955
|
+
option_profiles:
|
|
956
|
+
llama.cpp:
|
|
957
|
+
- name: "GPU速度重視"
|
|
958
|
+
args:
|
|
959
|
+
"-ngl": 99
|
|
960
|
+
"--ctx-size": 4096
|
|
961
|
+
vllm:
|
|
962
|
+
- name: "標準"
|
|
963
|
+
args:
|
|
964
|
+
"--dtype": "auto"
|
|
965
|
+
"--max-model-len": 4096
|
|
966
|
+
"""
|
|
967
|
+
|
|
968
|
+
model_config = ConfigDict(extra="forbid")
|
|
969
|
+
|
|
970
|
+
model_dirs: list[str] = Field(
|
|
971
|
+
default_factory=list,
|
|
972
|
+
description=(
|
|
973
|
+
"Directories to scan for model files "
|
|
974
|
+
"(.gguf, .safetensors, .bin, .pt, .ggml). "
|
|
975
|
+
"Paths are expanded (~ and env vars) at scan time, not at load. "
|
|
976
|
+
"Non-existent paths are silently skipped."
|
|
977
|
+
),
|
|
978
|
+
)
|
|
979
|
+
backends: dict[str, LauncherBackendConfig] = Field(
|
|
980
|
+
default_factory=dict,
|
|
981
|
+
description=(
|
|
982
|
+
"Per-backend binary path overrides. "
|
|
983
|
+
"Keys are backend names ('llama.cpp', 'vllm'). "
|
|
984
|
+
"When a key is absent, the default executable is used "
|
|
985
|
+
"('llama-server' / 'python') and resolved via PATH. "
|
|
986
|
+
"Useful when running a from-source build or a venv-specific binary."
|
|
987
|
+
),
|
|
988
|
+
)
|
|
989
|
+
option_profiles: dict[str, list[LauncherOptionProfile]] = Field(
|
|
990
|
+
default_factory=dict,
|
|
991
|
+
description=(
|
|
992
|
+
"Named option presets per backend. "
|
|
993
|
+
"Keys should be backend names: 'llama.cpp', 'vllm'. "
|
|
994
|
+
"Each key maps to an ordered list of named presets. "
|
|
995
|
+
"A free-form 'extra args' field is always available in the UI "
|
|
996
|
+
"for one-off overrides without touching this config."
|
|
997
|
+
),
|
|
998
|
+
)
|
|
999
|
+
|
|
1000
|
+
|
|
855
1001
|
class PluginsConfig(BaseModel):
|
|
856
1002
|
"""The ``plugins:`` block in providers.yaml (v2.3.0).
|
|
857
1003
|
|
|
@@ -1060,6 +1206,17 @@ class CodeRouterConfig(BaseModel):
|
|
|
1060
1206
|
"plugins (zero-cost, backward-compatible default)."
|
|
1061
1207
|
),
|
|
1062
1208
|
)
|
|
1209
|
+
launcher: LauncherConfig | None = Field(
|
|
1210
|
+
default=None,
|
|
1211
|
+
description=(
|
|
1212
|
+
"Launcher configuration for the /launcher UI. "
|
|
1213
|
+
"Defines model_dirs to scan and option_profiles per backend "
|
|
1214
|
+
"('llama.cpp', 'vllm'). "
|
|
1215
|
+
"Unset (None) = Launcher UI shows empty model list and no profiles. "
|
|
1216
|
+
"The Launcher UI itself is always available at /launcher "
|
|
1217
|
+
"regardless of this setting."
|
|
1218
|
+
),
|
|
1219
|
+
)
|
|
1063
1220
|
|
|
1064
1221
|
@model_validator(mode="after")
|
|
1065
1222
|
def _check_default_profile_exists(self) -> CodeRouterConfig:
|
|
@@ -12,6 +12,8 @@ to hit:
|
|
|
12
12
|
* :mod:`coderouter.guards.self_healing` — v2.0-J auto-exclude +
|
|
13
13
|
restart + recovery probe
|
|
14
14
|
* :mod:`coderouter.guards.continuous_probe` — v2.0-I background probing
|
|
15
|
+
* :mod:`coderouter.guards._fingerprint` — P1-4 response fingerprinting
|
|
16
|
+
for goal_progress_stall signal
|
|
15
17
|
|
|
16
18
|
Each guard is a pure-functional / single-class module that the engine
|
|
17
19
|
consults at the appropriate dispatch point. Guards never block the
|