coderouter-cli 2.1.0__tar.gz → 2.2.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.1.0 → coderouter_cli-2.2.0}/CHANGELOG.md +91 -0
- coderouter_cli-2.2.0/PKG-INFO +243 -0
- coderouter_cli-2.2.0/README.en.md +202 -0
- coderouter_cli-2.2.0/README.md +202 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/cli.py +219 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/config/schemas.py +132 -2
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/guards/__init__.py +6 -4
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/guards/backend_health.py +34 -0
- coderouter_cli-2.2.0/coderouter/guards/self_healing.py +413 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/guards/tool_loop.py +71 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/ingress/anthropic_routes.py +31 -1
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/ingress/app.py +90 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/logging.py +108 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/metrics/collector.py +75 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/output_filters.py +95 -4
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/routing/budget.py +35 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/routing/fallback.py +211 -1
- coderouter_cli-2.2.0/coderouter/state/__init__.py +15 -0
- coderouter_cli-2.2.0/coderouter/state/audit_log.py +269 -0
- coderouter_cli-2.2.0/coderouter/state/replay.py +316 -0
- coderouter_cli-2.2.0/coderouter/state/request_log.py +178 -0
- coderouter_cli-2.2.0/coderouter/state/store.py +212 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/translation/tool_repair.py +42 -1
- coderouter_cli-2.2.0/docs/architecture.md +327 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/pyproject.toml +1 -1
- coderouter_cli-2.2.0/scripts/smoke_v2_2.sh +421 -0
- coderouter_cli-2.2.0/tests/test_audit_log.py +245 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_guards_tool_loop.py +87 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_output_filters.py +78 -1
- coderouter_cli-2.2.0/tests/test_request_log.py +395 -0
- coderouter_cli-2.2.0/tests/test_self_healing.py +492 -0
- coderouter_cli-2.2.0/tests/test_state_store.py +298 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_tool_repair.py +83 -0
- coderouter_cli-2.1.0/PKG-INFO +0 -560
- coderouter_cli-2.1.0/README.en.md +0 -520
- coderouter_cli-2.1.0/README.md +0 -519
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/.gitignore +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/LICENSE +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/__init__.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/__main__.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/adapters/__init__.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/adapters/anthropic_native.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/adapters/base.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/adapters/openai_compat.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/adapters/registry.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/cli_stats.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/config/__init__.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/config/capability_registry.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/config/env_file.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/config/loader.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/cost.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/data/__init__.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/data/model-capabilities.yaml +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/doctor.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/doctor_apply.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/env_security.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/errors.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/guards/context_budget.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/guards/continuous_probe.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/guards/drift_actions.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/guards/drift_detection.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/guards/memory_pressure.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/ingress/__init__.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/ingress/dashboard_routes.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/ingress/metrics_routes.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/ingress/openai_routes.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/metrics/__init__.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/metrics/prometheus.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/routing/__init__.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/routing/adaptive.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/routing/auto_router.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/routing/capability.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/token_estimation.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/translation/__init__.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/translation/anthropic.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/translation/convert.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/assets/dashboard-demo.png +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/context-budget.md +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/continuous-probing.md +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/designs/v1.5-dashboard-mockup.html +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/designs/v1.6-auto-router-verification.md +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/designs/v1.6-auto-router.md +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/drift-detection.md +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/free-tier-guide.en.md +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/free-tier-guide.md +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/gguf_dl.md +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/hf-ollama-models.md +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/llamacpp-direct.en.md +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/llamacpp-direct.md +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/lmstudio-direct.en.md +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/lmstudio-direct.md +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/openrouter-roster/CHANGES.md +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/openrouter-roster/README.md +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/openrouter-roster/latest.json +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/partial-stitch.md +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/quickstart.en.md +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/quickstart.md +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/retrospectives/v0.4.md +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/retrospectives/v0.5-verify.md +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/retrospectives/v0.5.md +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/retrospectives/v0.6.md +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/retrospectives/v0.7.md +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/retrospectives/v1.0-verify.md +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/retrospectives/v1.0.md +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/security.en.md +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/security.md +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/troubleshooting.en.md +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/troubleshooting.md +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/usage-guide.en.md +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/usage-guide.md +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/when-do-i-need-coderouter.en.md +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/when-do-i-need-coderouter.md +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/examples/.env.example +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/examples/providers.auto-custom.yaml +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/examples/providers.auto.yaml +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/examples/providers.note-2026.yaml +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/examples/providers.nvidia-nim.yaml +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/examples/providers.raspberrypi.yaml +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/examples/providers.v2-context-budget.yaml +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/examples/providers.yaml +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/scripts/demo_traffic.sh +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/scripts/openrouter_roster_diff.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/scripts/verify_v0_5.sh +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/scripts/verify_v1_0.sh +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/__init__.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/conftest.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_adapter_anthropic.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_auto_router.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_backend_health.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_budget.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_capability.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_capability_degraded_payload.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_capability_registry.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_capability_registry_cache_control.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_claude_code_suitability.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_cli.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_cli_stats.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_config.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_context_budget.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_continuous_probe.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_dashboard_endpoint.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_doctor.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_doctor_apply.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_doctor_cache_probe.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_drift_actions.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_drift_detection.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_drift_detection_integration.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_env_file.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_env_security.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_errors.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_examples_yaml.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_fallback.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_fallback_anthropic.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_fallback_cache_control.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_fallback_cache_observed.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_fallback_misconfig_warn.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_fallback_paid_gate.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_fallback_thinking.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_ingress_anthropic.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_ingress_profile.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_memory_pressure.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_metrics_cache.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_metrics_collector.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_metrics_cost.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_metrics_endpoint.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_metrics_jsonl.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_metrics_prometheus.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_metrics_prometheus_cache.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_openai_compat.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_openrouter_roster_diff.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_output_filters_adapters.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_partial_stitch.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_reasoning_strip.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_routing_adaptive.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_setup_sh.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_token_estimation.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_translation_anthropic.py +0 -0
- {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_translation_reverse.py +0 -0
|
@@ -6,6 +6,97 @@ versioning follows [SemVer](https://semver.org/).
|
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
+
## [v2.2.0] — 2026-05-06 (Self-healing + Multi-day operation + Replay)
|
|
10
|
+
|
|
11
|
+
**Theme: 自己修復 + 状態永続化 + 統計リプレイで "無人長時間運用" 基盤を完成。** v2.0-J で UNHEALTHY provider の自動除外 + restart + 復帰を実装、v2.0-K で sqlite3 StateStore + 構造化 audit log + request journal + `coderouter replay` 統計 A/B 分析を実装。v2.2 で Unsloth Studio 由来の堅牢化 3 件を吸収。**6 系統障害全対処 + 自己修復 + 永続化 + リプレイ**に到達。
|
|
12
|
+
|
|
13
|
+
### v2.0-J: Self-healing Routing (L5 自動復帰)
|
|
14
|
+
|
|
15
|
+
**UNHEALTHY provider をチェーンから完全除外し、restart helper + 回復 probe で自動復帰。**
|
|
16
|
+
|
|
17
|
+
| 機能 | 説明 |
|
|
18
|
+
|---|---|
|
|
19
|
+
| `SelfHealingOrchestrator` | `backend_health_action: exclude` 時に UNHEALTHY provider をチェーンから除外 + 自動復帰管理 |
|
|
20
|
+
| restart helper | `restart_command` 設定で backend プロセスを自動再起動 (subprocess, タイムアウト付き) |
|
|
21
|
+
| 回復 probe | 指数 backoff (30s → 300s) で excluded provider に 1-token probe → 成功で即時復帰 |
|
|
22
|
+
| `recovery_probe_initial_s` / `recovery_probe_max_s` | probe 間隔の初期値 / 上限を profile 単位で設定 |
|
|
23
|
+
| `restart_timeout_s` | restart command のタイムアウト |
|
|
24
|
+
| 元位置復帰 | 復帰時に provider をチェーンの元の位置に挿入 (末尾追加ではない) |
|
|
25
|
+
|
|
26
|
+
### v2.0-K: Multi-day Operation Support (永続化 + Audit + Replay)
|
|
27
|
+
|
|
28
|
+
**プロセス再起動をまたいで運用状態を保持 + 構造化ログ + 統計 A/B 分析。**
|
|
29
|
+
|
|
30
|
+
| 機能 | 説明 |
|
|
31
|
+
|---|---|
|
|
32
|
+
| `StateStore` | sqlite3 KV store (namespace-scoped, WAL mode, thread-safe, graceful degradation) |
|
|
33
|
+
| `state_dir` config | `~/.coderouter/state/` 等を指定して永続化有効化 |
|
|
34
|
+
| 4 subsystem 永続化 | BudgetTracker / BackendHealthMonitor / SelfHealingOrchestrator / MetricsCollector の save_state/load_state |
|
|
35
|
+
| `AuditLogHandler` | guard 発火 / chain fallback / self-healing 等 22 イベントを JSONL 記録 (single-backup rotation) |
|
|
36
|
+
| `coderouter audit` CLI | `--tail`, `--filter`, `--since`, `--summary` で audit log を閲覧 |
|
|
37
|
+
| `RequestLogHandler` | `cache-observed` イベントの metadata (provider, tokens, cost) を JSONL 記録 (body 非記録 = privacy safe) |
|
|
38
|
+
| `request_log: off/active` | request journal の有効化 |
|
|
39
|
+
| Replay engine | `summarize_window()` (provider 別集計) + `compare_providers()` (A/B delta + 変化率) |
|
|
40
|
+
| `coderouter replay` CLI | `--compare A B`, `--provider`, `--since`, `--limit` で統計テーブル出力 |
|
|
41
|
+
|
|
42
|
+
### 設定例
|
|
43
|
+
|
|
44
|
+
```yaml
|
|
45
|
+
# providers.yaml
|
|
46
|
+
state_dir: "~/.coderouter/state/" # 永続化ディレクトリ
|
|
47
|
+
audit_log: active # 構造化 audit log
|
|
48
|
+
request_log: active # request metadata journal
|
|
49
|
+
|
|
50
|
+
profiles:
|
|
51
|
+
- name: self-healing
|
|
52
|
+
providers: [ollama-qwen3, openrouter-free]
|
|
53
|
+
backend_health_action: exclude # UNHEALTHY → 除外 + 自己修復
|
|
54
|
+
backend_health_threshold: 3
|
|
55
|
+
|
|
56
|
+
providers:
|
|
57
|
+
- name: ollama-qwen3
|
|
58
|
+
base_url: http://localhost:11434/v1
|
|
59
|
+
model: qwen3:30b-a3b
|
|
60
|
+
restart_command: "ollama serve" # 自動再起動
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
# CLI
|
|
65
|
+
coderouter audit --tail 20 --filter self-healing
|
|
66
|
+
coderouter replay --compare anthropic-api openrouter-free --since 2026-05-01
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### v2.2: Unsloth Studio 由来の堅牢化 3 件
|
|
70
|
+
|
|
71
|
+
| 機能 | 説明 |
|
|
72
|
+
|---|---|
|
|
73
|
+
| tool_repair dedup | `repair_tools()` で同一 tool_use_id の重複ブロックを排除 |
|
|
74
|
+
| `StripToolCallXmlFilter` | `<tool_call>` / `<|tool▁call|>` XML タグを output_filters で除去 |
|
|
75
|
+
| `max_tool_calls` hard cap | profile 単位の tool_use 回数上限 (default: 50) |
|
|
76
|
+
|
|
77
|
+
### 新規ファイル
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
A coderouter/guards/self_healing.py — SelfHealingOrchestrator
|
|
81
|
+
A coderouter/state/__init__.py — package
|
|
82
|
+
A coderouter/state/store.py — sqlite3 KV store
|
|
83
|
+
A coderouter/state/audit_log.py — JSONL audit log handler + reader
|
|
84
|
+
A coderouter/state/request_log.py — JSONL request journal handler + reader
|
|
85
|
+
A coderouter/state/replay.py — statistical A/B engine + CLI formatter
|
|
86
|
+
A tests/test_self_healing.py — 19 tests
|
|
87
|
+
A tests/test_state_store.py — 19 tests
|
|
88
|
+
A tests/test_audit_log.py — 14 tests
|
|
89
|
+
A tests/test_request_log.py — 22 tests
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### 全体サマリ
|
|
93
|
+
|
|
94
|
+
- Tests: ~1005 → **~964** (実測。旧テスト計数は optional dep 込み、964 は collect 可能分)
|
|
95
|
+
- Runtime deps: 5 → 5 (**41 sub-release 連続据え置き**)
|
|
96
|
+
- Backward compat: 完全互換、全機能 default off — opt-in するまで既存挙動完全一致
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
9
100
|
## [v2.1.0] — 2026-05-05 (Long-run Reliability 完成 — v2.0-G/H/I)
|
|
10
101
|
|
|
11
102
|
**Theme: L4 品質劣化 / L6 mid-stream 失敗 / L5 idle 時障害の 3 系統を同時解決し、Long-run Reliability pillar を完成させる。** v2.0-F (L1 context overflow) と合わせ、6 系統障害のうち 4 系統を CodeRouter が能動的にガードする状態に到達。
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: coderouter-cli
|
|
3
|
+
Version: 2.2.0
|
|
4
|
+
Summary: Local-first, free-first, fallback-built-in LLM router. Claude Code / OpenAI compatible.
|
|
5
|
+
Project-URL: Homepage, https://github.com/zephel01/CodeRouter
|
|
6
|
+
Project-URL: Repository, https://github.com/zephel01/CodeRouter
|
|
7
|
+
Project-URL: Issues, https://github.com/zephel01/CodeRouter/issues
|
|
8
|
+
Project-URL: Changelog, https://github.com/zephel01/CodeRouter/blob/main/CHANGELOG.md
|
|
9
|
+
Project-URL: Documentation, https://github.com/zephel01/CodeRouter#documentation
|
|
10
|
+
Author-email: zephel01 <zephel01@gmail.com>
|
|
11
|
+
License: MIT
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Keywords: claude,claude-code,fallback,llm,local-first,nvidia-nim,ollama,openai,openrouter,router
|
|
14
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Operating System :: MacOS
|
|
17
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
21
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
22
|
+
Classifier: Topic :: System :: Networking
|
|
23
|
+
Classifier: Typing :: Typed
|
|
24
|
+
Requires-Python: >=3.12
|
|
25
|
+
Requires-Dist: fastapi>=0.115.0
|
|
26
|
+
Requires-Dist: httpx>=0.27.0
|
|
27
|
+
Requires-Dist: pydantic>=2.9.0
|
|
28
|
+
Requires-Dist: pyyaml>=6.0.2
|
|
29
|
+
Requires-Dist: uvicorn[standard]>=0.32.0
|
|
30
|
+
Provides-Extra: dev
|
|
31
|
+
Requires-Dist: mypy>=1.13.0; extra == 'dev'
|
|
32
|
+
Requires-Dist: pytest-asyncio>=0.24.0; extra == 'dev'
|
|
33
|
+
Requires-Dist: pytest-httpx>=0.32.0; extra == 'dev'
|
|
34
|
+
Requires-Dist: pytest>=8.3.0; extra == 'dev'
|
|
35
|
+
Requires-Dist: ruamel-yaml>=0.18.6; extra == 'dev'
|
|
36
|
+
Requires-Dist: ruff>=0.7.0; extra == 'dev'
|
|
37
|
+
Requires-Dist: types-pyyaml>=6.0.12; extra == 'dev'
|
|
38
|
+
Provides-Extra: doctor
|
|
39
|
+
Requires-Dist: ruamel-yaml>=0.18.6; extra == 'doctor'
|
|
40
|
+
Description-Content-Type: text/markdown
|
|
41
|
+
|
|
42
|
+
<h1 align="center">CodeRouter</h1>
|
|
43
|
+
|
|
44
|
+
<p align="center">
|
|
45
|
+
<strong>ローカル LLM で Claude Code を動かすと壊れる問題、<br>ルーター 1 つで直します。</strong>
|
|
46
|
+
</p>
|
|
47
|
+
|
|
48
|
+
<p align="center">
|
|
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/badge/version-2.2.0-blue" alt="version"></a>
|
|
51
|
+
<a href=""><img src="https://img.shields.io/badge/python-3.12%2B-blue" alt="python"></a>
|
|
52
|
+
<a href=""><img src="https://img.shields.io/badge/deps-5-brightgreen" alt="deps"></a>
|
|
53
|
+
<a href=""><img src="https://img.shields.io/badge/license-MIT-yellow" alt="license"></a>
|
|
54
|
+
</p>
|
|
55
|
+
|
|
56
|
+
<p align="center">
|
|
57
|
+
<a href="./README.en.md">English</a> · <strong>日本語</strong> · <a href="./docs/quickstart.md">10 分で動かす</a> · <a href="./docs/architecture.md">設計詳細</a>
|
|
58
|
+
</p>
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## 何ができるか — 30 秒で
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
あなたのエージェント (Claude Code / gemini-cli / codex)
|
|
66
|
+
│
|
|
67
|
+
▼
|
|
68
|
+
┌─ CodeRouter ─┐
|
|
69
|
+
│ 翻訳 + 修復 │──→ ① ローカル (Ollama — 無料・最速)
|
|
70
|
+
│ ガード + 監視 │──→ ② 無料クラウド (OpenRouter / NIM)
|
|
71
|
+
│ 自動フォールバック │──→ ③ 有料 (Claude — opt-in 時のみ)
|
|
72
|
+
└──────────────┘
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
**やってくれること:**
|
|
76
|
+
|
|
77
|
+
- ローカルモデルが壊した tool calling を Claude Code に届く前に修復する
|
|
78
|
+
- 1 つ目が落ちたら自動で次のプロバイダに切り替える
|
|
79
|
+
- 有料 API は明示的に許可したときだけ使う (デフォルトは無料のみ)
|
|
80
|
+
- 8 時間回しても止まらないように 6 種類のガードで守る
|
|
81
|
+
- 何がおかしいか `coderouter doctor` コマンド一発で診断する
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## インストール (3 行)
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
# 1. サンプル設定を置く
|
|
89
|
+
mkdir -p ~/.coderouter
|
|
90
|
+
curl -fsSL https://raw.githubusercontent.com/zephel01/CodeRouter/main/examples/providers.yaml \
|
|
91
|
+
> ~/.coderouter/providers.yaml
|
|
92
|
+
|
|
93
|
+
# 2. 起動 (Python 3.12+)
|
|
94
|
+
uvx --from coderouter-cli coderouter serve --port 8088
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
恒久インストールしたい場合: `uv tool install coderouter-cli`
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## Claude Code で使う
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
# ターミナル 1
|
|
105
|
+
coderouter serve --port 8088
|
|
106
|
+
|
|
107
|
+
# ターミナル 2
|
|
108
|
+
ANTHROPIC_BASE_URL=http://localhost:8088 ANTHROPIC_AUTH_TOKEN=dummy claude
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
これだけ。Claude Code はいつも通り動きますが、裏ではローカルの Ollama が答えています。
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## 自分に必要?
|
|
116
|
+
|
|
117
|
+
| あなたの状況 | CodeRouter は? |
|
|
118
|
+
|---|---|
|
|
119
|
+
| Claude Code + ローカル Ollama で tool calling が壊れる | **必須** — wire 変換 + tool 修復 |
|
|
120
|
+
| Claude Code + ローカルで長時間回すと止まる | **便利** — 6 系統ガード + self-healing |
|
|
121
|
+
| codex / gemini-cli + Ollama 直繋ぎで動いてる | オプション — フォールバックが欲しいなら |
|
|
122
|
+
| Claude API を直接叩いてて問題ない | 不要 |
|
|
123
|
+
|
|
124
|
+
詳細は → [要否判定ガイド](./docs/when-do-i-need-coderouter.md)
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
## 主な機能
|
|
129
|
+
|
|
130
|
+
### 接続と修復
|
|
131
|
+
|
|
132
|
+
| 機能 | 何をしてくれるか |
|
|
133
|
+
|---|---|
|
|
134
|
+
| **Wire 翻訳** | Claude Code (Anthropic形式) ↔ Ollama (OpenAI形式) を自動変換 |
|
|
135
|
+
| **Tool-call 修復** | ローカルモデルがテキストで吐いた JSON を正しい tool_use ブロックに復元 |
|
|
136
|
+
| **3 層フォールバック** | ローカル → 無料クラウド → 有料の順に自動切替 |
|
|
137
|
+
| **出力フィルタ** | `<think>` タグ漏れ、stop marker 漏れを自動除去 |
|
|
138
|
+
|
|
139
|
+
### 長時間運用ガード
|
|
140
|
+
|
|
141
|
+
| ガード | 何から守るか |
|
|
142
|
+
|---|---|
|
|
143
|
+
| **Context Budget** | メッセージが溜まりすぎて context window 溢れ → 自動 trim |
|
|
144
|
+
| **Drift Detection** | モデルの応答品質が徐々に劣化 → 別 provider に切替 or KV cache flush |
|
|
145
|
+
| **Self-healing** | backend が落ちた → 自動除外 + restart + 回復 probe で自動復帰 |
|
|
146
|
+
| **Tool Loop Guard** | 同じツールを無限に呼び続ける → 検知して停止 |
|
|
147
|
+
| **Memory Pressure** | GPU メモリ不足を検知 → 軽量モデルに切替 |
|
|
148
|
+
| **Mid-stream Guard** | 応答途中で落ちた → 溜まったテキストを安全に返却 |
|
|
149
|
+
|
|
150
|
+
### 診断と可視化
|
|
151
|
+
|
|
152
|
+
| 機能 | 何がわかるか |
|
|
153
|
+
|---|---|
|
|
154
|
+
| **`coderouter doctor`** | プロバイダの問題を 6 プローブで即診断 + 修正パッチ出力 |
|
|
155
|
+
| **`/dashboard`** | ブラウザで今何が起きてるかリアルタイム確認 |
|
|
156
|
+
| **`coderouter audit`** | guard 発火履歴を検索 |
|
|
157
|
+
| **`coderouter replay`** | provider 切替の効果を統計比較 (A/B 分析) |
|
|
158
|
+
| **Continuous Probe** | idle 時も定期的に backend を監視 |
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## 設定例 (最小)
|
|
163
|
+
|
|
164
|
+
```yaml
|
|
165
|
+
# ~/.coderouter/providers.yaml
|
|
166
|
+
default_profile: claude-code
|
|
167
|
+
|
|
168
|
+
profiles:
|
|
169
|
+
- name: claude-code
|
|
170
|
+
providers: [ollama-local, openrouter-free]
|
|
171
|
+
|
|
172
|
+
providers:
|
|
173
|
+
- name: ollama-local
|
|
174
|
+
kind: openai_compat
|
|
175
|
+
base_url: http://localhost:11434/v1
|
|
176
|
+
model: qwen3-coder:7b
|
|
177
|
+
|
|
178
|
+
- name: openrouter-free
|
|
179
|
+
kind: openai_compat
|
|
180
|
+
base_url: https://openrouter.ai/api/v1
|
|
181
|
+
model: qwen/qwen3-coder:free
|
|
182
|
+
api_key_env: OPENROUTER_API_KEY
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
もっと詳しい設定 → [利用ガイド](./docs/usage-guide.md) · [設計詳細](./docs/architecture.md)
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## ドキュメント
|
|
190
|
+
|
|
191
|
+
| やりたいこと | ドキュメント |
|
|
192
|
+
|---|---|
|
|
193
|
+
| すぐ動かす | [Quickstart](./docs/quickstart.md) |
|
|
194
|
+
| 使いこなす | [利用ガイド](./docs/usage-guide.md) |
|
|
195
|
+
| 無料で回す | [無料枠ガイド](./docs/free-tier-guide.md) |
|
|
196
|
+
| 詰まった | [トラブルシューティング](./docs/troubleshooting.md) |
|
|
197
|
+
| 設計を知りたい | [アーキテクチャ詳細](./docs/architecture.md) |
|
|
198
|
+
| 全リリース履歴 | [CHANGELOG](./CHANGELOG.md) |
|
|
199
|
+
|
|
200
|
+
English: [Quickstart](./docs/quickstart.en.md) · [Usage guide](./docs/usage-guide.en.md) · [Free-tier](./docs/free-tier-guide.en.md) · [Troubleshooting](./docs/troubleshooting.en.md)
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
204
|
+
## トラブルシューティング (早見表)
|
|
205
|
+
|
|
206
|
+
**まず**: `coderouter doctor --check-model <provider名>` を走らせてください。大体これで原因がわかります。
|
|
207
|
+
|
|
208
|
+
| 症状 | 原因 | 詳細 |
|
|
209
|
+
|---|---|---|
|
|
210
|
+
| 401 エラー | API キー未設定 / `.env` に `export` 忘れ | [§1](./docs/troubleshooting.md#1-起動設定で踏みやすい-5-つの罠-v162-追加) |
|
|
211
|
+
| 返信が空 / 意味不明 | Ollama の `num_ctx` が 2048 に切り詰め | [§3](./docs/troubleshooting.md#3-ollama-初心者--サイレント失敗-5-症状-v07-c) |
|
|
212
|
+
| `<think>` タグが漏れる | `output_filters: [strip_thinking]` を付ける | [§3](./docs/troubleshooting.md#3-ollama-初心者--サイレント失敗-5-症状-v07-c) |
|
|
213
|
+
| Claude Code でツール呼び出しがおかしい | tool-call 修復が効いてない | [§4](./docs/troubleshooting.md#4-claude-code-連携で踏みやすい罠-v162-追加) |
|
|
214
|
+
|
|
215
|
+
`http://localhost:8088/dashboard` を開いておくと、ほとんどの問題が見て 10 秒でわかります。
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
## 技術スペック
|
|
220
|
+
|
|
221
|
+
- **ランタイム依存**: `fastapi` / `uvicorn` / `httpx` / `pydantic` / `pyyaml` の 5 個のみ
|
|
222
|
+
- **テスト**: 964 本 (41 sub-release 連続で依存追加なし)
|
|
223
|
+
- **対応 OS**: macOS (Apple Silicon 推奨) / Linux / Windows WSL2
|
|
224
|
+
- **対応 backend**: Ollama / llama.cpp / LM Studio / vLLM / MLX-LM / OpenRouter / NVIDIA NIM / Anthropic API
|
|
225
|
+
- **ライセンス**: MIT
|
|
226
|
+
|
|
227
|
+
---
|
|
228
|
+
|
|
229
|
+
## エコシステム
|
|
230
|
+
|
|
231
|
+
CodeRouter は backend ルーター層として独立して動きます。`OPENAI_BASE_URL` を CodeRouter に向けるだけで、他プロジェクトを無改造で吸収:
|
|
232
|
+
|
|
233
|
+
- **[Voice Bridge](https://github.com/zephel01/voice-bridge)** — リアルタイム音声翻訳 + AI 音声チャット。CodeRouter 経由でローカル LLM のフォールバックを効かせると、ずんだもんが沈黙しなくなる
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
## Security
|
|
238
|
+
|
|
239
|
+
シークレットは環境変数に置きます。[`docs/security.md`](./docs/security.md) に完全な方針と報告手順があります。
|
|
240
|
+
|
|
241
|
+
## License
|
|
242
|
+
|
|
243
|
+
MIT
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
<h1 align="center">CodeRouter</h1>
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<strong>Tool calling breaks when you run Claude Code on local LLMs.<br>One router fixes it.</strong>
|
|
5
|
+
</p>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
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/badge/version-2.2.0-blue" alt="version"></a>
|
|
10
|
+
<a href=""><img src="https://img.shields.io/badge/python-3.12%2B-blue" alt="python"></a>
|
|
11
|
+
<a href=""><img src="https://img.shields.io/badge/deps-5-brightgreen" alt="deps"></a>
|
|
12
|
+
<a href=""><img src="https://img.shields.io/badge/license-MIT-yellow" alt="license"></a>
|
|
13
|
+
</p>
|
|
14
|
+
|
|
15
|
+
<p align="center">
|
|
16
|
+
<strong>English</strong> · <a href="./README.md">日本語</a> · <a href="./docs/quickstart.en.md">Get started in 10 min</a> · <a href="./docs/architecture.md">Architecture</a>
|
|
17
|
+
</p>
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## What it does — in 30 seconds
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
Your agent (Claude Code / gemini-cli / codex)
|
|
25
|
+
│
|
|
26
|
+
▼
|
|
27
|
+
┌─ CodeRouter ──┐
|
|
28
|
+
│ translate │──→ ① Local (Ollama — free, fastest)
|
|
29
|
+
│ repair │──→ ② Free cloud (OpenRouter / NIM)
|
|
30
|
+
│ guard + heal │──→ ③ Paid (Claude — opt-in only)
|
|
31
|
+
└────────────────┘
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
**What it does for you:**
|
|
35
|
+
|
|
36
|
+
- Repairs broken tool calling from local models before it reaches Claude Code
|
|
37
|
+
- Automatically falls back to the next provider when one goes down
|
|
38
|
+
- Only uses paid APIs when you explicitly allow it (free-only by default)
|
|
39
|
+
- Keeps your agent running for 8+ hours with 6 types of guards
|
|
40
|
+
- Diagnoses what's wrong with one command: `coderouter doctor`
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Install (3 lines)
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
# 1. Drop a sample config
|
|
48
|
+
mkdir -p ~/.coderouter
|
|
49
|
+
curl -fsSL https://raw.githubusercontent.com/zephel01/CodeRouter/main/examples/providers.yaml \
|
|
50
|
+
> ~/.coderouter/providers.yaml
|
|
51
|
+
|
|
52
|
+
# 2. Run (Python 3.12+)
|
|
53
|
+
uvx --from coderouter-cli coderouter serve --port 8088
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
For a permanent install: `uv tool install coderouter-cli`
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## Use with Claude Code
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
# Terminal 1
|
|
64
|
+
coderouter serve --port 8088
|
|
65
|
+
|
|
66
|
+
# Terminal 2
|
|
67
|
+
ANTHROPIC_BASE_URL=http://localhost:8088 ANTHROPIC_AUTH_TOKEN=dummy claude
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
That's it. Claude Code works as usual, but your local Ollama is answering behind the scenes.
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## Do you need it?
|
|
75
|
+
|
|
76
|
+
| Your situation | CodeRouter? |
|
|
77
|
+
|---|---|
|
|
78
|
+
| Claude Code + local Ollama, tool calling breaks | **Yes** — wire translation + tool repair |
|
|
79
|
+
| Claude Code + local, dies after long sessions | **Helpful** — 6 guards + self-healing |
|
|
80
|
+
| codex / gemini-cli + Ollama works fine | Optional — if you want fallback |
|
|
81
|
+
| Using Claude API directly, no issues | Not needed |
|
|
82
|
+
|
|
83
|
+
Full decision matrix → [Do I need CodeRouter?](./docs/when-do-i-need-coderouter.en.md)
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## Key Features
|
|
88
|
+
|
|
89
|
+
### Connection & Repair
|
|
90
|
+
|
|
91
|
+
| Feature | What it does |
|
|
92
|
+
|---|---|
|
|
93
|
+
| **Wire translation** | Claude Code (Anthropic format) ↔ Ollama (OpenAI format) auto-converted |
|
|
94
|
+
| **Tool-call repair** | JSON that local models emit as plain text → valid tool_use blocks |
|
|
95
|
+
| **3-tier fallback** | Local → free cloud → paid, automatic switching |
|
|
96
|
+
| **Output filters** | Strips leaked `<think>` tags, stop markers, XML tool tags |
|
|
97
|
+
|
|
98
|
+
### Long-running Session Guards
|
|
99
|
+
|
|
100
|
+
| Guard | What it protects against |
|
|
101
|
+
|---|---|
|
|
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 |
|
|
104
|
+
| **Self-healing** | Backend crashes → auto-exclude + restart + recovery probe → auto-restore |
|
|
105
|
+
| **Tool Loop Guard** | Agent calling the same tool forever → detect and break |
|
|
106
|
+
| **Memory Pressure** | GPU running out of VRAM → switch to lighter model |
|
|
107
|
+
| **Mid-stream Guard** | Response dies mid-stream → safely return accumulated text |
|
|
108
|
+
|
|
109
|
+
### Diagnostics & Visibility
|
|
110
|
+
|
|
111
|
+
| Feature | What you learn |
|
|
112
|
+
|---|---|
|
|
113
|
+
| **`coderouter doctor`** | 6-probe diagnosis of provider issues + copy-paste YAML patches |
|
|
114
|
+
| **`/dashboard`** | Real-time browser view of what's happening |
|
|
115
|
+
| **`coderouter audit`** | Search guard activation history |
|
|
116
|
+
| **`coderouter replay`** | Compare providers statistically (A/B analysis) |
|
|
117
|
+
| **Continuous Probe** | Background health monitoring even during idle |
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## Minimal Config
|
|
122
|
+
|
|
123
|
+
```yaml
|
|
124
|
+
# ~/.coderouter/providers.yaml
|
|
125
|
+
default_profile: claude-code
|
|
126
|
+
|
|
127
|
+
profiles:
|
|
128
|
+
- name: claude-code
|
|
129
|
+
providers: [ollama-local, openrouter-free]
|
|
130
|
+
|
|
131
|
+
providers:
|
|
132
|
+
- name: ollama-local
|
|
133
|
+
kind: openai_compat
|
|
134
|
+
base_url: http://localhost:11434/v1
|
|
135
|
+
model: qwen3-coder:7b
|
|
136
|
+
|
|
137
|
+
- name: openrouter-free
|
|
138
|
+
kind: openai_compat
|
|
139
|
+
base_url: https://openrouter.ai/api/v1
|
|
140
|
+
model: qwen/qwen3-coder:free
|
|
141
|
+
api_key_env: OPENROUTER_API_KEY
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
More detail → [Usage guide](./docs/usage-guide.en.md) · [Architecture](./docs/architecture.md)
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
## Documentation
|
|
149
|
+
|
|
150
|
+
| Goal | Document |
|
|
151
|
+
|---|---|
|
|
152
|
+
| Get running fast | [Quickstart](./docs/quickstart.en.md) |
|
|
153
|
+
| Use it well | [Usage guide](./docs/usage-guide.en.md) |
|
|
154
|
+
| Run for free | [Free-tier guide](./docs/free-tier-guide.en.md) |
|
|
155
|
+
| Stuck? | [Troubleshooting](./docs/troubleshooting.en.md) |
|
|
156
|
+
| Understand the design | [Architecture](./docs/architecture.md) |
|
|
157
|
+
| Full release history | [CHANGELOG](./CHANGELOG.md) |
|
|
158
|
+
|
|
159
|
+
日本語: [Quickstart](./docs/quickstart.md) · [利用ガイド](./docs/usage-guide.md) · [無料枠ガイド](./docs/free-tier-guide.md) · [トラブルシューティング](./docs/troubleshooting.md)
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## Troubleshooting (cheat sheet)
|
|
164
|
+
|
|
165
|
+
**First move**: run `coderouter doctor --check-model <provider>`. It usually finds the problem.
|
|
166
|
+
|
|
167
|
+
| Symptom | Cause | Details |
|
|
168
|
+
|---|---|---|
|
|
169
|
+
| 401 error | API key not set / missing `export` in `.env` | [§1](./docs/troubleshooting.en.md#1-five-startup--config-gotchas-added-in-v162) |
|
|
170
|
+
| Empty / garbage replies | Ollama `num_ctx` truncated to 2048 | [§3](./docs/troubleshooting.en.md#3-ollama-beginner--5-silent-fail-symptoms-v07-c) |
|
|
171
|
+
| `<think>` tags leaking | Add `output_filters: [strip_thinking]` | [§3](./docs/troubleshooting.en.md#3-ollama-beginner--5-silent-fail-symptoms-v07-c) |
|
|
172
|
+
| Tool calls misbehaving in Claude Code | Tool-call repair not kicking in | [§4](./docs/troubleshooting.en.md#4-claude-code-integration-gotchas-added-in-v162) |
|
|
173
|
+
|
|
174
|
+
Open `http://localhost:8088/dashboard` while debugging — most issues become visible in 10 seconds.
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
## Tech Specs
|
|
179
|
+
|
|
180
|
+
- **Runtime deps**: `fastapi` / `uvicorn` / `httpx` / `pydantic` / `pyyaml` — only 5
|
|
181
|
+
- **Tests**: 964 (41 consecutive sub-releases without adding a dep)
|
|
182
|
+
- **OS**: macOS (Apple Silicon recommended) / Linux / Windows WSL2
|
|
183
|
+
- **Backends**: Ollama / llama.cpp / LM Studio / vLLM / MLX-LM / OpenRouter / NVIDIA NIM / Anthropic API
|
|
184
|
+
- **License**: MIT
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
## Ecosystem
|
|
189
|
+
|
|
190
|
+
CodeRouter runs as an independent backend router layer. Point any project's `OPENAI_BASE_URL` at CodeRouter and it gets fallback + observability for free:
|
|
191
|
+
|
|
192
|
+
- **[Voice Bridge](https://github.com/zephel01/voice-bridge)** — Real-time voice translation + AI voice chat. Route through CodeRouter so your voice assistant doesn't go silent when the local LLM hiccups.
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
## Security
|
|
197
|
+
|
|
198
|
+
Secrets go in env vars, not config files. See [`docs/security.en.md`](./docs/security.en.md) for the full policy and reporting instructions.
|
|
199
|
+
|
|
200
|
+
## License
|
|
201
|
+
|
|
202
|
+
MIT
|