coderouter-cli 2.6.0__tar.gz → 2.6.1__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.6.0 → coderouter_cli-2.6.1}/.gitignore +1 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/CHANGELOG.md +45 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/PKG-INFO +32 -1
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/README.en.md +31 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/README.md +31 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/ingress/dashboard_routes.py +23 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/metrics/collector.py +60 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/docs/README.md +38 -1
- coderouter_cli-2.6.1/docs/backends/claude-code-llamacpp-vllm.md +172 -0
- coderouter_cli-2.6.1/docs/guides/language-tax.en.md +138 -0
- coderouter_cli-2.6.1/docs/guides/language-tax.md +139 -0
- coderouter_cli-2.6.1/examples/README.md +68 -0
- coderouter_cli-2.6.1/examples/providers-multiagent.yaml +188 -0
- coderouter_cli-2.6.0/examples/providers.v2-context-budget.yaml → coderouter_cli-2.6.1/examples/providers.context-budget-test.yaml +2 -1
- coderouter_cli-2.6.0/examples/providers.llama-cpp-vllm.yaml → coderouter_cli-2.6.1/examples/providers.llamacpp-vllm.yaml +19 -9
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/examples/providers.nvidia-nim.yaml +1 -0
- coderouter_cli-2.6.0/examples/providers.auto-custom.yaml → coderouter_cli-2.6.1/examples/providers.ollama-auto-custom.yaml +6 -5
- coderouter_cli-2.6.0/examples/providers.auto.yaml → coderouter_cli-2.6.1/examples/providers.ollama-auto.yaml +2 -1
- coderouter_cli-2.6.0/examples/providers.note-2026.yaml → coderouter_cli-2.6.1/examples/providers.ollama-free-chain.yaml +3 -2
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/examples/providers.raspberrypi.yaml +1 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/examples/providers.yaml +1 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/pyproject.toml +1 -1
- coderouter_cli-2.6.1/tests/test_tokens_saved_metric.py +87 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/LICENSE +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/__init__.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/__main__.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/adapters/__init__.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/adapters/anthropic_native.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/adapters/base.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/adapters/openai_compat.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/adapters/registry.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/cli.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/cli_stats.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/config/__init__.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/config/capability_registry.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/config/env_file.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/config/loader.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/config/schemas.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/cost.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/data/__init__.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/data/model-capabilities.yaml +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/doctor.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/doctor_apply.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/env_security.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/errors.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/gguf_introspect.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/guards/__init__.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/guards/_fingerprint.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/guards/backend_health.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/guards/context_budget.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/guards/continuous_probe.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/guards/drift_actions.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/guards/drift_detection.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/guards/memory_budget.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/guards/memory_pressure.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/guards/self_healing.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/guards/tool_loop.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/hardware.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/ingress/__init__.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/ingress/anthropic_routes.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/ingress/app.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/ingress/launcher_routes.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/ingress/metrics_routes.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/ingress/openai_routes.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/language_tax.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/logging.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/metrics/__init__.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/metrics/prometheus.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/output_filters.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/plugins/__init__.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/plugins/base.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/plugins/loader.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/plugins/registry.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/routing/__init__.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/routing/adaptive.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/routing/auto_router.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/routing/budget.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/routing/capability.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/routing/fallback.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/state/__init__.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/state/audit_log.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/state/replay.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/state/request_log.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/state/store.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/state/suggest_rules.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/token_estimation.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/token_estimation_accurate.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/translation/__init__.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/translation/anthropic.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/translation/convert.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/coderouter/translation/tool_repair.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/docs/assets/dashboard-demo.png +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/docs/backends/gguf_dl.md +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/docs/backends/hf-ollama-models.md +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/docs/backends/install-backends.en.md +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/docs/backends/install-backends.md +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/docs/backends/launcher-quickstart.md +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/docs/backends/launcher.md +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/docs/backends/llamacpp-direct.en.md +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/docs/backends/llamacpp-direct.md +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/docs/backends/lmstudio-direct.en.md +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/docs/backends/lmstudio-direct.md +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/docs/backends/verify-ollama-0.23.1.md +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/docs/concepts/architecture.md +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/docs/concepts/context-budget.md +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/docs/concepts/continuous-probing.md +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/docs/concepts/drift-detection.md +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/docs/concepts/partial-stitch.md +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/docs/designs/v1.5-dashboard-mockup.html +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/docs/designs/v1.6-auto-router-verification.md +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/docs/designs/v1.6-auto-router.md +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/docs/guides/free-tier-guide.en.md +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/docs/guides/free-tier-guide.md +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/docs/guides/security.en.md +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/docs/guides/security.md +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/docs/guides/troubleshooting.en.md +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/docs/guides/troubleshooting.md +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/docs/guides/usage-guide.en.md +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/docs/guides/usage-guide.md +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/docs/low-memory-integration.md +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/docs/openrouter-roster/CHANGES.md +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/docs/openrouter-roster/README.md +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/docs/openrouter-roster/latest.json +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/docs/retrospectives/v0.4.md +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/docs/retrospectives/v0.5-verify.md +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/docs/retrospectives/v0.5.md +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/docs/retrospectives/v0.6.md +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/docs/retrospectives/v0.7.md +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/docs/retrospectives/v1.0-verify.md +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/docs/retrospectives/v1.0.md +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/docs/start/quickstart.en.md +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/docs/start/quickstart.md +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/docs/start/when-do-i-need-coderouter.en.md +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/docs/start/when-do-i-need-coderouter.md +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/examples/.env.example +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/scripts/demo_traffic.sh +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/scripts/openrouter_roster_diff.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/scripts/smoke_v2_2.sh +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/scripts/verify-providers.yaml +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/scripts/verify_ollama_0_23.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/scripts/verify_v0_5.sh +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/scripts/verify_v1_0.sh +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/__init__.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/conftest.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_adapter_anthropic.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_audit_log.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_auto_router.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_auto_router_cjk.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_backend_health.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_budget.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_capability.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_capability_degraded_payload.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_capability_registry.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_capability_registry_cache_control.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_claude_code_suitability.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_cli.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_cli_stats.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_config.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_context_budget.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_continuous_probe.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_dashboard_endpoint.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_doctor.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_doctor_apply.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_doctor_cache_probe.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_drift_actions.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_drift_detection.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_drift_detection_integration.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_env_file.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_env_security.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_errors.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_examples_yaml.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_fallback.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_fallback_anthropic.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_fallback_cache_control.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_fallback_cache_observed.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_fallback_misconfig_warn.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_fallback_paid_gate.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_fallback_thinking.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_gguf_introspect.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_guards_tool_loop.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_hardware.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_ingress_anthropic.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_ingress_profile.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_language_tax.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_language_tax_integration.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_memory_budget.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_memory_pressure.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_metrics_cache.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_metrics_collector.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_metrics_cost.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_metrics_endpoint.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_metrics_jsonl.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_metrics_prometheus.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_metrics_prometheus_cache.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_openai_compat.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_openrouter_roster_diff.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_output_filters.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_output_filters_adapters.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_partial_stitch.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_plugins_integration.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_plugins_loader.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_plugins_registry.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_reasoning_strip.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_repair_byte_fallback.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_request_log.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_role_normalization.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_routing_adaptive.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_self_healing.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_setup_sh.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_state_store.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_token_estimation.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_token_estimation_accurate.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_tool_repair.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_translation_anthropic.py +0 -0
- {coderouter_cli-2.6.0 → coderouter_cli-2.6.1}/tests/test_translation_reverse.py +0 -0
|
@@ -6,6 +6,51 @@ versioning follows [SemVer](https://semver.org/).
|
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
+
## [v2.6.1] — 2026-06-28 (Token-savings accounting)
|
|
10
|
+
|
|
11
|
+
Patch release: surfaces **token-savings accounting** in the metrics layer
|
|
12
|
+
and dashboard. The figure is owned by core, so it appears even when no
|
|
13
|
+
plugin is installed (trim savings from the context-budget guard), and the
|
|
14
|
+
optional `compress` plugin adds to the same total via a neutral
|
|
15
|
+
`tokens-saved` log event. **No new core dependency**, **no behavioral
|
|
16
|
+
change** to existing paths, and **fully backward compatible** — existing
|
|
17
|
+
counters and events are untouched; the new buckets are additive.
|
|
18
|
+
|
|
19
|
+
### Added
|
|
20
|
+
|
|
21
|
+
- **Token-savings buckets in `MetricsCollector`**
|
|
22
|
+
(`coderouter/metrics/collector.py`). `tokens_saved_total` plus a
|
|
23
|
+
per-mechanism breakdown (`tokens_saved_by_mechanism`). Two feeds
|
|
24
|
+
aggregate under one schema: `trim` (derived from the existing
|
|
25
|
+
`context-budget-trimmed` event's before/after token estimate) and
|
|
26
|
+
`compress` (the neutral `tokens-saved` event emitted by the compress
|
|
27
|
+
plugin — no core import). Wired through `snapshot()`, `save_state()`,
|
|
28
|
+
`load_state()`, and `reset()`.
|
|
29
|
+
- **Dashboard Token Savings tiles**
|
|
30
|
+
(`coderouter/ingress/dashboard_routes.py`). Three tiles — trim /
|
|
31
|
+
compress / total — in the "Cost & Language Tax" panel, zero-filled so a
|
|
32
|
+
fresh or local-only deployment renders cleanly.
|
|
33
|
+
|
|
34
|
+
### Docs / examples
|
|
35
|
+
|
|
36
|
+
- Reorganized provider samples under `examples/` with a category index.
|
|
37
|
+
- Added the language-tax guide (JA/EN) and a Claude Code +
|
|
38
|
+
llama.cpp/vllm backend guide.
|
|
39
|
+
|
|
40
|
+
### Tests
|
|
41
|
+
|
|
42
|
+
- `tests/test_tokens_saved_metric.py` — trim/compress accounting,
|
|
43
|
+
negative-delta clamping, combined aggregate, persistence round-trip,
|
|
44
|
+
and reset. Full suite: **1263 passed, 1 skipped**.
|
|
45
|
+
|
|
46
|
+
### Companion
|
|
47
|
+
|
|
48
|
+
- `coderouter-plugin-compress` emits the `tokens-saved` event (plugin
|
|
49
|
+
branch `feat/tokens-saved-emit`, v0.2.0). CodeRouter core works
|
|
50
|
+
standalone — trim savings show without the plugin.
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
9
54
|
## [v2.6.0] — 2026-06-20 (Language Tax: measure, route, visualize)
|
|
10
55
|
|
|
11
56
|
Minor release: makes the CJK **"language tax"** — cloud tokenizers bill
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: coderouter-cli
|
|
3
|
-
Version: 2.6.
|
|
3
|
+
Version: 2.6.1
|
|
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
|
|
@@ -161,6 +161,36 @@ ANTHROPIC_BASE_URL=http://localhost:8088 ANTHROPIC_AUTH_TOKEN=dummy claude
|
|
|
161
161
|
| **`coderouter replay`** | provider 切替の効果を統計比較 (A/B 分析) / `--suggest-rules` でルール最適化提案 |
|
|
162
162
|
| **Continuous Probe** | idle 時も定期的に backend を監視 |
|
|
163
163
|
|
|
164
|
+
### 言語税トラッキング — v2.6.0
|
|
165
|
+
|
|
166
|
+
日本語などの CJK テキストは、クラウドのトークナイザだと「同じ意味の英語」より多くのトークンを消費します(**実測: GPT-4o 系 o200k で平均 1.6 倍、GPT-4 系 cl100k で平均 2.0 倍**)。ローカル LLM は課金されないので、この「言語税」はクラウド利用時だけ効いてきます。CodeRouter v2.6.0 はこれを **計測・ルーティング回避・可視化** します。
|
|
167
|
+
|
|
168
|
+
| 機能 | 何をしてくれるか |
|
|
169
|
+
|---|---|
|
|
170
|
+
| **言語税の計測** | プロバイダに `tokenizer_path`(ローカルの `tokenizer.json`)を指定すると、char/4 ヒューリスティック比の実トークン倍率と割増 USD を算出(ネットワーク不要・未設定なら無効) |
|
|
171
|
+
| **`cjk_ratio_min` ルーティング** | CJK 比率が高いリクエストを自動でローカル LLM(課金ゼロ)へ。コードや英語はクラウドへ |
|
|
172
|
+
| **ダッシュボード可視化** | `/dashboard` の「Cost & Language Tax」パネルで総支出・キャッシュ節約・言語税をリアルタイム表示 |
|
|
173
|
+
|
|
174
|
+
```yaml
|
|
175
|
+
# providers.yaml — CJK 多めのターンはローカルへ自動回避
|
|
176
|
+
auto_router:
|
|
177
|
+
rules:
|
|
178
|
+
- match: { cjk_ratio_min: 0.3 } # 日本語が3割以上 → ローカル
|
|
179
|
+
profile: local
|
|
180
|
+
- match: { has_tools: true } # ツール使用 → クラウド
|
|
181
|
+
profile: cloud
|
|
182
|
+
default_rule_profile: cloud
|
|
183
|
+
|
|
184
|
+
providers:
|
|
185
|
+
- name: cloud-sonnet
|
|
186
|
+
kind: anthropic
|
|
187
|
+
base_url: https://api.anthropic.com
|
|
188
|
+
model: claude-sonnet-4-6
|
|
189
|
+
tokenizer_path: ~/.coderouter/tokenizers/sonnet.json # 言語税の正確計測(任意)
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
詳細 → [言語税ガイド](./docs/guides/language-tax.md)
|
|
193
|
+
|
|
164
194
|
### Launcher — llama.cpp / vllm 起動 UI
|
|
165
195
|
|
|
166
196
|
`http://localhost:8088/launcher` で開けるブラウザ UI。llama.cpp や vllm を GUI で起動・管理できます。
|
|
@@ -229,6 +259,7 @@ providers:
|
|
|
229
259
|
| 使いこなす | [利用ガイド](./docs/guides/usage-guide.md) |
|
|
230
260
|
| 無料で回す | [無料枠ガイド](./docs/guides/free-tier-guide.md) |
|
|
231
261
|
| llama.cpp / vllm を GUI で起動 | [Launcher ガイド](./docs/backends/launcher.md) |
|
|
262
|
+
| 言語税を計測・回避する | [言語税ガイド](./docs/guides/language-tax.md) |
|
|
232
263
|
| 詰まった | [トラブルシューティング](./docs/guides/troubleshooting.md) |
|
|
233
264
|
| 設計を知りたい | [アーキテクチャ詳細](./docs/concepts/architecture.md) |
|
|
234
265
|
| 全リリース履歴 | [CHANGELOG](./CHANGELOG.md) |
|
|
@@ -116,6 +116,36 @@ Full decision matrix → [Do I need CodeRouter?](./docs/start/when-do-i-need-cod
|
|
|
116
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
|
+
### Language Tax tracking — v2.6.0
|
|
120
|
+
|
|
121
|
+
CJK text (Japanese / Chinese / Korean) costs more tokens on cloud tokenizers than the same meaning in English (**measured: ~1.6× on average with GPT-4o-era o200k, ~2.0× with GPT-4-era cl100k**). Local models bill nothing per token, so this "language tax" only bites on the cloud leg. CodeRouter v2.6.0 makes it **measurable, routable, and visible**.
|
|
122
|
+
|
|
123
|
+
| Feature | What it does |
|
|
124
|
+
|---|---|
|
|
125
|
+
| **Language-tax measurement** | Set a provider's `tokenizer_path` (a local `tokenizer.json`) to compute the real token multiplier vs the char/4 heuristic and the extra USD. No network; inert when unset. |
|
|
126
|
+
| **`cjk_ratio_min` routing** | Auto-route CJK-heavy turns to a local (tax-free) model; code/English falls through to the cloud chain. |
|
|
127
|
+
| **Dashboard panel** | The `/dashboard` "Cost & Language Tax" panel shows total spend, cache savings, and language-tax spend live. |
|
|
128
|
+
|
|
129
|
+
```yaml
|
|
130
|
+
# providers.yaml — steer CJK-heavy turns to local
|
|
131
|
+
auto_router:
|
|
132
|
+
rules:
|
|
133
|
+
- match: { cjk_ratio_min: 0.3 } # >=30% CJK chars -> local
|
|
134
|
+
profile: local
|
|
135
|
+
- match: { has_tools: true } # tool use -> cloud
|
|
136
|
+
profile: cloud
|
|
137
|
+
default_rule_profile: cloud
|
|
138
|
+
|
|
139
|
+
providers:
|
|
140
|
+
- name: cloud-sonnet
|
|
141
|
+
kind: anthropic
|
|
142
|
+
base_url: https://api.anthropic.com
|
|
143
|
+
model: claude-sonnet-4-6
|
|
144
|
+
tokenizer_path: ~/.coderouter/tokenizers/sonnet.json # accurate language-tax (optional)
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Details → [Language Tax guide](./docs/guides/language-tax.en.md)
|
|
148
|
+
|
|
119
149
|
### Launcher — llama.cpp / vllm GUI
|
|
120
150
|
|
|
121
151
|
Browser UI at `http://localhost:8088/launcher` for starting and managing local inference backends.
|
|
@@ -184,6 +214,7 @@ More detail → [Usage guide](./docs/guides/usage-guide.en.md) · [Architecture]
|
|
|
184
214
|
| Use it well | [Usage guide](./docs/guides/usage-guide.en.md) |
|
|
185
215
|
| Run for free | [Free-tier guide](./docs/guides/free-tier-guide.en.md) |
|
|
186
216
|
| Launch llama.cpp / vllm via GUI | [Launcher guide](./docs/backends/launcher.md) |
|
|
217
|
+
| Measure & avoid the language tax | [Language Tax guide](./docs/guides/language-tax.en.md) |
|
|
187
218
|
| Stuck? | [Troubleshooting](./docs/guides/troubleshooting.en.md) |
|
|
188
219
|
| Understand the design | [Architecture](./docs/concepts/architecture.md) |
|
|
189
220
|
| Full release history | [CHANGELOG](./CHANGELOG.md) |
|
|
@@ -116,6 +116,36 @@ ANTHROPIC_BASE_URL=http://localhost:8088 ANTHROPIC_AUTH_TOKEN=dummy claude
|
|
|
116
116
|
| **`coderouter replay`** | provider 切替の効果を統計比較 (A/B 分析) / `--suggest-rules` でルール最適化提案 |
|
|
117
117
|
| **Continuous Probe** | idle 時も定期的に backend を監視 |
|
|
118
118
|
|
|
119
|
+
### 言語税トラッキング — v2.6.0
|
|
120
|
+
|
|
121
|
+
日本語などの CJK テキストは、クラウドのトークナイザだと「同じ意味の英語」より多くのトークンを消費します(**実測: GPT-4o 系 o200k で平均 1.6 倍、GPT-4 系 cl100k で平均 2.0 倍**)。ローカル LLM は課金されないので、この「言語税」はクラウド利用時だけ効いてきます。CodeRouter v2.6.0 はこれを **計測・ルーティング回避・可視化** します。
|
|
122
|
+
|
|
123
|
+
| 機能 | 何をしてくれるか |
|
|
124
|
+
|---|---|
|
|
125
|
+
| **言語税の計測** | プロバイダに `tokenizer_path`(ローカルの `tokenizer.json`)を指定すると、char/4 ヒューリスティック比の実トークン倍率と割増 USD を算出(ネットワーク不要・未設定なら無効) |
|
|
126
|
+
| **`cjk_ratio_min` ルーティング** | CJK 比率が高いリクエストを自動でローカル LLM(課金ゼロ)へ。コードや英語はクラウドへ |
|
|
127
|
+
| **ダッシュボード可視化** | `/dashboard` の「Cost & Language Tax」パネルで総支出・キャッシュ節約・言語税をリアルタイム表示 |
|
|
128
|
+
|
|
129
|
+
```yaml
|
|
130
|
+
# providers.yaml — CJK 多めのターンはローカルへ自動回避
|
|
131
|
+
auto_router:
|
|
132
|
+
rules:
|
|
133
|
+
- match: { cjk_ratio_min: 0.3 } # 日本語が3割以上 → ローカル
|
|
134
|
+
profile: local
|
|
135
|
+
- match: { has_tools: true } # ツール使用 → クラウド
|
|
136
|
+
profile: cloud
|
|
137
|
+
default_rule_profile: cloud
|
|
138
|
+
|
|
139
|
+
providers:
|
|
140
|
+
- name: cloud-sonnet
|
|
141
|
+
kind: anthropic
|
|
142
|
+
base_url: https://api.anthropic.com
|
|
143
|
+
model: claude-sonnet-4-6
|
|
144
|
+
tokenizer_path: ~/.coderouter/tokenizers/sonnet.json # 言語税の正確計測(任意)
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
詳細 → [言語税ガイド](./docs/guides/language-tax.md)
|
|
148
|
+
|
|
119
149
|
### Launcher — llama.cpp / vllm 起動 UI
|
|
120
150
|
|
|
121
151
|
`http://localhost:8088/launcher` で開けるブラウザ UI。llama.cpp や vllm を GUI で起動・管理できます。
|
|
@@ -184,6 +214,7 @@ providers:
|
|
|
184
214
|
| 使いこなす | [利用ガイド](./docs/guides/usage-guide.md) |
|
|
185
215
|
| 無料で回す | [無料枠ガイド](./docs/guides/free-tier-guide.md) |
|
|
186
216
|
| llama.cpp / vllm を GUI で起動 | [Launcher ガイド](./docs/backends/launcher.md) |
|
|
217
|
+
| 言語税を計測・回避する | [言語税ガイド](./docs/guides/language-tax.md) |
|
|
187
218
|
| 詰まった | [トラブルシューティング](./docs/guides/troubleshooting.md) |
|
|
188
219
|
| 設計を知りたい | [アーキテクチャ詳細](./docs/concepts/architecture.md) |
|
|
189
220
|
| 全リリース履歴 | [CHANGELOG](./CHANGELOG.md) |
|
|
@@ -184,6 +184,21 @@ _DASHBOARD_HTML = r"""<!doctype html>
|
|
|
184
184
|
</div>
|
|
185
185
|
</div>
|
|
186
186
|
<div id="language-tax-by-provider" class="text-xs text-slate-400 tabnum mt-3"></div>
|
|
187
|
+
<!-- Token Savings: trim (core budget guard) + compress (plugin) -->
|
|
188
|
+
<div class="grid grid-cols-3 gap-3 mt-3">
|
|
189
|
+
<div class="rounded-md bg-slate-800/50 p-3">
|
|
190
|
+
<div class="text-xs text-slate-400">Tokens saved · trim</div>
|
|
191
|
+
<div class="text-2xl font-semibold tabnum text-sky-400" data-bind="tokens_saved_trim">0</div>
|
|
192
|
+
</div>
|
|
193
|
+
<div class="rounded-md bg-slate-800/50 p-3">
|
|
194
|
+
<div class="text-xs text-slate-400">Tokens saved · compress</div>
|
|
195
|
+
<div class="text-2xl font-semibold tabnum text-sky-400" data-bind="tokens_saved_compress">0</div>
|
|
196
|
+
</div>
|
|
197
|
+
<div class="rounded-md bg-slate-800/50 p-3">
|
|
198
|
+
<div class="text-xs text-slate-400">Tokens saved · total</div>
|
|
199
|
+
<div class="text-2xl font-semibold tabnum text-green-400" data-bind="tokens_saved_total">0</div>
|
|
200
|
+
</div>
|
|
201
|
+
</div>
|
|
187
202
|
</section>
|
|
188
203
|
<section class="bg-slate-900/60 border border-slate-800 rounded-lg p-4">
|
|
189
204
|
<h2 class="text-sm font-semibold uppercase tracking-wider text-slate-400 mb-3">Usage Mix</h2>
|
|
@@ -474,6 +489,14 @@ _DASHBOARD_HTML = r"""<!doctype html>
|
|
|
474
489
|
rows.map(([n, v]) =>
|
|
475
490
|
'<span class="mr-4"><span class="text-slate-500">' + escapeHTML(n) +
|
|
476
491
|
'</span> ' + usd(v) + '</span>').join("");
|
|
492
|
+
// token-savings tiles. trim comes from the core budget guard;
|
|
493
|
+
// compress from the optional plugin. Collector zero-fills, so an
|
|
494
|
+
// install with neither still renders "0" cleanly.
|
|
495
|
+
const ts = c.tokens_saved_by_mechanism || {};
|
|
496
|
+
const intfmt = (x) => (Number(x) || 0).toLocaleString();
|
|
497
|
+
setBind("tokens_saved_trim", intfmt(ts.trim));
|
|
498
|
+
setBind("tokens_saved_compress", intfmt(ts.compress));
|
|
499
|
+
setBind("tokens_saved_total", intfmt(c.tokens_saved_total));
|
|
477
500
|
};
|
|
478
501
|
|
|
479
502
|
const renderSnapshot = (snap) => {
|
|
@@ -197,6 +197,16 @@ class MetricsCollector(logging.Handler):
|
|
|
197
197
|
self._language_tax_usd: dict[str, float] = {}
|
|
198
198
|
self._language_tax_usd_aggregate: float = 0.0
|
|
199
199
|
|
|
200
|
+
# token-savings accounting. Tokens that never reached the backend
|
|
201
|
+
# because a reduction mechanism shrank or dropped them. Two
|
|
202
|
+
# mechanisms feed this: ``trim`` (core context-budget guard, derived
|
|
203
|
+
# from the existing ``context-budget-trimmed`` event) and
|
|
204
|
+
# ``compress`` (the optional compress plugin, via the neutral
|
|
205
|
+
# ``tokens-saved`` event). Owned by core so the figure exists even
|
|
206
|
+
# when no plugin is installed.
|
|
207
|
+
self._tokens_saved_total: int = 0
|
|
208
|
+
self._tokens_saved_by_mechanism: Counter[str] = Counter()
|
|
209
|
+
|
|
200
210
|
# v2.0-F (L1): context budget guard counters. Per-profile counts
|
|
201
211
|
# of warnings (over warn threshold) and trims (messages removed).
|
|
202
212
|
# The ``latest_usage_ratio`` dict records the most recent ratio
|
|
@@ -425,6 +435,41 @@ class MetricsCollector(logging.Handler):
|
|
|
425
435
|
profile = _str(extras.get("profile"))
|
|
426
436
|
self._context_budget_trims_total += 1
|
|
427
437
|
self._context_budget_trims_by_profile[profile] += 1
|
|
438
|
+
# token-savings: the trim already carries the estimated
|
|
439
|
+
# before/after token counts, so fold the delta into the
|
|
440
|
+
# shared savings buckets (mechanism="trim").
|
|
441
|
+
before = extras.get("estimated_tokens_before")
|
|
442
|
+
after = extras.get("estimated_tokens_after")
|
|
443
|
+
if isinstance(before, int | float) and isinstance(
|
|
444
|
+
after, int | float
|
|
445
|
+
):
|
|
446
|
+
saved = max(0, int(before) - int(after))
|
|
447
|
+
if saved:
|
|
448
|
+
self._tokens_saved_total += saved
|
|
449
|
+
self._tokens_saved_by_mechanism["trim"] += saved
|
|
450
|
+
elif event == "tokens-saved":
|
|
451
|
+
# Neutral token-savings event emitted by non-core reduction
|
|
452
|
+
# mechanisms (e.g. the compress plugin). Carries a
|
|
453
|
+
# ``mechanism`` label plus either a precomputed
|
|
454
|
+
# ``tokens_saved`` or a ``tokens_before`` / ``tokens_after``
|
|
455
|
+
# pair. Negative deltas clamp to zero. No core import needed
|
|
456
|
+
# by the emitter — it just logs this record name.
|
|
457
|
+
mechanism = _str(extras.get("mechanism")) or "unknown"
|
|
458
|
+
saved_raw = extras.get("tokens_saved")
|
|
459
|
+
before = extras.get("tokens_before")
|
|
460
|
+
after = extras.get("tokens_after")
|
|
461
|
+
if isinstance(saved_raw, int | float):
|
|
462
|
+
saved = max(0, int(saved_raw))
|
|
463
|
+
elif isinstance(before, int | float) and isinstance(
|
|
464
|
+
after, int | float
|
|
465
|
+
):
|
|
466
|
+
saved = max(0, int(before) - int(after))
|
|
467
|
+
else:
|
|
468
|
+
saved = 0
|
|
469
|
+
if saved:
|
|
470
|
+
self._tokens_saved_total += saved
|
|
471
|
+
self._tokens_saved_by_mechanism[mechanism] += saved
|
|
472
|
+
self._push_recent(event, extras, record)
|
|
428
473
|
elif event == "drift-detected":
|
|
429
474
|
# v2.0-G (L4): drift detection fired.
|
|
430
475
|
provider = _str(extras.get("provider"))
|
|
@@ -624,6 +669,11 @@ class MetricsCollector(logging.Handler):
|
|
|
624
669
|
"language_tax_usd_aggregate": round(
|
|
625
670
|
self._language_tax_usd_aggregate, 6
|
|
626
671
|
),
|
|
672
|
+
# token-savings: total + per-mechanism (trim / compress).
|
|
673
|
+
"tokens_saved_total": self._tokens_saved_total,
|
|
674
|
+
"tokens_saved_by_mechanism": dict(
|
|
675
|
+
self._tokens_saved_by_mechanism
|
|
676
|
+
),
|
|
627
677
|
# v2.0-F (L1): context budget guard aggregate counters.
|
|
628
678
|
"context_budget_warnings_total": self._context_budget_warnings_total,
|
|
629
679
|
"context_budget_trims_total": self._context_budget_trims_total,
|
|
@@ -684,6 +734,10 @@ class MetricsCollector(logging.Handler):
|
|
|
684
734
|
"chain_budget_exceeded_total": self._chain_budget_exceeded_total,
|
|
685
735
|
"chain_memory_pressure_blocked_total": self._chain_memory_pressure_blocked_total,
|
|
686
736
|
"chain_uniform_auth_failure_total": self._chain_uniform_auth_failure_total,
|
|
737
|
+
"tokens_saved_total": self._tokens_saved_total,
|
|
738
|
+
"tokens_saved_by_mechanism": dict(
|
|
739
|
+
self._tokens_saved_by_mechanism
|
|
740
|
+
),
|
|
687
741
|
"probe_rounds_total": self._probe_rounds_total,
|
|
688
742
|
}
|
|
689
743
|
|
|
@@ -724,6 +778,9 @@ class MetricsCollector(logging.Handler):
|
|
|
724
778
|
self._language_tax_usd_aggregate += float(
|
|
725
779
|
state.get("language_tax_usd_aggregate", 0.0)
|
|
726
780
|
)
|
|
781
|
+
self._tokens_saved_total += int(state.get("tokens_saved_total", 0))
|
|
782
|
+
for k, v in (state.get("tokens_saved_by_mechanism") or {}).items():
|
|
783
|
+
self._tokens_saved_by_mechanism[k] += int(v)
|
|
727
784
|
self._chain_paid_gate_blocked_total += int(
|
|
728
785
|
state.get("chain_paid_gate_blocked_total", 0)
|
|
729
786
|
)
|
|
@@ -782,6 +839,9 @@ class MetricsCollector(logging.Handler):
|
|
|
782
839
|
# v2.6
|
|
783
840
|
self._language_tax_usd.clear()
|
|
784
841
|
self._language_tax_usd_aggregate = 0.0
|
|
842
|
+
# token-savings
|
|
843
|
+
self._tokens_saved_total = 0
|
|
844
|
+
self._tokens_saved_by_mechanism.clear()
|
|
785
845
|
# v2.0-H (L6)
|
|
786
846
|
self._partial_stitch_surfaced_total = 0
|
|
787
847
|
# v2.0-I
|
|
@@ -16,10 +16,12 @@ Index of CodeRouter's public documentation — find the right page by what you w
|
|
|
16
16
|
| 自分に必要か知りたい / Is it for me? | [start/when-do-i-need-coderouter](start/when-do-i-need-coderouter.md) |
|
|
17
17
|
| 無料で運用したい / Run for free | [guides/free-tier-guide](guides/free-tier-guide.md) |
|
|
18
18
|
| 機能を一通り知りたい / Learn the features | [guides/usage-guide](guides/usage-guide.md) |
|
|
19
|
+
| 言語税を計測・回避したい / Measure & avoid the language tax | [guides/language-tax](guides/language-tax.md) |
|
|
19
20
|
| エラーで詰まった / Something broke | [guides/troubleshooting](guides/troubleshooting.md) |
|
|
20
21
|
| ローカル LLM を起動したい / Launch a local LLM | [backends/launcher-quickstart](backends/launcher-quickstart.md) |
|
|
21
22
|
| APIキー・機密の扱い / Secrets & security | [guides/security](guides/security.md) |
|
|
22
23
|
| 仕組みを理解したい / Understand the design | [concepts/architecture](concepts/architecture.md) |
|
|
24
|
+
| プラグインで拡張したい / Extend with plugins | [対応プラグイン / Plugins](#対応プラグイン--plugins) |
|
|
23
25
|
|
|
24
26
|
---
|
|
25
27
|
|
|
@@ -55,6 +57,7 @@ Many documents have a Japanese version (`.md`) and an English version (`.en.md`)
|
|
|
55
57
|
日常的に使いこなすためのガイド。 / Day-to-day usage.
|
|
56
58
|
|
|
57
59
|
- **usage-guide** — 機能を一通り使いこなす / Full feature guide · [日本語](guides/usage-guide.md) · [English](guides/usage-guide.en.md)
|
|
60
|
+
- **language-tax** — 日本語の言語税を計測・ルーティング回避・可視化 / Measure, route around, and visualize the CJK language tax · [日本語](guides/language-tax.md) · [English](guides/language-tax.en.md)
|
|
58
61
|
- **free-tier-guide** — NVIDIA NIM × OpenRouter Free でコストゼロ運用 / Zero-cost operation · [日本語](guides/free-tier-guide.md) · [English](guides/free-tier-guide.en.md)
|
|
59
62
|
- **troubleshooting** — つまずいたときの解決集 / Fixing problems · [日本語](guides/troubleshooting.md) · [English](guides/troubleshooting.en.md)
|
|
60
63
|
- **security** — シークレット管理とセキュリティ方針 / Secrets handling & security posture · [日本語](guides/security.md) · [English](guides/security.en.md)
|
|
@@ -91,4 +94,38 @@ CodeRouter の仕組みと信頼性機構。 / How CodeRouter works and its reli
|
|
|
91
94
|
|
|
92
95
|
---
|
|
93
96
|
|
|
94
|
-
|
|
97
|
+
## 対応プラグイン / Plugins
|
|
98
|
+
|
|
99
|
+
CodeRouter は v2.3.0 で入った **Plugin SDK** により、別パッケージのプラグインを *opt-in* で読み込めます。`plugins.enabled` に名前を明示したときだけ作動する(サプライチェーン防御)ため、インストールしただけでは何も起きません。各プラグインは独立した PyPI パッケージなので、**コアの依存は一切増えません**。
|
|
100
|
+
|
|
101
|
+
CodeRouter's **Plugin SDK** (since v2.3.0) loads out-of-tree plugins *opt-in*: a plugin runs only when its name is listed in `plugins.enabled` (supply-chain defense), so installing one does nothing by itself. Each plugin ships as a separate PyPI package, so **the core's dependencies never grow**.
|
|
102
|
+
|
|
103
|
+
| プラグイン / Plugin | 何をするか / What it does | インストール / Install | リポジトリ / Repo |
|
|
104
|
+
|---|---|---|---|
|
|
105
|
+
| **compress** | ツール出力(JSON / ログ)を LLM に届く前に圧縮してトークンを削減。原文はローカル保持で可逆(CCR)。`cache-align` で Anthropic プロンプトキャッシュも整列。<br>Compresses tool output (JSON / logs) before it reaches the LLM to cut tokens; originals kept locally and reversible (CCR). `cache-align` also aligns Anthropic prompt caching. | `pip install coderouter-plugin-compress` | [coderouter-plugin-compress](https://github.com/zephel01/coderouter-plugin-compress) |
|
|
106
|
+
| **memory** | 応答から key facts を抽出して `facts.jsonl` に蓄積し、次セッションの system prompt へ自動注入。「毎回同じ説明」を wire 層で解消。<br>Extracts key facts from responses into `facts.jsonl` and auto-injects them into the next session's system prompt — solving "explain it every time" at the wire layer. | `pip install coderouter-plugin-memory` | [coderouter-plugin-memory](https://github.com/zephel01/coderouter-plugin-memory) |
|
|
107
|
+
|
|
108
|
+
有効化は `providers.yaml` に追記するだけ。起動ログに `plugin-loaded` が出れば有効です。
|
|
109
|
+
Enable by adding to `providers.yaml`; a `plugin-loaded` line in the startup log confirms activation.
|
|
110
|
+
|
|
111
|
+
```yaml
|
|
112
|
+
plugins:
|
|
113
|
+
enabled:
|
|
114
|
+
- compress # ツール出力を圧縮 / compress tool output
|
|
115
|
+
- compress-stats # 圧縮率を coderouter stats に出力 / report compression ratio
|
|
116
|
+
- cache-align # プロンプトキャッシュのブレークポイント整列 / align prompt-cache breakpoints
|
|
117
|
+
- memory # セッション横断メモリ / cross-session memory
|
|
118
|
+
config:
|
|
119
|
+
compress:
|
|
120
|
+
mode: safe # off | safe | aggressive
|
|
121
|
+
ccr: true # 圧縮の可逆復元(既定 on)/ reversible re-expansion (default on)
|
|
122
|
+
memory:
|
|
123
|
+
consolidate_model: qwen3:1.7b
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
各プラグインの詳細・設定は上記リポジトリの README を参照してください。
|
|
127
|
+
See each plugin's repo README for full configuration.
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
最終更新 / Last updated: 2026-06-24
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
# Claude Code × ローカル LLM(llama.cpp / vLLM)接続ガイド — Ollama なしの設定とトラブルシュート
|
|
2
|
+
|
|
3
|
+
Ollama を使わず、**ダウンロード済みの `.gguf` を llama.cpp で**、または **vLLM で** 動かし、CodeRouter 経由で Claude Code に繋ぐための実践ガイドです。
|
|
4
|
+
構成の作り方と、実際に踏みやすいエラー(400 / 接続拒否 / 502 / コネクタ無効化 / `n_ctx=4096` のまま)の直し方をまとめています。
|
|
5
|
+
|
|
6
|
+
> 関連: [Launcher ガイド](./launcher.md) / [バックエンド インストール手順書](./install-backends.md) / [examples/README](../../examples/README.md)
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## 全体構成
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
Claude Code ──(ANTHROPIC_BASE_URL)──► CodeRouter (:8088) ──► ① llama.cpp (:8080)
|
|
14
|
+
├─► ② vLLM (:8000)
|
|
15
|
+
└─► ③ 無料クラウド (fallback)
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
CodeRouter が求めるのは「OpenAI 互換 API を話すバックエンド」だけです。Ollama はその選択肢の 1 つにすぎず、llama.cpp / vLLM でも等価に使えます。
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## セットアップ手順
|
|
23
|
+
|
|
24
|
+
### 1. バックエンドを起動する(Ollama なし)
|
|
25
|
+
|
|
26
|
+
**llama.cpp(ダウンロード済み GGUF を使う)**
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
brew install llama.cpp # macOS / Linux(Windows: winget install ggml.llamacpp)
|
|
30
|
+
|
|
31
|
+
llama-server -m ~/models/<model>.gguf --host 127.0.0.1 --port 8080 \
|
|
32
|
+
-ngl 99 --ctx-size 32768
|
|
33
|
+
# 起動ログの「n_ctx = 32768」を必ず確認する
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
**vLLM(NVIDIA GPU)**
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
uv venv ~/.coderouter/backends/vllm
|
|
40
|
+
~/.coderouter/backends/vllm/bin/python -m pip install vllm
|
|
41
|
+
~/.coderouter/backends/vllm/bin/python -m vllm.entrypoints.openai.api_server \
|
|
42
|
+
--model Qwen/Qwen2.5-Coder-7B-Instruct --port 8000 --max-model-len 32768
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
> 起動を GUI に任せたい場合は [Launcher](./launcher.md)。ただし Launcher が面倒を見るのは**起動まで**で、下記の provider 登録は別作業です。
|
|
46
|
+
|
|
47
|
+
### 2. CodeRouter に provider として登録する(`~/.coderouter/providers.yaml`)
|
|
48
|
+
|
|
49
|
+
```yaml
|
|
50
|
+
allow_paid: false
|
|
51
|
+
default_profile: default
|
|
52
|
+
|
|
53
|
+
providers:
|
|
54
|
+
- name: llama-cpp-local
|
|
55
|
+
kind: openai_compat
|
|
56
|
+
base_url: http://localhost:8080/v1 # ← 起動したポートと一致させる
|
|
57
|
+
model: "" # llama-server は model 名を問わない
|
|
58
|
+
timeout_s: 120
|
|
59
|
+
|
|
60
|
+
- name: vllm-local
|
|
61
|
+
kind: openai_compat
|
|
62
|
+
base_url: http://localhost:8000/v1 # ← vLLM の既定は 8000
|
|
63
|
+
model: Qwen/Qwen2.5-Coder-7B-Instruct
|
|
64
|
+
timeout_s: 120
|
|
65
|
+
|
|
66
|
+
- name: openrouter-free # 逃げ先(任意だが推奨)
|
|
67
|
+
kind: openai_compat
|
|
68
|
+
base_url: https://openrouter.ai/api/v1
|
|
69
|
+
model: qwen/qwen3-coder:free
|
|
70
|
+
api_key_env: OPENROUTER_API_KEY
|
|
71
|
+
|
|
72
|
+
profiles:
|
|
73
|
+
- name: default
|
|
74
|
+
providers: [llama-cpp-local, vllm-local, openrouter-free]
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
`examples/providers.llamacpp-vllm.yaml` をコピーして始めると速いです。
|
|
78
|
+
|
|
79
|
+
### 3. CodeRouter を起動して Claude Code を繋ぐ
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
# ターミナル1
|
|
83
|
+
coderouter serve --port 8088
|
|
84
|
+
|
|
85
|
+
# ターミナル2(このシェルだけに env を効かせる。グローバルに置かない)
|
|
86
|
+
ANTHROPIC_BASE_URL=http://localhost:8088 ANTHROPIC_AUTH_TOKEN=dummy claude
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
`ANTHROPIC_AUTH_TOKEN` はダミーで可(CodeRouter は検証しない)。実 API キーは `providers.yaml` 側で管理します。
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## 設定の 4 つの要点
|
|
94
|
+
|
|
95
|
+
### ① ポートを一致させる
|
|
96
|
+
|
|
97
|
+
`base_url` のポートは起動した推論サーバーと一字一句一致させること。ズレると `transport error: All connection attempts failed`(接続拒否)になります。
|
|
98
|
+
|
|
99
|
+
| バックエンド | 既定ポート | 確認 |
|
|
100
|
+
|---|---|---|
|
|
101
|
+
| llama.cpp | `8080` | `curl localhost:8080/health` |
|
|
102
|
+
| vLLM | `8000` | `curl localhost:8000/v1/models` |
|
|
103
|
+
| Ollama | `11434` | `curl localhost:11434/api/version` |
|
|
104
|
+
|
|
105
|
+
### ② context size を Claude Code 用に上げる
|
|
106
|
+
|
|
107
|
+
Claude Code は毎ターン **15〜35K tokens** を送ります。`--ctx-size` / `--max-model-len` が小さいと
|
|
108
|
+
`exceed_context_size_error (400)` になります。**32768 以上**を既定に。
|
|
109
|
+
モデルの学習時 context を超える場合は YaRN 等の rope 拡張を使います。
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
llama-server -m <model>.gguf --port 8080 -ngl 99 \
|
|
113
|
+
--ctx-size 65536 --rope-scaling yarn --yarn-orig-ctx 32768
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
大きい ctx で OOM する場合は、ctx を下げる / KV 量子化(`--cache-type-k q8_0 --cache-type-v q8_0`)/ 小さいモデルへ。
|
|
117
|
+
|
|
118
|
+
### ③ チェーン末尾に「効くフォールバック」を置く
|
|
119
|
+
|
|
120
|
+
`providers:` がローカルだけだと、落ちた瞬間に逃げ先が無く **502** になります。末尾に無料クラウドを 1 本足すと、ローカルが落ちても・context が載らなくても Claude Code が止まりません。有料は `ALLOW_PAID=true` を立てない限り呼ばれません(既定 `allow_paid: false`)。
|
|
121
|
+
|
|
122
|
+
### ④ 編集の反映は 3 ステップ
|
|
123
|
+
|
|
124
|
+
動いているプロセスには即時反映されません。
|
|
125
|
+
|
|
126
|
+
1. 設定を **`~/.coderouter/providers.yaml`** に置く(`examples/` を直すだけでは効かない)
|
|
127
|
+
2. **`coderouter serve` を再起動**(`launcher:` / プロファイルは起動時に読まれる)
|
|
128
|
+
3. **バックエンドを起動し直す**(`--ctx-size` 等は再起動して初めて効く)
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## トラブルシュート早見表
|
|
133
|
+
|
|
134
|
+
| 症状 / ログ | 原因 | 対処 |
|
|
135
|
+
|---|---|---|
|
|
136
|
+
| `400 exceed_context_size_error` `n_ctx:4096` | ctx-size が小さく Claude Code の prompt が入らない | `--ctx-size 32768` 以上で**起動し直す**。学習 ctx 超は YaRN |
|
|
137
|
+
| `transport error: All connection attempts failed` (status: null) | バックエンドが落ちている / **ポート不一致** | サーバを起動 + `base_url` のポートを実ポートに合わせる |
|
|
138
|
+
| すべて `provider-failed` → **502 Bad Gateway** | チェーンの逃げ先が全滅 | バックエンドを 1 つ復旧 + 末尾に無料クラウド fallback |
|
|
139
|
+
| 起動し直しても `n_ctx=4096` のまま | 旧プロセスが残存 / 設定が `~/.coderouter` に未反映 / serve 未再起動 | `ps aux \| grep llama-server` で実コマンド確認 → 反映3ステップ |
|
|
140
|
+
| OOM でバックエンドが即落ち | ctx を上げすぎ | ctx を下げる / KV 量子化 / 小さいモデル |
|
|
141
|
+
| `capability-degraded: cache_control` | OpenAI 形式へ翻訳時に Anthropic prompt-cache マーカーを落とすだけ | **無害**。対処不要 |
|
|
142
|
+
| `claude.ai connectors are disabled …` | env の `ANTHROPIC_AUTH_TOKEN`/`API_KEY` が claude.ai ログインより優先 | CodeRouter 用 env はそのシェル/フォルダ限定に(`direnv`)。普段使いシェルでは `unset` |
|
|
143
|
+
| `/mcp` に `✘ failed` が残る | 不要な MCP サーバ登録 | `claude mcp remove <name> -s user` |
|
|
144
|
+
|
|
145
|
+
### 切り分けコマンド
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
# バックエンドが生きているか
|
|
149
|
+
curl -s localhost:8080/health ; echo # llama.cpp
|
|
150
|
+
curl -s localhost:8000/v1/models ; echo # vLLM
|
|
151
|
+
ps aux | grep -E '[l]lama-server|[v]llm'
|
|
152
|
+
|
|
153
|
+
# CodeRouter 側の状態
|
|
154
|
+
open http://localhost:8088/dashboard # 誰が落ちているか色で分かる
|
|
155
|
+
coderouter doctor --check-model llama-cpp-local # provider を 6 プローブで診断
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## 3 つのバックエンド早見
|
|
161
|
+
|
|
162
|
+
| | 何が要るか | モデル形式 | 起動の単位 |
|
|
163
|
+
|---|---|---|---|
|
|
164
|
+
| Ollama | `ollama pull` | Ollama 管理 | デーモン 1 つが on-demand |
|
|
165
|
+
| **llama.cpp** | `.gguf` + `llama-server` | `.gguf`(手元のファイル) | **1 起動 = 1 モデル = 1 ポート** |
|
|
166
|
+
| **vLLM** | NVIDIA GPU + venv | HF ID / ローカルパス | 1 起動 = 1 モデル = 1 ポート |
|
|
167
|
+
|
|
168
|
+
llama.cpp / vLLM は「起動したモデルだけ」が使えます(Ollama のように 1 つの口で複数モデルを出し分けることはしません)。複数使うならポートを分けてそれぞれ provider 登録します。
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
最終更新: 2026-06-24
|