coderouter-cli 2.8.0__tar.gz → 2.8.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (266) hide show
  1. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/CHANGELOG.md +29 -0
  2. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/PKG-INFO +1 -1
  3. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/adapters/registry.py +42 -0
  4. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/guides/language-tax.en.md +1 -1
  5. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/guides/language-tax.md +1 -1
  6. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/pyproject.toml +1 -1
  7. coderouter_cli-2.8.1/tests/test_agent_cli.py +81 -0
  8. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_plugin_adapter.py +54 -9
  9. coderouter_cli-2.8.0/tests/test_agent_cli.py +0 -1507
  10. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/.gitignore +0 -0
  11. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/LICENSE +0 -0
  12. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/README.en.md +0 -0
  13. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/README.md +0 -0
  14. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/__init__.py +0 -0
  15. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/__main__.py +0 -0
  16. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/adapters/__init__.py +0 -0
  17. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/adapters/agent_cli.py +0 -0
  18. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/adapters/anthropic_native.py +0 -0
  19. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/adapters/base.py +0 -0
  20. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/adapters/openai_compat.py +0 -0
  21. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/cli.py +0 -0
  22. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/cli_stats.py +0 -0
  23. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/config/__init__.py +0 -0
  24. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/config/capability_registry.py +0 -0
  25. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/config/env_file.py +0 -0
  26. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/config/loader.py +0 -0
  27. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/config/schemas.py +0 -0
  28. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/cost.py +0 -0
  29. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/data/__init__.py +0 -0
  30. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/data/model-capabilities.yaml +0 -0
  31. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/doctor.py +0 -0
  32. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/doctor_apply.py +0 -0
  33. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/env_security.py +0 -0
  34. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/errors.py +0 -0
  35. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/gguf_introspect.py +0 -0
  36. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/guards/__init__.py +0 -0
  37. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/guards/_fingerprint.py +0 -0
  38. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/guards/backend_health.py +0 -0
  39. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/guards/context_budget.py +0 -0
  40. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/guards/continuous_probe.py +0 -0
  41. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/guards/drift_actions.py +0 -0
  42. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/guards/drift_detection.py +0 -0
  43. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/guards/memory_budget.py +0 -0
  44. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/guards/memory_pressure.py +0 -0
  45. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/guards/self_healing.py +0 -0
  46. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/guards/tool_loop.py +0 -0
  47. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/hardware.py +0 -0
  48. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/ingress/__init__.py +0 -0
  49. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/ingress/anthropic_routes.py +0 -0
  50. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/ingress/app.py +0 -0
  51. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/ingress/dashboard_routes.py +0 -0
  52. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/ingress/launcher_routes.py +0 -0
  53. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/ingress/metrics_routes.py +0 -0
  54. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/ingress/openai_routes.py +0 -0
  55. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/language_tax.py +0 -0
  56. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/launcher_speculative.py +0 -0
  57. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/logging.py +0 -0
  58. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/metrics/__init__.py +0 -0
  59. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/metrics/collector.py +0 -0
  60. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/metrics/prometheus.py +0 -0
  61. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/output_filters.py +0 -0
  62. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/plugins/__init__.py +0 -0
  63. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/plugins/base.py +0 -0
  64. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/plugins/loader.py +0 -0
  65. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/plugins/registry.py +0 -0
  66. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/routing/__init__.py +0 -0
  67. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/routing/adaptive.py +0 -0
  68. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/routing/auto_router.py +0 -0
  69. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/routing/budget.py +0 -0
  70. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/routing/capability.py +0 -0
  71. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/routing/fallback.py +0 -0
  72. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/state/__init__.py +0 -0
  73. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/state/audit_log.py +0 -0
  74. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/state/replay.py +0 -0
  75. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/state/request_log.py +0 -0
  76. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/state/store.py +0 -0
  77. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/state/suggest_rules.py +0 -0
  78. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/token_estimation.py +0 -0
  79. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/token_estimation_accurate.py +0 -0
  80. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/translation/__init__.py +0 -0
  81. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/translation/anthropic.py +0 -0
  82. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/translation/convert.py +0 -0
  83. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/translation/tool_repair.py +0 -0
  84. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/README.en.md +0 -0
  85. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/README.md +0 -0
  86. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/assets/dashboard-demo.png +0 -0
  87. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/backends/claude-code-llamacpp-vllm.en.md +0 -0
  88. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/backends/claude-code-llamacpp-vllm.md +0 -0
  89. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/backends/external-agents.en.md +0 -0
  90. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/backends/external-agents.md +0 -0
  91. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/backends/gguf_dl.en.md +0 -0
  92. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/backends/gguf_dl.md +0 -0
  93. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/backends/hf-ollama-models.en.md +0 -0
  94. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/backends/hf-ollama-models.md +0 -0
  95. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/backends/install-backends.en.md +0 -0
  96. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/backends/install-backends.md +0 -0
  97. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/backends/launcher-quickstart.en.md +0 -0
  98. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/backends/launcher-quickstart.md +0 -0
  99. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/backends/launcher.en.md +0 -0
  100. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/backends/launcher.md +0 -0
  101. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/backends/llamacpp-direct.en.md +0 -0
  102. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/backends/llamacpp-direct.md +0 -0
  103. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/backends/lmstudio-direct.en.md +0 -0
  104. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/backends/lmstudio-direct.md +0 -0
  105. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/backends/verify-ollama-0.23.1.md +0 -0
  106. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/concepts/architecture.en.md +0 -0
  107. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/concepts/architecture.md +0 -0
  108. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/concepts/context-budget.en.md +0 -0
  109. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/concepts/context-budget.md +0 -0
  110. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/concepts/continuous-probing.en.md +0 -0
  111. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/concepts/continuous-probing.md +0 -0
  112. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/concepts/drift-detection.en.md +0 -0
  113. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/concepts/drift-detection.md +0 -0
  114. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/concepts/partial-stitch.en.md +0 -0
  115. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/concepts/partial-stitch.md +0 -0
  116. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/designs/agent-cli-plugin-extraction.md +0 -0
  117. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/designs/external-agents-adapter.md +0 -0
  118. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/designs/orchestration-companion.md +0 -0
  119. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/designs/v1.5-dashboard-mockup.html +0 -0
  120. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/designs/v1.6-auto-router-verification.md +0 -0
  121. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/designs/v1.6-auto-router.md +0 -0
  122. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/guides/free-tier-guide.en.md +0 -0
  123. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/guides/free-tier-guide.md +0 -0
  124. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/guides/remote-access.en.md +0 -0
  125. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/guides/remote-access.md +0 -0
  126. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/guides/security.en.md +0 -0
  127. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/guides/security.md +0 -0
  128. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/guides/troubleshooting.en.md +0 -0
  129. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/guides/troubleshooting.md +0 -0
  130. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/guides/usage-guide.en.md +0 -0
  131. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/guides/usage-guide.md +0 -0
  132. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/low-memory-integration.en.md +0 -0
  133. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/low-memory-integration.md +0 -0
  134. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/openrouter-roster/CHANGES.md +0 -0
  135. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/openrouter-roster/README.md +0 -0
  136. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/openrouter-roster/latest.json +0 -0
  137. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/retrospectives/v0.4.md +0 -0
  138. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/retrospectives/v0.5-verify.md +0 -0
  139. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/retrospectives/v0.5.md +0 -0
  140. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/retrospectives/v0.6.md +0 -0
  141. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/retrospectives/v0.7.md +0 -0
  142. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/retrospectives/v1.0-verify.md +0 -0
  143. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/retrospectives/v1.0.md +0 -0
  144. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/start/quickstart.en.md +0 -0
  145. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/start/quickstart.md +0 -0
  146. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/start/when-do-i-need-coderouter.en.md +0 -0
  147. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/start/when-do-i-need-coderouter.md +0 -0
  148. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/examples/.env.example +0 -0
  149. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/examples/README.md +0 -0
  150. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/examples/providers-agent-cli.yaml +0 -0
  151. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/examples/providers-multiagent.yaml +0 -0
  152. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/examples/providers.context-budget-test.yaml +0 -0
  153. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/examples/providers.llamacpp-vllm.yaml +0 -0
  154. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/examples/providers.nvidia-nim.yaml +0 -0
  155. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/examples/providers.ollama-auto-custom.yaml +0 -0
  156. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/examples/providers.ollama-auto.yaml +0 -0
  157. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/examples/providers.ollama-free-chain.yaml +0 -0
  158. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/examples/providers.raspberrypi.yaml +0 -0
  159. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/examples/providers.yaml +0 -0
  160. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/scripts/demo_traffic.sh +0 -0
  161. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/scripts/openrouter_roster_diff.py +0 -0
  162. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/scripts/smoke_v2_2.sh +0 -0
  163. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/scripts/verify-providers.yaml +0 -0
  164. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/scripts/verify_ollama_0_23.py +0 -0
  165. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/scripts/verify_v0_5.sh +0 -0
  166. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/scripts/verify_v1_0.sh +0 -0
  167. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/__init__.py +0 -0
  168. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/conftest.py +0 -0
  169. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_adapter_anthropic.py +0 -0
  170. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_audit_log.py +0 -0
  171. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_auto_router.py +0 -0
  172. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_auto_router_cjk.py +0 -0
  173. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_backend_health.py +0 -0
  174. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_budget.py +0 -0
  175. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_capability.py +0 -0
  176. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_capability_degraded_payload.py +0 -0
  177. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_capability_registry.py +0 -0
  178. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_capability_registry_cache_control.py +0 -0
  179. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_capability_tool_choice.py +0 -0
  180. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_claude_code_suitability.py +0 -0
  181. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_cli.py +0 -0
  182. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_cli_bind_warning.py +0 -0
  183. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_cli_stats.py +0 -0
  184. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_config.py +0 -0
  185. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_config_shim_actions.py +0 -0
  186. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_context_budget.py +0 -0
  187. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_continuous_probe.py +0 -0
  188. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_dashboard_endpoint.py +0 -0
  189. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_doctor.py +0 -0
  190. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_doctor_apply.py +0 -0
  191. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_doctor_cache_probe.py +0 -0
  192. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_drift_actions.py +0 -0
  193. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_drift_detection.py +0 -0
  194. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_drift_detection_integration.py +0 -0
  195. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_env_file.py +0 -0
  196. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_env_security.py +0 -0
  197. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_errors.py +0 -0
  198. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_examples_yaml.py +0 -0
  199. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_fallback.py +0 -0
  200. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_fallback_anthropic.py +0 -0
  201. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_fallback_cache_control.py +0 -0
  202. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_fallback_cache_observed.py +0 -0
  203. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_fallback_cache_strip.py +0 -0
  204. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_fallback_empty_response.py +0 -0
  205. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_fallback_misconfig_warn.py +0 -0
  206. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_fallback_paid_gate.py +0 -0
  207. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_fallback_thinking.py +0 -0
  208. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_fallback_tool_choice_emulate.py +0 -0
  209. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_fix_h1_prometheus_drift.py +0 -0
  210. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_fix_h2_h6_translation.py +0 -0
  211. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_fix_h3_client_reuse.py +0 -0
  212. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_fix_h4_h5_guards.py +0 -0
  213. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_fix_h7_probe_restore.py +0 -0
  214. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_fix_h8_launcher_auth.py +0 -0
  215. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_fix_mA_routing.py +0 -0
  216. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_fix_mB_adapters.py +0 -0
  217. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_fix_mC_convert.py +0 -0
  218. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_fix_mD_logging_metrics.py +0 -0
  219. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_fix_mE_config_validation.py +0 -0
  220. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_fix_mF_ingress.py +0 -0
  221. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_gguf_introspect.py +0 -0
  222. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_guards_tool_loop.py +0 -0
  223. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_hardware.py +0 -0
  224. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_ingress_anthropic.py +0 -0
  225. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_ingress_count_tokens.py +0 -0
  226. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_ingress_profile.py +0 -0
  227. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_language_tax.py +0 -0
  228. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_language_tax_integration.py +0 -0
  229. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_launcher_mtp.py +0 -0
  230. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_launcher_mtp_fallback.py +0 -0
  231. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_launcher_provider_sync.py +0 -0
  232. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_memory_budget.py +0 -0
  233. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_memory_pressure.py +0 -0
  234. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_metrics_cache.py +0 -0
  235. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_metrics_collector.py +0 -0
  236. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_metrics_cost.py +0 -0
  237. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_metrics_endpoint.py +0 -0
  238. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_metrics_jsonl.py +0 -0
  239. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_metrics_prometheus.py +0 -0
  240. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_metrics_prometheus_cache.py +0 -0
  241. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_models_passthrough.py +0 -0
  242. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_openai_compat.py +0 -0
  243. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_openrouter_roster_diff.py +0 -0
  244. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_output_filters.py +0 -0
  245. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_output_filters_adapters.py +0 -0
  246. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_partial_stitch.py +0 -0
  247. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_plugins_integration.py +0 -0
  248. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_plugins_loader.py +0 -0
  249. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_plugins_registry.py +0 -0
  250. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_reasoning_strip.py +0 -0
  251. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_repair_byte_fallback.py +0 -0
  252. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_request_log.py +0 -0
  253. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_role_normalization.py +0 -0
  254. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_routing_adaptive.py +0 -0
  255. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_self_healing.py +0 -0
  256. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_setup_sh.py +0 -0
  257. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_state_store.py +0 -0
  258. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_token_estimation.py +0 -0
  259. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_token_estimation_accurate.py +0 -0
  260. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_tokens_saved_metric.py +0 -0
  261. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_tool_repair.py +0 -0
  262. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_tool_repair_lenient.py +0 -0
  263. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_tool_repair_r4.py +0 -0
  264. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_toolrepair_bench.py +0 -0
  265. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_translation_anthropic.py +0 -0
  266. {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_translation_reverse.py +0 -0
@@ -9,6 +9,35 @@ are kept verbatim where the Japanese text itself is the subject).
9
9
 
10
10
  ---
11
11
 
12
+ ## [v2.8.1] — 2026-07-11 (agent_cli moved to coderouter-plugin-agents — Phase 2b)
13
+
14
+ Phase 2b of the agent_cli plugin extraction
15
+ (`docs/designs/agent-cli-plugin-extraction.md` §4/§5/§7): the adapter body
16
+ and its behavior tests now live in the new external package
17
+ **`coderouter-plugin-agents`** (0.1.0, entry point `coderouter.adapter` →
18
+ `agents`, pins `coderouter-cli>=2.8,<3.0`). Core still bundles the in-core
19
+ `agent_cli` adapter unchanged during the transition — providers.yaml needs
20
+ no edits yet — and the in-core copy keeps winning resolution until Phase 2c
21
+ removes it.
22
+
23
+ ### Added
24
+
25
+ - **`agent-cli-in-core-deprecated` warning** (`adapters/registry.py`) —
26
+ fires once per process when the in-core `agent_cli` branch serves a
27
+ request while the plugin is also installed and enabled, signalling that
28
+ the plugin path takes over at Phase 2c.
29
+
30
+ ### Changed
31
+
32
+ - **`tests/test_agent_cli.py` slimmed 91 → 9** — the 82 adapter-behavior
33
+ tests (argv snapshots, parsers, env isolation, prompt-delivery
34
+ lifecycles, E2E, gemini rejection) moved verbatim to the plugin repo per
35
+ the design's §4.5 split map; the 9 retained tests cover the
36
+ `ProviderConfig`/`AgentCliConfig` pydantic validation that stays in Core
37
+ under §4.4 案(b) (AgentCliConfig remains a stable Core contract).
38
+ - `tests/test_plugin_adapter.py` +1 (deprecation-log semantics: in-core
39
+ still serves by identity, warning fires exactly once).
40
+
12
41
  ## [v2.8.0] — 2026-07-11 (Plugin SDK: Adapter hook wired — Phase 2a of the agent_cli extraction)
13
42
 
14
43
  Opens the Plugin SDK's Adapter surface: the previously dead-end `Adapter`
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: coderouter-cli
3
- Version: 2.8.0
3
+ Version: 2.8.1
4
4
  Summary: Local-first, free-first, fallback-built-in LLM router. Claude Code / OpenAI compatible.
5
5
  Project-URL: Homepage, https://github.com/zephel01/CodeRouter
6
6
  Project-URL: Repository, https://github.com/zephel01/CodeRouter
@@ -8,15 +8,23 @@ from coderouter.adapters.anthropic_native import AnthropicAdapter
8
8
  from coderouter.adapters.base import BaseAdapter
9
9
  from coderouter.adapters.openai_compat import OpenAICompatAdapter
10
10
  from coderouter.config.schemas import ProviderConfig
11
+ from coderouter.logging import get_logger
11
12
 
12
13
  if TYPE_CHECKING:
13
14
  from coderouter.plugins.registry import PluginRegistry
14
15
 
16
+ logger = get_logger(__name__)
17
+
15
18
  # in-core kinds, in resolution order. Kept as a tuple (not derived from
16
19
  # the if-chain below) so the "Unknown adapter kind" error message and
17
20
  # the plugin-shadow guard have a single source of truth.
18
21
  _IN_CORE_KINDS: tuple[str, ...] = ("openai_compat", "anthropic", "agent_cli")
19
22
 
23
+ # Module-level flag so the Phase 2b in-core agent_cli deprecation warning
24
+ # (docs/designs/agent-cli-plugin-extraction.md §5.1) fires at most once per
25
+ # process, regardless of how many agent_cli providers are built.
26
+ _agent_cli_deprecation_logged = False
27
+
20
28
 
21
29
  def _plugin_kinds(plugin_registry: PluginRegistry | None) -> list[str]:
22
30
  """``kind`` values served by enabled adapter plugins, for error text."""
@@ -25,6 +33,36 @@ def _plugin_kinds(plugin_registry: PluginRegistry | None) -> list[str]:
25
33
  return [factory.kind for factory in plugin_registry.adapters]
26
34
 
27
35
 
36
+ def _warn_agent_cli_in_core_deprecated_once() -> None:
37
+ """Log ``agent-cli-in-core-deprecated`` once per process (§5.1).
38
+
39
+ Only called when the in-core ``agent_cli`` branch is taken AND an
40
+ adapter plugin has also registered a ``kind="agent_cli"`` factory —
41
+ i.e. the operator already has ``coderouter-plugin-agents`` installed
42
+ and enabled, but Core's in-core copy still wins resolution order
43
+ (§3.2) during the Phase 2b migration window. Nudges them toward the
44
+ plugin path ahead of its Phase 2c removal from Core.
45
+ """
46
+ global _agent_cli_deprecation_logged
47
+ if _agent_cli_deprecation_logged:
48
+ return
49
+ _agent_cli_deprecation_logged = True
50
+ logger.warning(
51
+ "agent-cli-in-core-deprecated",
52
+ extra={
53
+ "hint": (
54
+ "an 'agent_cli' adapter plugin is installed and enabled, "
55
+ "but Core's in-core agent_cli implementation still served "
56
+ "this request (in-core wins resolution during the Phase 2b "
57
+ "migration window). The in-core copy will be removed in "
58
+ "Phase 2c — no action is required yet, but new setups "
59
+ "should already be relying on the plugin path "
60
+ "(coderouter-plugin-agents)."
61
+ ),
62
+ },
63
+ )
64
+
65
+
28
66
  def build_adapter(
29
67
  provider: ProviderConfig,
30
68
  plugin_registry: PluginRegistry | None = None,
@@ -46,6 +84,10 @@ def build_adapter(
46
84
  # os plumbing) is only pulled in when a config actually uses it.
47
85
  from coderouter.adapters.agent_cli import AgentCliAdapter
48
86
 
87
+ if plugin_registry is not None and any(
88
+ factory.kind == "agent_cli" for factory in plugin_registry.adapters
89
+ ):
90
+ _warn_agent_cli_in_core_deprecated_once()
49
91
  return AgentCliAdapter(provider)
50
92
  if plugin_registry is not None:
51
93
  for factory in plugin_registry.adapters:
@@ -31,7 +31,7 @@ Two distinct axes:
31
31
 
32
32
  ## 2. Measured data
33
33
 
34
- Measured with real production tokenizers (reproduce: `_OUTPUTS/CodeRouter-language-tax/measure/`).
34
+ Measured with real production tokenizers (reproduce: `_OUTPUTS/01-機能実装/language-tax/measure/`).
35
35
 
36
36
  ### Economic tax — same meaning, JA vs EN (avg of 5 translation pairs)
37
37
 
@@ -31,7 +31,7 @@ English version: [`language-tax.en.md`](./language-tax.en.md)
31
31
 
32
32
  ## 2. 実測データ
33
33
 
34
- 実在の本番トークナイザで計測した結果です(再現スクリプト: `_OUTPUTS/CodeRouter-language-tax/measure/`)。
34
+ 実在の本番トークナイザで計測した結果です(再現スクリプト: `_OUTPUTS/01-機能実装/language-tax/measure/`)。
35
35
 
36
36
  ### 経済的な税 — 同じ意味で JA vs EN(対訳5ペアの平均)
37
37
 
@@ -11,7 +11,7 @@
11
11
  # in plan.md §11.B; once granted, this name will become an alias and
12
12
  # `coderouter` will become the canonical distribution name.
13
13
  name = "coderouter-cli"
14
- version = "2.8.0"
14
+ version = "2.8.1"
15
15
  description = "Local-first, free-first, fallback-built-in LLM router. Claude Code / OpenAI compatible."
16
16
  readme = "README.md"
17
17
  requires-python = ">=3.12"
@@ -0,0 +1,81 @@
1
+ """Config-schema validation tests for ``kind="agent_cli"`` providers.
2
+
3
+ Phase 2b of the agent_cli plugin extraction
4
+ (``docs/designs/agent-cli-plugin-extraction.md`` §4.4 案(b), §4.5, §7)
5
+ moved the adapter-behavior tests (argv construction, output parsing,
6
+ subprocess stubbing, env isolation, timeouts, recursion limits, and the
7
+ TestClient E2E flows — ~82 of the original 91 tests) to the
8
+ ``coderouter-plugin-agents`` plugin package, alongside the
9
+ ``AgentCliAdapter`` implementation itself
10
+ (``coderouter/adapters/agent_cli.py``, kept in-core only as a
11
+ backward-compatible copy through Phase 2c — see
12
+ ``coderouter/adapters/registry.py``'s ``agent-cli-in-core-deprecated``
13
+ log).
14
+
15
+ What stays in Core, and stays here, is the schema contract: ``kind:
16
+ agent_cli`` and the ``agent_cli:`` sub-config (``AgentCliConfig``) are
17
+ recognized by ``ProviderConfig`` regardless of whether the adapter
18
+ plugin is installed, because Core owns config validation (fail-fast at
19
+ config-load time, ``extra="forbid"``). These 9 tests are that contract's
20
+ regression guard.
21
+ """
22
+
23
+ from __future__ import annotations
24
+
25
+ import pytest
26
+ from pydantic import ValidationError
27
+
28
+ from coderouter.config.schemas import AgentCliConfig, ProviderConfig
29
+
30
+
31
+ def test_schema_agent_cli_required_for_kind() -> None:
32
+ with pytest.raises(ValidationError, match="agent_cli sub-config is required"):
33
+ ProviderConfig(name="x", kind="agent_cli", model="opus")
34
+
35
+
36
+ def test_schema_base_url_optional_for_agent_cli() -> None:
37
+ p = ProviderConfig(
38
+ name="x",
39
+ kind="agent_cli",
40
+ model="opus",
41
+ agent_cli=AgentCliConfig(agent="claude"),
42
+ )
43
+ assert p.base_url is None
44
+
45
+
46
+ def test_schema_base_url_required_for_openai_compat() -> None:
47
+ with pytest.raises(ValidationError, match="base_url is required"):
48
+ ProviderConfig(name="x", kind="openai_compat", model="m")
49
+
50
+
51
+ def test_schema_command_defaults_to_agent() -> None:
52
+ cfg = AgentCliConfig(agent="claude")
53
+ assert cfg.command == "claude"
54
+
55
+
56
+ def test_schema_command_defaults_to_agy_for_antigravity() -> None:
57
+ # antigravity is the one agent whose binary name differs from the
58
+ # ``agent`` value (product "Antigravity CLI", command "agy").
59
+ cfg = AgentCliConfig(agent="antigravity")
60
+ assert cfg.command == "agy"
61
+
62
+
63
+ def test_schema_command_still_defaults_to_agent_for_others() -> None:
64
+ for agent in ("claude", "codex", "grok"):
65
+ cfg = AgentCliConfig(agent=agent) # type: ignore[arg-type]
66
+ assert cfg.command == agent
67
+
68
+
69
+ def test_schema_antigravity_accepted_by_literal() -> None:
70
+ cfg = AgentCliConfig(agent="antigravity")
71
+ assert cfg.agent == "antigravity"
72
+
73
+
74
+ def test_schema_antigravity_explicit_command_not_overridden() -> None:
75
+ cfg = AgentCliConfig(agent="antigravity", command="/opt/bin/agy")
76
+ assert cfg.command == "/opt/bin/agy"
77
+
78
+
79
+ def test_schema_write_conflict_rejected() -> None:
80
+ with pytest.raises(ValidationError, match="conflicts with"):
81
+ AgentCliConfig(agent="claude", allow_file_writes=True, sandbox_mode="read_only")
@@ -67,9 +67,7 @@ class _FakeAgentAdapter(BaseAdapter):
67
67
  async def healthcheck(self) -> bool:
68
68
  return True
69
69
 
70
- async def generate(
71
- self, request: ChatRequest, *, overrides: Any = None
72
- ) -> ChatResponse:
70
+ async def generate(self, request: ChatRequest, *, overrides: Any = None) -> ChatResponse:
73
71
  return ChatResponse(
74
72
  id="fake-agent-1",
75
73
  created=int(time.time()),
@@ -121,9 +119,7 @@ class _ShadowOpenAICompatProvider:
121
119
  pass
122
120
 
123
121
  def build(self, config: ProviderConfig) -> BaseAdapter:
124
- raise AssertionError(
125
- "plugin factory must not be consulted for an in-core kind"
126
- )
122
+ raise AssertionError("plugin factory must not be consulted for an in-core kind")
127
123
 
128
124
 
129
125
  def _fake_agent_provider_config(**overrides: object) -> ProviderConfig:
@@ -222,6 +218,57 @@ def test_in_core_agent_cli_kind_is_not_shadowed_by_plugin() -> None:
222
218
  assert isinstance(adapter, AgentCliAdapter)
223
219
 
224
220
 
221
+ def test_in_core_agent_cli_deprecation_logged_once_per_process(
222
+ monkeypatch: pytest.MonkeyPatch, caplog: pytest.LogCaptureFixture
223
+ ) -> None:
224
+ """Phase 2b (docs/designs/agent-cli-plugin-extraction.md §5.1):
225
+
226
+ when the in-core ``agent_cli`` branch is taken *and* an adapter
227
+ plugin has also registered a ``kind="agent_cli"`` factory,
228
+ ``build_adapter`` must log ``agent-cli-in-core-deprecated`` exactly
229
+ once per process — not once per call — while still resolving to the
230
+ in-core :class:`AgentCliAdapter` (in-core keeps winning resolution
231
+ order, §3.2).
232
+ """
233
+ import coderouter.adapters.registry as registry_mod
234
+
235
+ # The module-level once-per-process flag may already be set by
236
+ # another test in this session (e.g.
237
+ # test_in_core_agent_cli_kind_is_not_shadowed_by_plugin above, which
238
+ # also exercises the agent_cli + plugin-present combination) — reset
239
+ # it so this test's assertions are deterministic regardless of
240
+ # ordering.
241
+ monkeypatch.setattr(registry_mod, "_agent_cli_deprecation_logged", False)
242
+
243
+ class _AgentCliLikeProvider:
244
+ name = "agents"
245
+ kind = "agent_cli"
246
+
247
+ def __init__(self, **_config: object) -> None:
248
+ pass
249
+
250
+ def build(self, config: ProviderConfig) -> BaseAdapter: # pragma: no cover
251
+ raise AssertionError("in-core must win; plugin factory unused")
252
+
253
+ reg = PluginRegistry()
254
+ reg.add("adapter", _AgentCliLikeProvider())
255
+
256
+ provider = ProviderConfig(
257
+ name="agent",
258
+ kind="agent_cli",
259
+ model="opus",
260
+ agent_cli=AgentCliConfig(agent="claude"),
261
+ )
262
+
263
+ with caplog.at_level("WARNING"):
264
+ first = build_adapter(provider, reg)
265
+ second = build_adapter(provider, reg)
266
+
267
+ assert isinstance(first, AgentCliAdapter)
268
+ assert isinstance(second, AgentCliAdapter)
269
+ assert sum(1 for rec in caplog.records if rec.msg == "agent-cli-in-core-deprecated") == 1
270
+
271
+
225
272
  def test_unknown_kind_error_lists_in_core_and_plugin_kinds() -> None:
226
273
  reg = PluginRegistry()
227
274
  reg.add("adapter", _FakeAgentProvider())
@@ -291,9 +338,7 @@ def test_adapter_group_is_active_not_future(
291
338
 
292
339
  assert reg.count("adapter") == 1
293
340
  assert reg.adapters[0].kind == "fake_agent"
294
- assert not any(
295
- rec.msg == "plugin-group-not-yet-active" for rec in caplog.records
296
- )
341
+ assert not any(rec.msg == "plugin-group-not-yet-active" for rec in caplog.records)
297
342
 
298
343
 
299
344
  def test_installed_but_not_enabled_adapter_is_unavailable(