coderouter-cli 2.18.0__tar.gz → 2.19.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 (330) hide show
  1. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/CHANGELOG.md +67 -0
  2. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/PKG-INFO +3 -5
  3. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/README.en.md +2 -3
  4. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/README.md +2 -4
  5. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/ingress/app.py +3 -0
  6. coderouter_cli-2.19.0/coderouter/ingress/responses_routes.py +269 -0
  7. coderouter_cli-2.19.0/coderouter/translation/responses.py +686 -0
  8. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/start/quickstart.en.md +27 -16
  9. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/start/quickstart.md +27 -16
  10. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/start/when-do-i-need-coderouter.en.md +1 -1
  11. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/start/when-do-i-need-coderouter.md +1 -1
  12. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/pyproject.toml +1 -1
  13. coderouter_cli-2.19.0/tests/test_responses_api.py +398 -0
  14. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/.gitignore +0 -0
  15. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/LICENSE +0 -0
  16. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/__init__.py +0 -0
  17. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/__main__.py +0 -0
  18. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/adapters/__init__.py +0 -0
  19. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/adapters/anthropic_native.py +0 -0
  20. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/adapters/base.py +0 -0
  21. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/adapters/openai_compat.py +0 -0
  22. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/adapters/registry.py +0 -0
  23. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/adapters/slot_affinity.py +0 -0
  24. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/cli.py +0 -0
  25. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/cli_stats.py +0 -0
  26. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/config/__init__.py +0 -0
  27. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/config/capability_registry.py +0 -0
  28. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/config/env_file.py +0 -0
  29. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/config/loader.py +0 -0
  30. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/config/schemas.py +0 -0
  31. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/cost.py +0 -0
  32. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/credentials.py +0 -0
  33. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/data/__init__.py +0 -0
  34. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/data/model-capabilities.yaml +0 -0
  35. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/doctor.py +0 -0
  36. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/doctor_apply.py +0 -0
  37. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/doctor_claude_code.py +0 -0
  38. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/env_security.py +0 -0
  39. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/errors.py +0 -0
  40. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/gguf_introspect.py +0 -0
  41. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/guards/__init__.py +0 -0
  42. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/guards/_fingerprint.py +0 -0
  43. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/guards/backend_health.py +0 -0
  44. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/guards/context_budget.py +0 -0
  45. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/guards/continuous_probe.py +0 -0
  46. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/guards/drift_actions.py +0 -0
  47. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/guards/drift_detection.py +0 -0
  48. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/guards/memory_budget.py +0 -0
  49. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/guards/memory_pressure.py +0 -0
  50. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/guards/self_healing.py +0 -0
  51. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/guards/tool_loop.py +0 -0
  52. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/hardware.py +0 -0
  53. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/ingress/__init__.py +0 -0
  54. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/ingress/anthropic_errors.py +0 -0
  55. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/ingress/anthropic_routes.py +0 -0
  56. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/ingress/dashboard_routes.py +0 -0
  57. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/ingress/launcher_routes.py +0 -0
  58. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/ingress/metrics_routes.py +0 -0
  59. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/ingress/openai_routes.py +0 -0
  60. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/ingress/tool_search.py +0 -0
  61. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/ingress/ui_auth.py +0 -0
  62. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/language_tax.py +0 -0
  63. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/launcher_devices.py +0 -0
  64. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/launcher_speculative.py +0 -0
  65. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/launcher_swap.py +0 -0
  66. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/logging.py +0 -0
  67. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/metrics/__init__.py +0 -0
  68. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/metrics/collector.py +0 -0
  69. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/metrics/prometheus.py +0 -0
  70. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/output_filters.py +0 -0
  71. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/plugins/__init__.py +0 -0
  72. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/plugins/base.py +0 -0
  73. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/plugins/loader.py +0 -0
  74. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/plugins/registry.py +0 -0
  75. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/py.typed +0 -0
  76. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/rollback.py +0 -0
  77. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/routing/__init__.py +0 -0
  78. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/routing/adaptive.py +0 -0
  79. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/routing/auto_router.py +0 -0
  80. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/routing/budget.py +0 -0
  81. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/routing/capability.py +0 -0
  82. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/routing/fallback.py +0 -0
  83. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/routing/fallback_trace.py +0 -0
  84. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/secret_redaction.py +0 -0
  85. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/state/__init__.py +0 -0
  86. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/state/audit_log.py +0 -0
  87. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/state/replay.py +0 -0
  88. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/state/request_log.py +0 -0
  89. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/state/store.py +0 -0
  90. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/state/suggest_rules.py +0 -0
  91. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/token_estimation.py +0 -0
  92. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/token_estimation_accurate.py +0 -0
  93. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/translation/__init__.py +0 -0
  94. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/translation/anthropic.py +0 -0
  95. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/translation/convert.py +0 -0
  96. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/translation/tool_repair.py +0 -0
  97. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/coderouter/vscode_init.py +0 -0
  98. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/README.en.md +0 -0
  99. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/README.md +0 -0
  100. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/assets/dashboard-demo.png +0 -0
  101. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/backends/claude-code-llamacpp-vllm.en.md +0 -0
  102. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/backends/claude-code-llamacpp-vllm.md +0 -0
  103. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/backends/external-agents.en.md +0 -0
  104. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/backends/external-agents.md +0 -0
  105. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/backends/gguf_dl.en.md +0 -0
  106. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/backends/gguf_dl.md +0 -0
  107. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/backends/hf-ollama-models.en.md +0 -0
  108. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/backends/hf-ollama-models.md +0 -0
  109. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/backends/install-backends.en.md +0 -0
  110. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/backends/install-backends.md +0 -0
  111. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/backends/launcher-quickstart.en.md +0 -0
  112. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/backends/launcher-quickstart.md +0 -0
  113. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/backends/launcher.en.md +0 -0
  114. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/backends/launcher.md +0 -0
  115. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/backends/llamacpp-direct.en.md +0 -0
  116. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/backends/llamacpp-direct.md +0 -0
  117. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/backends/lmstudio-direct.en.md +0 -0
  118. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/backends/lmstudio-direct.md +0 -0
  119. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/backends/verify-ollama-0.23.1.md +0 -0
  120. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/concepts/architecture.en.md +0 -0
  121. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/concepts/architecture.md +0 -0
  122. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/concepts/commit-point.en.md +0 -0
  123. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/concepts/commit-point.md +0 -0
  124. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/concepts/context-budget.en.md +0 -0
  125. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/concepts/context-budget.md +0 -0
  126. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/concepts/continuous-probing.en.md +0 -0
  127. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/concepts/continuous-probing.md +0 -0
  128. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/concepts/drift-detection.en.md +0 -0
  129. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/concepts/drift-detection.md +0 -0
  130. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/concepts/partial-stitch.en.md +0 -0
  131. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/concepts/partial-stitch.md +0 -0
  132. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/concepts/stream-truncation.en.md +0 -0
  133. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/concepts/stream-truncation.md +0 -0
  134. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/designs/agent-cli-plugin-extraction.md +0 -0
  135. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/designs/external-agents-adapter.md +0 -0
  136. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/designs/launcher-model-swap.md +0 -0
  137. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/designs/launcher-multi-build.md +0 -0
  138. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/designs/orchestration-companion.md +0 -0
  139. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/designs/v1.5-dashboard-mockup.html +0 -0
  140. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/designs/v1.6-auto-router-verification.md +0 -0
  141. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/designs/v1.6-auto-router.md +0 -0
  142. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/guides/free-tier-guide.en.md +0 -0
  143. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/guides/free-tier-guide.md +0 -0
  144. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/guides/language-tax.en.md +0 -0
  145. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/guides/language-tax.md +0 -0
  146. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/guides/remote-access.en.md +0 -0
  147. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/guides/remote-access.md +0 -0
  148. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/guides/security.en.md +0 -0
  149. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/guides/security.md +0 -0
  150. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/guides/subagent-routing.en.md +0 -0
  151. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/guides/subagent-routing.md +0 -0
  152. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/guides/troubleshooting.en.md +0 -0
  153. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/guides/troubleshooting.md +0 -0
  154. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/guides/usage-guide.en.md +0 -0
  155. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/guides/usage-guide.md +0 -0
  156. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/guides/vscode.md +0 -0
  157. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/low-memory-integration.en.md +0 -0
  158. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/low-memory-integration.md +0 -0
  159. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/openrouter-roster/CHANGES.md +0 -0
  160. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/openrouter-roster/README.md +0 -0
  161. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/openrouter-roster/latest.json +0 -0
  162. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/retrospectives/v0.4.md +0 -0
  163. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/retrospectives/v0.5-verify.md +0 -0
  164. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/retrospectives/v0.5.md +0 -0
  165. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/retrospectives/v0.6.md +0 -0
  166. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/retrospectives/v0.7.md +0 -0
  167. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/retrospectives/v1.0-verify.md +0 -0
  168. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/docs/retrospectives/v1.0.md +0 -0
  169. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/examples/.env.example +0 -0
  170. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/examples/README.md +0 -0
  171. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/examples/providers-agent-cli.yaml +0 -0
  172. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/examples/providers-multiagent.yaml +0 -0
  173. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/examples/providers.cli-session.yaml +0 -0
  174. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/examples/providers.context-budget-test.yaml +0 -0
  175. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/examples/providers.llamacpp-vllm.yaml +0 -0
  176. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/examples/providers.nvidia-nim.yaml +0 -0
  177. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/examples/providers.ollama-auto-custom.yaml +0 -0
  178. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/examples/providers.ollama-auto.yaml +0 -0
  179. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/examples/providers.ollama-free-chain.yaml +0 -0
  180. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/examples/providers.opusplan.yaml +0 -0
  181. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/examples/providers.raspberrypi.yaml +0 -0
  182. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/examples/providers.swap.yaml +0 -0
  183. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/examples/providers.yaml +0 -0
  184. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/scripts/demo_traffic.sh +0 -0
  185. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/scripts/openrouter_roster_diff.py +0 -0
  186. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/scripts/smoke_v2_2.sh +0 -0
  187. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/scripts/verify-providers.yaml +0 -0
  188. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/scripts/verify_ollama_0_23.py +0 -0
  189. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/scripts/verify_v0_5.sh +0 -0
  190. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/scripts/verify_v1_0.sh +0 -0
  191. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/__init__.py +0 -0
  192. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/conftest.py +0 -0
  193. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_adapter_anthropic.py +0 -0
  194. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_agent_cli.py +0 -0
  195. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_anthropic_errors.py +0 -0
  196. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_audit_log.py +0 -0
  197. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_auto_router.py +0 -0
  198. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_auto_router_cjk.py +0 -0
  199. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_auto_router_hints.py +0 -0
  200. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_backend_health.py +0 -0
  201. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_budget.py +0 -0
  202. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_capability.py +0 -0
  203. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_capability_degraded_payload.py +0 -0
  204. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_capability_registry.py +0 -0
  205. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_capability_registry_cache_control.py +0 -0
  206. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_capability_tool_choice.py +0 -0
  207. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_claude_code_suitability.py +0 -0
  208. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_cli.py +0 -0
  209. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_cli_bind_warning.py +0 -0
  210. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_cli_stats.py +0 -0
  211. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_config.py +0 -0
  212. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_config_cwd_warning.py +0 -0
  213. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_config_shim_actions.py +0 -0
  214. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_context_budget.py +0 -0
  215. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_continuous_probe.py +0 -0
  216. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_credentials.py +0 -0
  217. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_dashboard_endpoint.py +0 -0
  218. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_doctor.py +0 -0
  219. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_doctor_apply.py +0 -0
  220. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_doctor_cache_probe.py +0 -0
  221. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_doctor_claude_code.py +0 -0
  222. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_drift_actions.py +0 -0
  223. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_drift_detection.py +0 -0
  224. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_drift_detection_integration.py +0 -0
  225. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_env_file.py +0 -0
  226. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_env_security.py +0 -0
  227. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_errors.py +0 -0
  228. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_examples_yaml.py +0 -0
  229. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_examples_yaml_roundtrip.py +0 -0
  230. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_fallback.py +0 -0
  231. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_fallback_anthropic.py +0 -0
  232. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_fallback_cache_control.py +0 -0
  233. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_fallback_cache_observed.py +0 -0
  234. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_fallback_cache_strip.py +0 -0
  235. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_fallback_empty_response.py +0 -0
  236. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_fallback_misconfig_warn.py +0 -0
  237. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_fallback_paid_gate.py +0 -0
  238. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_fallback_reason.py +0 -0
  239. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_fallback_thinking.py +0 -0
  240. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_fallback_tool_choice_emulate.py +0 -0
  241. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_fallback_tool_integrity.py +0 -0
  242. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_fix_h1_prometheus_drift.py +0 -0
  243. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_fix_h2_h6_translation.py +0 -0
  244. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_fix_h3_client_reuse.py +0 -0
  245. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_fix_h4_h5_guards.py +0 -0
  246. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_fix_h7_probe_restore.py +0 -0
  247. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_fix_h8_launcher_auth.py +0 -0
  248. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_fix_mA_routing.py +0 -0
  249. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_fix_mB_adapters.py +0 -0
  250. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_fix_mC_convert.py +0 -0
  251. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_fix_mD_logging_metrics.py +0 -0
  252. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_fix_mE_config_validation.py +0 -0
  253. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_fix_mF_ingress.py +0 -0
  254. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_fix_v213_launcher_hardening.py +0 -0
  255. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_gguf_introspect.py +0 -0
  256. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_guards_tool_loop.py +0 -0
  257. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_hardware.py +0 -0
  258. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_import_hygiene.py +0 -0
  259. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_ingress_anthropic.py +0 -0
  260. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_ingress_count_tokens.py +0 -0
  261. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_ingress_profile.py +0 -0
  262. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_language_tax.py +0 -0
  263. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_language_tax_integration.py +0 -0
  264. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_launcher_backend_variants.py +0 -0
  265. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_launcher_config_bench.py +0 -0
  266. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_launcher_devices.py +0 -0
  267. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_launcher_devices_detect.py +0 -0
  268. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_launcher_devices_routes.py +0 -0
  269. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_launcher_gui_devices.py +0 -0
  270. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_launcher_gui_events.py +0 -0
  271. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_launcher_gui_readiness.py +0 -0
  272. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_launcher_gui_sweep_close.py +0 -0
  273. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_launcher_mtp.py +0 -0
  274. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_launcher_mtp_fallback.py +0 -0
  275. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_launcher_provider_sync.py +0 -0
  276. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_launcher_readiness_restart.py +0 -0
  277. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_launcher_swap.py +0 -0
  278. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_launcher_swap_review.py +0 -0
  279. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_launcher_variant_config.py +0 -0
  280. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_launcher_variant_gui.py +0 -0
  281. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_launcher_variant_routes.py +0 -0
  282. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_launcher_variant_sweep.py +0 -0
  283. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_memory_budget.py +0 -0
  284. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_memory_pressure.py +0 -0
  285. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_metrics_cache.py +0 -0
  286. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_metrics_collector.py +0 -0
  287. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_metrics_cost.py +0 -0
  288. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_metrics_endpoint.py +0 -0
  289. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_metrics_jsonl.py +0 -0
  290. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_metrics_prometheus.py +0 -0
  291. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_metrics_prometheus_cache.py +0 -0
  292. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_models_passthrough.py +0 -0
  293. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_openai_compat.py +0 -0
  294. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_openrouter_roster_diff.py +0 -0
  295. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_output_filters.py +0 -0
  296. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_output_filters_adapters.py +0 -0
  297. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_packaging.py +0 -0
  298. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_partial_stitch.py +0 -0
  299. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_plugin_adapter.py +0 -0
  300. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_plugins_integration.py +0 -0
  301. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_plugins_loader.py +0 -0
  302. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_plugins_registry.py +0 -0
  303. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_reasoning_strip.py +0 -0
  304. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_repair_byte_fallback.py +0 -0
  305. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_request_log.py +0 -0
  306. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_role_normalization.py +0 -0
  307. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_rollback.py +0 -0
  308. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_routing_adaptive.py +0 -0
  309. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_secret_redaction.py +0 -0
  310. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_self_healing.py +0 -0
  311. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_setup_sh.py +0 -0
  312. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_slot_affinity.py +0 -0
  313. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_state_store.py +0 -0
  314. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_stop_reason_forward_compat.py +0 -0
  315. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_stream_truncation.py +0 -0
  316. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_token_estimation.py +0 -0
  317. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_token_estimation_accurate.py +0 -0
  318. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_tokens_saved_metric.py +0 -0
  319. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_tool_repair.py +0 -0
  320. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_tool_repair_differential.py +0 -0
  321. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_tool_repair_lenient.py +0 -0
  322. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_tool_repair_r4.py +0 -0
  323. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_tool_repair_scanners.py +0 -0
  324. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_tool_search.py +0 -0
  325. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_toolrepair_bench.py +0 -0
  326. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_translation_anthropic.py +0 -0
  327. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_translation_reverse.py +0 -0
  328. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_ttft_timeout.py +0 -0
  329. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_ui_auth.py +0 -0
  330. {coderouter_cli-2.18.0 → coderouter_cli-2.19.0}/tests/test_vscode_init.py +0 -0
@@ -9,6 +9,73 @@ are kept verbatim where the Japanese text itself is the subject).
9
9
 
10
10
  ---
11
11
 
12
+ ## [v2.19.0] — 2026-10-24 (OpenAI Responses API for the Codex CLI)
13
+
14
+ ### Added
15
+
16
+ - **`POST /v1/responses`** — the OpenAI Responses API, so the current Codex
17
+ CLI (Responses-only since 2026-02) can use CodeRouter as a custom
18
+ provider (`wire_api = "responses"`, `base_url = http://127.0.0.1:8088/v1`;
19
+ see `docs/start/quickstart.md` Pattern B). The request is translated to an
20
+ Anthropic Messages request and runs through the same fallback engine as
21
+ `/v1/messages`, so fallback, tool-call repair, the guards, the TTFT
22
+ cut-off and the chain-failure error mapping all apply; the result is
23
+ translated back (`coderouter/translation/responses.py`). Built against
24
+ the wire contract in openai/codex `970111f` (2026-10-23):
25
+ - `developer` / `system` messages (Codex sends its system prompt as the
26
+ first `developer` input item, not `instructions`) become Anthropic
27
+ `system` text; `instructions` is honoured for other clients.
28
+ - Tools: `function` → `function_call` with a JSON-string `arguments`;
29
+ `custom` grammar tools such as `apply_patch` → `custom_tool_call` with
30
+ the raw `input` string (Codex rejects a `function_call` for those; the
31
+ grammar is passed to the model in the tool description); `namespace`
32
+ (MCP) tools are flattened per request and answered with `namespace` +
33
+ the inner `name`. Hosted tools (`web_search`, …) are dropped.
34
+ - History: `function_call` / `custom_tool_call` and their outputs become
35
+ `tool_use` / `tool_result`; orphan outputs are dropped and calls with no
36
+ output get a synthetic `"aborted"` result so the Anthropic pairing rules
37
+ hold. `reasoning` and hosted-tool items are dropped.
38
+ - Stream: `response.created` → per item `output_item.added` (text deltas
39
+ only inside an open item) → `output_item.done` → `response.completed`
40
+ with `response.id` and complete usage details (`cached_tokens`,
41
+ `reasoning_tokens`). `max_tokens` stops become `response.incomplete`
42
+ (`max_output_tokens`).
43
+ - Errors: pre-content failures get an OpenAI-style error body with a real
44
+ status (400 / 429 with `Retry-After`, which Codex needs to retry a 429 /
45
+ 502). A context overflow on a streaming request — upstream overflow or
46
+ `context_budget_action: reject` — becomes `response.failed` with code
47
+ `context_length_exceeded`, the only overflow signal Codex recognizes. A
48
+ failure after the stream started is `response.failed` (`server_error`),
49
+ which Codex retries.
50
+ - Profile selection as on the other routes (body `profile` >
51
+ `X-CodeRouter-Profile` > `X-CodeRouter-Mode` > auto router > default);
52
+ Codex's `session-id` header feeds llama-server slot affinity.
53
+ - Non-streaming JSON responses are supported for other clients.
54
+ - Tool outputs that carry images (Codex `view_image`, MCP image results)
55
+ become image blocks, not base64 text. Usage reports OpenAI semantics —
56
+ `input_tokens` includes cache reads and writes — so Codex's
57
+ context-window accounting (and its auto-compaction) sees the real
58
+ prompt size. A stream that ends without `message_stop`, or with a block
59
+ still open, is reported as `response.failed` (retryable) rather than a
60
+ `response.completed` that would silently drop the partial item.
61
+ Flattened tool names are capped at 64 characters (hash suffix) for
62
+ strict OpenAI-compatible backends, and a custom-tool call whose
63
+ arguments hold a single string under another key still reaches
64
+ `apply_patch` as raw text.
65
+
66
+ ### Changed
67
+
68
+ - Docs: quickstart Pattern B (ja/en) now configures Codex through
69
+ CodeRouter; README and the "do I need CodeRouter?" guide updated.
70
+
71
+ ### Known limits
72
+
73
+ - Reasoning items are not produced or round-tripped; hosted tools are not
74
+ emulated; `previous_response_id` (server-side conversation state) is not
75
+ supported — Codex does not use it on HTTP.
76
+
77
+ ---
78
+
12
79
  ## [v2.18.0] — 2026-10-24 (route on Claude Code's own request hints)
13
80
 
14
81
  ### Added
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: coderouter-cli
3
- Version: 2.18.0
3
+ Version: 2.19.0
4
4
  Summary: Local-first, free-first, fallback-built-in LLM router. Claude Code / OpenAI compatible.
5
5
  Project-URL: Homepage, https://github.com/zephel01/CodeRouter
6
6
  Project-URL: Repository, https://github.com/zephel01/CodeRouter
@@ -66,7 +66,7 @@ Description-Content-Type: text/markdown
66
66
  ## 何ができるか — 30 秒で
67
67
 
68
68
  ```
69
- あなたのエージェント (Claude Code / agy ほか ※)
69
+ あなたのエージェント (Claude Code / codex / agy)
70
70
  │
71
71
  ▼
72
72
  ┌─ CodeRouter ─┐
@@ -76,8 +76,6 @@ Description-Content-Type: text/markdown
76
76
  └──────────────┘
77
77
  ```
78
78
 
79
- ※ 現行の codex CLI は Responses API(`/v1/responses`)専用になったため、CodeRouter 経由ではまだ使えません(対応予定)。直結の代替手順 → [quickstart Pattern B](./docs/start/quickstart.md#pattern-b-codex-cli-で使う)
80
-
81
79
  **やってくれること:**
82
80
 
83
81
  - ローカルモデルが壊した tool calling を Claude Code に届く前に修復する
@@ -147,7 +145,7 @@ ANTHROPIC_BASE_URL=http://localhost:8088 ANTHROPIC_AUTH_TOKEN=dummy claude
147
145
  | Claude Code + ローカル Ollama で tool calling が壊れる | **必須** — tool 修復 (+ 必要なら wire 変換) |
148
146
  | Claude Code + ローカルで長時間回すと止まる | **必須級** — 6 系統ガード + self-healing |
149
147
  | Ollama v0.14+ / LM Studio にネイティブ直結で動いてる | **便利** — 直結に無い fallback / ガード / 診断を追加 (passthrough で翻訳ゼロ) |
150
- | codex / agy + Ollama 直繋ぎで動いてる | オプション — フォールバックが欲しいなら(codex は `/v1/responses` 対応後) |
148
+ | codex / agy + Ollama 直繋ぎで動いてる | オプション — フォールバックが欲しいなら(codex は v2.19.0 の `/v1/responses` 経由) |
151
149
  | Claude API を直接叩いてて問題ない | 不要 |
152
150
 
153
151
  詳細は → [要否判定ガイド](./docs/start/when-do-i-need-coderouter.md)
@@ -21,7 +21,7 @@
21
21
  ## What it does — in 30 seconds
22
22
 
23
23
  ```
24
- Your agent (Claude Code / agy, etc. *)
24
+ Your agent (Claude Code / codex / agy)
25
25
  │
26
26
  ▼
27
27
  ┌─ CodeRouter ──┐
@@ -31,7 +31,6 @@ Your agent (Claude Code / agy, etc. *)
31
31
  └────────────────┘
32
32
  ```
33
33
 
34
- \* Current codex CLI speaks only the Responses API (`/v1/responses`), so it cannot go through CodeRouter yet (planned). Direct-connect workaround → [quickstart Pattern B](./docs/start/quickstart.en.md#pattern-b-use-it-with-the-codex-cli)
35
34
 
36
35
  **What it does for you:**
37
36
 
@@ -83,7 +82,7 @@ That's it. Claude Code works as usual, but your local Ollama is answering behind
83
82
  |---|---|
84
83
  | Claude Code + local Ollama, tool calling breaks | **Yes** — wire translation + tool repair |
85
84
  | Claude Code + local, dies after long sessions | **Helpful** — 6 guards + self-healing |
86
- | codex / agy + Ollama works fine | Optional — if you want fallback (codex: once `/v1/responses` lands) |
85
+ | codex / agy + Ollama works fine | Optional — if you want fallback (codex: via `/v1/responses`, v2.19.0+) |
87
86
  | Using Claude API directly, no issues | Not needed |
88
87
 
89
88
  Full decision matrix → [Do I need CodeRouter?](./docs/start/when-do-i-need-coderouter.en.md)
@@ -21,7 +21,7 @@
21
21
  ## 何ができるか — 30 秒で
22
22
 
23
23
  ```
24
- あなたのエージェント (Claude Code / agy ほか ※)
24
+ あなたのエージェント (Claude Code / codex / agy)
25
25
  │
26
26
  ▼
27
27
  ┌─ CodeRouter ─┐
@@ -31,8 +31,6 @@
31
31
  └──────────────┘
32
32
  ```
33
33
 
34
- ※ 現行の codex CLI は Responses API(`/v1/responses`)専用になったため、CodeRouter 経由ではまだ使えません(対応予定)。直結の代替手順 → [quickstart Pattern B](./docs/start/quickstart.md#pattern-b-codex-cli-で使う)
35
-
36
34
  **やってくれること:**
37
35
 
38
36
  - ローカルモデルが壊した tool calling を Claude Code に届く前に修復する
@@ -102,7 +100,7 @@ ANTHROPIC_BASE_URL=http://localhost:8088 ANTHROPIC_AUTH_TOKEN=dummy claude
102
100
  | Claude Code + ローカル Ollama で tool calling が壊れる | **必須** — tool 修復 (+ 必要なら wire 変換) |
103
101
  | Claude Code + ローカルで長時間回すと止まる | **必須級** — 6 系統ガード + self-healing |
104
102
  | Ollama v0.14+ / LM Studio にネイティブ直結で動いてる | **便利** — 直結に無い fallback / ガード / 診断を追加 (passthrough で翻訳ゼロ) |
105
- | codex / agy + Ollama 直繋ぎで動いてる | オプション — フォールバックが欲しいなら(codex は `/v1/responses` 対応後) |
103
+ | codex / agy + Ollama 直繋ぎで動いてる | オプション — フォールバックが欲しいなら(codex は v2.19.0 の `/v1/responses` 経由) |
106
104
  | Claude API を直接叩いてて問題ない | 不要 |
107
105
 
108
106
  詳細は → [要否判定ガイド](./docs/start/when-do-i-need-coderouter.md)
@@ -19,6 +19,7 @@ from coderouter.ingress.dashboard_routes import router as dashboard_router
19
19
  from coderouter.ingress.launcher_routes import router as launcher_router
20
20
  from coderouter.ingress.metrics_routes import router as metrics_router
21
21
  from coderouter.ingress.openai_routes import router as openai_router
22
+ from coderouter.ingress.responses_routes import router as responses_router
22
23
  from coderouter.logging import configure_logging, get_logger
23
24
  from coderouter.metrics import install_collector
24
25
  from coderouter.plugins import discover_and_load
@@ -491,6 +492,8 @@ def create_app(config_path: str | None = None) -> FastAPI:
491
492
 
492
493
  app.include_router(openai_router, prefix="/v1", tags=["openai-compat"])
493
494
  app.include_router(anthropic_router, prefix="/v1", tags=["anthropic-compat"])
495
+ # v2.19.0: OpenAI Responses API (Codex CLI).
496
+ app.include_router(responses_router, prefix="/v1", tags=["openai-responses"])
494
497
  # v1.5-A: /metrics.json sits at the root (no /v1 prefix) — metrics are not
495
498
  # part of the OpenAI / Anthropic API surface, and Prometheus-style
496
499
  # endpoints conventionally live at the root in v1.5-B.
@@ -0,0 +1,269 @@
1
+ """OpenAI Responses API route: ``POST /v1/responses`` (v2.19.0).
2
+
3
+ Lets the OpenAI Codex CLI (Responses-only since 2026-02) use CodeRouter as a
4
+ custom provider::
5
+
6
+ [model_providers.coderouter]
7
+ name = "CodeRouter"
8
+ base_url = "http://127.0.0.1:8088/v1"
9
+ wire_api = "responses"
10
+
11
+ The request is translated to an Anthropic Messages request
12
+ (:mod:`coderouter.translation.responses`) and run through the same fallback
13
+ engine as ``/v1/messages`` — tool-call repair, guards, fallback and the
14
+ v2.16.0 error mapping all apply. Profile selection mirrors the other
15
+ routes: body ``profile`` > ``X-CodeRouter-Profile`` > ``X-CodeRouter-Mode``
16
+ > auto router > default.
17
+
18
+ Failures are reported the way Codex reads them:
19
+
20
+ - before the response commits: an OpenAI-style error body with a real
21
+ HTTP status (400 non-retryable / 429 with ``Retry-After`` / 502);
22
+ - a context overflow on a streaming request: ``response.failed`` with code
23
+ ``context_length_exceeded`` — the only overflow signal Codex recognizes
24
+ (an HTTP 400 is treated as a plain invalid request);
25
+ - after the stream started: ``response.failed`` (``server_error``), then end
26
+ of stream, which Codex retries.
27
+ """
28
+
29
+ from __future__ import annotations
30
+
31
+ import asyncio
32
+ import contextlib
33
+ import json
34
+ from collections.abc import AsyncIterator
35
+
36
+ from fastapi import APIRouter, Header, Request
37
+ from fastapi.responses import JSONResponse, Response, StreamingResponse
38
+
39
+ from coderouter.adapters.slot_affinity import affinity_key
40
+ from coderouter.guards.context_budget import ContextBudgetRejectError
41
+ from coderouter.guards.tool_loop import ToolCountExceededError, ToolLoopBreakError
42
+ from coderouter.ingress.anthropic_errors import (
43
+ PROMPT_TOO_LONG_PREFIX,
44
+ AnthropicErrorResponse,
45
+ map_no_providers_error,
46
+ )
47
+ from coderouter.ingress.anthropic_routes import (
48
+ _DisconnectWatcher,
49
+ _resolve_stream_timeout_s,
50
+ )
51
+ from coderouter.logging import get_logger
52
+ from coderouter.routing import FallbackEngine, MidStreamError, NoProvidersAvailableError
53
+ from coderouter.routing.auto_router import (
54
+ RESERVED_PROFILE_NAME,
55
+ classify,
56
+ extract_gateway_hints,
57
+ )
58
+ from coderouter.translation import AnthropicStreamEvent
59
+ from coderouter.translation.responses import (
60
+ ResponsesStreamTranslator,
61
+ anthropic_response_to_responses,
62
+ format_sse,
63
+ responses_to_anthropic,
64
+ )
65
+
66
+ router = APIRouter()
67
+ logger = get_logger(__name__)
68
+
69
+ _PROFILE_HEADER = "x-coderouter-profile"
70
+ _MODE_HEADER = "x-coderouter-mode"
71
+
72
+ _OPENAI_TYPE = {
73
+ "invalid_request_error": "invalid_request_error",
74
+ "request_too_large": "invalid_request_error",
75
+ "rate_limit_error": "rate_limit_error",
76
+ "timeout_error": "server_error",
77
+ "api_error": "server_error",
78
+ }
79
+
80
+
81
+ def _openai_error(
82
+ status: int,
83
+ message: str,
84
+ *,
85
+ etype: str,
86
+ code: str | None = None,
87
+ headers: dict[str, str] | None = None,
88
+ ) -> JSONResponse:
89
+ return JSONResponse(
90
+ status_code=status,
91
+ content={"error": {"message": message, "type": etype, "param": None, "code": code}},
92
+ headers=headers or None,
93
+ )
94
+
95
+
96
+ def _is_overflow(mapped: AnthropicErrorResponse) -> bool:
97
+ return mapped.status_code == 400 and mapped.message.lower().startswith(PROMPT_TOO_LONG_PREFIX)
98
+
99
+
100
+ def _mapped_to_http(mapped: AnthropicErrorResponse) -> JSONResponse:
101
+ code = None
102
+ if _is_overflow(mapped):
103
+ code = "context_length_exceeded"
104
+ elif mapped.status_code == 429:
105
+ code = "rate_limit_exceeded"
106
+ return _openai_error(
107
+ mapped.status_code,
108
+ mapped.message,
109
+ etype=_OPENAI_TYPE.get(mapped.error_type, "server_error"),
110
+ code=code,
111
+ headers=dict(mapped.headers),
112
+ )
113
+
114
+
115
+ def _failed_stream(translator: ResponsesStreamTranslator, code: str, message: str) -> StreamingResponse:
116
+ async def gen() -> AsyncIterator[str]:
117
+ for ev in translator.start():
118
+ yield format_sse(ev)
119
+ for ev in translator.failed(code, message):
120
+ yield format_sse(ev)
121
+
122
+ return StreamingResponse(gen(), media_type="text/event-stream", headers={"Cache-Control": "no-cache"})
123
+
124
+
125
+ @router.post("/responses", response_model=None)
126
+ async def responses(
127
+ request: Request,
128
+ x_coderouter_profile: str | None = Header(default=None, alias=_PROFILE_HEADER),
129
+ x_coderouter_mode: str | None = Header(default=None, alias=_MODE_HEADER),
130
+ ) -> Response:
131
+ """OpenAI Responses API endpoint (streaming and non-streaming)."""
132
+ engine: FallbackEngine = request.app.state.engine
133
+ config = request.app.state.config
134
+
135
+ try:
136
+ body = await request.json()
137
+ except (json.JSONDecodeError, ValueError):
138
+ return _openai_error(400, "request body must be JSON", etype="invalid_request_error")
139
+ if not isinstance(body, dict):
140
+ return _openai_error(400, "request body must be a JSON object", etype="invalid_request_error")
141
+
142
+ try:
143
+ anth_req, tool_map = responses_to_anthropic(body)
144
+ except Exception as exc: # pydantic ValidationError and shape errors
145
+ return _openai_error(400, f"could not translate request: {exc}", etype="invalid_request_error")
146
+
147
+ model = body.get("model") if isinstance(body.get("model"), str) else "coderouter"
148
+
149
+ # Conversation key for llama-server slot affinity: Claude-style hint
150
+ # headers when present, else Codex's own ``session-id`` header.
151
+ hints = extract_gateway_hints(request.headers)
152
+ anth_req.session_key = affinity_key(hints) or request.headers.get("session-id") or None
153
+
154
+ if anth_req.profile is None and x_coderouter_profile:
155
+ anth_req.profile = x_coderouter_profile
156
+ if anth_req.profile is None and x_coderouter_mode:
157
+ try:
158
+ anth_req.profile = config.resolve_mode(x_coderouter_mode)
159
+ except KeyError:
160
+ return _openai_error(
161
+ 400, f"unknown mode {x_coderouter_mode!r}", etype="invalid_request_error"
162
+ )
163
+ if anth_req.profile is None and config.default_profile == RESERVED_PROFILE_NAME:
164
+ anth_req.profile = classify(anth_req.model_dump(), config, hints)
165
+ if anth_req.profile is not None:
166
+ try:
167
+ config.profile_by_name(anth_req.profile)
168
+ except KeyError:
169
+ return _openai_error(
170
+ 400, f"unknown profile {anth_req.profile!r}", etype="invalid_request_error"
171
+ )
172
+
173
+ translator = ResponsesStreamTranslator(tool_map, model=model)
174
+
175
+ try:
176
+ anth_req, _ctx = engine.apply_context_budget(anth_req)
177
+ except ContextBudgetRejectError as exc:
178
+ if anth_req.stream:
179
+ return _failed_stream(translator, "context_length_exceeded", str(exc))
180
+ return _openai_error(400, str(exc), etype="invalid_request_error", code="context_length_exceeded")
181
+
182
+ if not anth_req.stream:
183
+ try:
184
+ resp = await engine.generate_anthropic(anth_req)
185
+ except NoProvidersAvailableError as exc:
186
+ return _mapped_to_http(map_no_providers_error(exc))
187
+ except ContextBudgetRejectError as exc:
188
+ return _openai_error(400, str(exc), etype="invalid_request_error", code="context_length_exceeded")
189
+ except (ToolLoopBreakError, ToolCountExceededError) as exc:
190
+ return _openai_error(400, str(exc), etype="invalid_request_error")
191
+ return JSONResponse(
192
+ anthropic_response_to_responses(resp.model_dump(exclude_none=True), tool_map, model=model)
193
+ )
194
+
195
+ # Streaming: pull the first engine event before committing, like
196
+ # /v1/messages (v2.16.0), so pre-content failures get a real status.
197
+ timeout_s = _resolve_stream_timeout_s(engine, anth_req.profile)
198
+ deadline = asyncio.get_running_loop().time() + timeout_s
199
+ source = engine.stream_anthropic(anth_req)
200
+ first: AnthropicStreamEvent | None = None
201
+ watcher = _DisconnectWatcher(request)
202
+ watcher.start()
203
+
204
+ async def _close() -> None:
205
+ with contextlib.suppress(Exception):
206
+ await source.aclose() # type: ignore[attr-defined]
207
+
208
+ try:
209
+ async with asyncio.timeout_at(deadline) as scope:
210
+ first = await anext(source)
211
+ except StopAsyncIteration:
212
+ first = None
213
+ except NoProvidersAvailableError as exc:
214
+ await _close()
215
+ mapped = map_no_providers_error(exc)
216
+ if _is_overflow(mapped):
217
+ return _failed_stream(translator, "context_length_exceeded", mapped.message)
218
+ return _mapped_to_http(mapped)
219
+ except ContextBudgetRejectError as exc:
220
+ await _close()
221
+ return _failed_stream(translator, "context_length_exceeded", str(exc))
222
+ except (ToolLoopBreakError, ToolCountExceededError) as exc:
223
+ await _close()
224
+ return _openai_error(400, str(exc), etype="invalid_request_error")
225
+ except MidStreamError as exc:
226
+ await _close()
227
+ return _failed_stream(translator, "server_error", str(exc))
228
+ except TimeoutError:
229
+ await _close()
230
+ if not scope.expired():
231
+ raise
232
+ return _openai_error(504, f"no upstream event within {timeout_s:.0f}s", etype="server_error")
233
+ except asyncio.CancelledError:
234
+ await _close()
235
+ if watcher.fired:
236
+ watcher.uncancel()
237
+ return Response(status_code=499)
238
+ raise
239
+ except BaseException:
240
+ await _close()
241
+ raise
242
+ finally:
243
+ await watcher.stop()
244
+
245
+ async def gen() -> AsyncIterator[str]:
246
+ try:
247
+ async with asyncio.timeout_at(deadline):
248
+ for ev in translator.start():
249
+ yield format_sse(ev)
250
+ if first is not None:
251
+ for out in translator.feed(first):
252
+ yield format_sse(out)
253
+ async for ev in source:
254
+ for out in translator.feed(ev):
255
+ yield format_sse(out)
256
+ for out in translator.finish():
257
+ yield format_sse(out)
258
+ except TimeoutError:
259
+ logger.warning("responses-stream-timeout", extra={"timeout_s": timeout_s})
260
+ for out in translator.failed("server_error", f"stream exceeded {timeout_s:.0f}s ceiling"):
261
+ yield format_sse(out)
262
+ except (MidStreamError, NoProvidersAvailableError) as exc:
263
+ logger.warning("responses-stream-failed", extra={"error": str(exc)[:300]})
264
+ for out in translator.failed("server_error", str(exc)):
265
+ yield format_sse(out)
266
+ finally:
267
+ await _close()
268
+
269
+ return StreamingResponse(gen(), media_type="text/event-stream", headers={"Cache-Control": "no-cache"})