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.
Files changed (178) hide show
  1. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/CHANGELOG.md +91 -0
  2. coderouter_cli-2.2.0/PKG-INFO +243 -0
  3. coderouter_cli-2.2.0/README.en.md +202 -0
  4. coderouter_cli-2.2.0/README.md +202 -0
  5. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/cli.py +219 -0
  6. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/config/schemas.py +132 -2
  7. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/guards/__init__.py +6 -4
  8. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/guards/backend_health.py +34 -0
  9. coderouter_cli-2.2.0/coderouter/guards/self_healing.py +413 -0
  10. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/guards/tool_loop.py +71 -0
  11. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/ingress/anthropic_routes.py +31 -1
  12. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/ingress/app.py +90 -0
  13. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/logging.py +108 -0
  14. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/metrics/collector.py +75 -0
  15. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/output_filters.py +95 -4
  16. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/routing/budget.py +35 -0
  17. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/routing/fallback.py +211 -1
  18. coderouter_cli-2.2.0/coderouter/state/__init__.py +15 -0
  19. coderouter_cli-2.2.0/coderouter/state/audit_log.py +269 -0
  20. coderouter_cli-2.2.0/coderouter/state/replay.py +316 -0
  21. coderouter_cli-2.2.0/coderouter/state/request_log.py +178 -0
  22. coderouter_cli-2.2.0/coderouter/state/store.py +212 -0
  23. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/translation/tool_repair.py +42 -1
  24. coderouter_cli-2.2.0/docs/architecture.md +327 -0
  25. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/pyproject.toml +1 -1
  26. coderouter_cli-2.2.0/scripts/smoke_v2_2.sh +421 -0
  27. coderouter_cli-2.2.0/tests/test_audit_log.py +245 -0
  28. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_guards_tool_loop.py +87 -0
  29. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_output_filters.py +78 -1
  30. coderouter_cli-2.2.0/tests/test_request_log.py +395 -0
  31. coderouter_cli-2.2.0/tests/test_self_healing.py +492 -0
  32. coderouter_cli-2.2.0/tests/test_state_store.py +298 -0
  33. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_tool_repair.py +83 -0
  34. coderouter_cli-2.1.0/PKG-INFO +0 -560
  35. coderouter_cli-2.1.0/README.en.md +0 -520
  36. coderouter_cli-2.1.0/README.md +0 -519
  37. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/.gitignore +0 -0
  38. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/LICENSE +0 -0
  39. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/__init__.py +0 -0
  40. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/__main__.py +0 -0
  41. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/adapters/__init__.py +0 -0
  42. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/adapters/anthropic_native.py +0 -0
  43. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/adapters/base.py +0 -0
  44. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/adapters/openai_compat.py +0 -0
  45. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/adapters/registry.py +0 -0
  46. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/cli_stats.py +0 -0
  47. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/config/__init__.py +0 -0
  48. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/config/capability_registry.py +0 -0
  49. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/config/env_file.py +0 -0
  50. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/config/loader.py +0 -0
  51. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/cost.py +0 -0
  52. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/data/__init__.py +0 -0
  53. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/data/model-capabilities.yaml +0 -0
  54. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/doctor.py +0 -0
  55. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/doctor_apply.py +0 -0
  56. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/env_security.py +0 -0
  57. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/errors.py +0 -0
  58. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/guards/context_budget.py +0 -0
  59. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/guards/continuous_probe.py +0 -0
  60. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/guards/drift_actions.py +0 -0
  61. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/guards/drift_detection.py +0 -0
  62. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/guards/memory_pressure.py +0 -0
  63. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/ingress/__init__.py +0 -0
  64. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/ingress/dashboard_routes.py +0 -0
  65. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/ingress/metrics_routes.py +0 -0
  66. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/ingress/openai_routes.py +0 -0
  67. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/metrics/__init__.py +0 -0
  68. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/metrics/prometheus.py +0 -0
  69. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/routing/__init__.py +0 -0
  70. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/routing/adaptive.py +0 -0
  71. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/routing/auto_router.py +0 -0
  72. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/routing/capability.py +0 -0
  73. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/token_estimation.py +0 -0
  74. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/translation/__init__.py +0 -0
  75. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/translation/anthropic.py +0 -0
  76. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/coderouter/translation/convert.py +0 -0
  77. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/assets/dashboard-demo.png +0 -0
  78. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/context-budget.md +0 -0
  79. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/continuous-probing.md +0 -0
  80. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/designs/v1.5-dashboard-mockup.html +0 -0
  81. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/designs/v1.6-auto-router-verification.md +0 -0
  82. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/designs/v1.6-auto-router.md +0 -0
  83. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/drift-detection.md +0 -0
  84. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/free-tier-guide.en.md +0 -0
  85. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/free-tier-guide.md +0 -0
  86. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/gguf_dl.md +0 -0
  87. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/hf-ollama-models.md +0 -0
  88. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/llamacpp-direct.en.md +0 -0
  89. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/llamacpp-direct.md +0 -0
  90. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/lmstudio-direct.en.md +0 -0
  91. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/lmstudio-direct.md +0 -0
  92. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/openrouter-roster/CHANGES.md +0 -0
  93. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/openrouter-roster/README.md +0 -0
  94. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/openrouter-roster/latest.json +0 -0
  95. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/partial-stitch.md +0 -0
  96. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/quickstart.en.md +0 -0
  97. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/quickstart.md +0 -0
  98. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/retrospectives/v0.4.md +0 -0
  99. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/retrospectives/v0.5-verify.md +0 -0
  100. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/retrospectives/v0.5.md +0 -0
  101. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/retrospectives/v0.6.md +0 -0
  102. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/retrospectives/v0.7.md +0 -0
  103. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/retrospectives/v1.0-verify.md +0 -0
  104. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/retrospectives/v1.0.md +0 -0
  105. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/security.en.md +0 -0
  106. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/security.md +0 -0
  107. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/troubleshooting.en.md +0 -0
  108. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/troubleshooting.md +0 -0
  109. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/usage-guide.en.md +0 -0
  110. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/usage-guide.md +0 -0
  111. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/when-do-i-need-coderouter.en.md +0 -0
  112. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/docs/when-do-i-need-coderouter.md +0 -0
  113. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/examples/.env.example +0 -0
  114. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/examples/providers.auto-custom.yaml +0 -0
  115. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/examples/providers.auto.yaml +0 -0
  116. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/examples/providers.note-2026.yaml +0 -0
  117. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/examples/providers.nvidia-nim.yaml +0 -0
  118. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/examples/providers.raspberrypi.yaml +0 -0
  119. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/examples/providers.v2-context-budget.yaml +0 -0
  120. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/examples/providers.yaml +0 -0
  121. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/scripts/demo_traffic.sh +0 -0
  122. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/scripts/openrouter_roster_diff.py +0 -0
  123. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/scripts/verify_v0_5.sh +0 -0
  124. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/scripts/verify_v1_0.sh +0 -0
  125. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/__init__.py +0 -0
  126. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/conftest.py +0 -0
  127. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_adapter_anthropic.py +0 -0
  128. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_auto_router.py +0 -0
  129. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_backend_health.py +0 -0
  130. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_budget.py +0 -0
  131. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_capability.py +0 -0
  132. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_capability_degraded_payload.py +0 -0
  133. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_capability_registry.py +0 -0
  134. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_capability_registry_cache_control.py +0 -0
  135. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_claude_code_suitability.py +0 -0
  136. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_cli.py +0 -0
  137. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_cli_stats.py +0 -0
  138. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_config.py +0 -0
  139. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_context_budget.py +0 -0
  140. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_continuous_probe.py +0 -0
  141. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_dashboard_endpoint.py +0 -0
  142. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_doctor.py +0 -0
  143. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_doctor_apply.py +0 -0
  144. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_doctor_cache_probe.py +0 -0
  145. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_drift_actions.py +0 -0
  146. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_drift_detection.py +0 -0
  147. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_drift_detection_integration.py +0 -0
  148. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_env_file.py +0 -0
  149. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_env_security.py +0 -0
  150. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_errors.py +0 -0
  151. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_examples_yaml.py +0 -0
  152. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_fallback.py +0 -0
  153. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_fallback_anthropic.py +0 -0
  154. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_fallback_cache_control.py +0 -0
  155. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_fallback_cache_observed.py +0 -0
  156. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_fallback_misconfig_warn.py +0 -0
  157. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_fallback_paid_gate.py +0 -0
  158. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_fallback_thinking.py +0 -0
  159. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_ingress_anthropic.py +0 -0
  160. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_ingress_profile.py +0 -0
  161. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_memory_pressure.py +0 -0
  162. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_metrics_cache.py +0 -0
  163. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_metrics_collector.py +0 -0
  164. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_metrics_cost.py +0 -0
  165. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_metrics_endpoint.py +0 -0
  166. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_metrics_jsonl.py +0 -0
  167. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_metrics_prometheus.py +0 -0
  168. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_metrics_prometheus_cache.py +0 -0
  169. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_openai_compat.py +0 -0
  170. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_openrouter_roster_diff.py +0 -0
  171. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_output_filters_adapters.py +0 -0
  172. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_partial_stitch.py +0 -0
  173. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_reasoning_strip.py +0 -0
  174. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_routing_adaptive.py +0 -0
  175. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_setup_sh.py +0 -0
  176. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_token_estimation.py +0 -0
  177. {coderouter_cli-2.1.0 → coderouter_cli-2.2.0}/tests/test_translation_anthropic.py +0 -0
  178. {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