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.
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/CHANGELOG.md +29 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/PKG-INFO +1 -1
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/adapters/registry.py +42 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/guides/language-tax.en.md +1 -1
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/guides/language-tax.md +1 -1
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/pyproject.toml +1 -1
- coderouter_cli-2.8.1/tests/test_agent_cli.py +81 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_plugin_adapter.py +54 -9
- coderouter_cli-2.8.0/tests/test_agent_cli.py +0 -1507
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/.gitignore +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/LICENSE +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/README.en.md +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/README.md +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/__init__.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/__main__.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/adapters/__init__.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/adapters/agent_cli.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/adapters/anthropic_native.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/adapters/base.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/adapters/openai_compat.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/cli.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/cli_stats.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/config/__init__.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/config/capability_registry.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/config/env_file.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/config/loader.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/config/schemas.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/cost.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/data/__init__.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/data/model-capabilities.yaml +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/doctor.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/doctor_apply.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/env_security.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/errors.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/gguf_introspect.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/guards/__init__.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/guards/_fingerprint.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/guards/backend_health.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/guards/context_budget.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/guards/continuous_probe.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/guards/drift_actions.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/guards/drift_detection.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/guards/memory_budget.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/guards/memory_pressure.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/guards/self_healing.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/guards/tool_loop.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/hardware.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/ingress/__init__.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/ingress/anthropic_routes.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/ingress/app.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/ingress/dashboard_routes.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/ingress/launcher_routes.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/ingress/metrics_routes.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/ingress/openai_routes.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/language_tax.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/launcher_speculative.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/logging.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/metrics/__init__.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/metrics/collector.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/metrics/prometheus.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/output_filters.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/plugins/__init__.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/plugins/base.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/plugins/loader.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/plugins/registry.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/routing/__init__.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/routing/adaptive.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/routing/auto_router.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/routing/budget.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/routing/capability.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/routing/fallback.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/state/__init__.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/state/audit_log.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/state/replay.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/state/request_log.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/state/store.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/state/suggest_rules.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/token_estimation.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/token_estimation_accurate.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/translation/__init__.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/translation/anthropic.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/translation/convert.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/coderouter/translation/tool_repair.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/README.en.md +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/README.md +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/assets/dashboard-demo.png +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/backends/claude-code-llamacpp-vllm.en.md +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/backends/claude-code-llamacpp-vllm.md +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/backends/external-agents.en.md +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/backends/external-agents.md +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/backends/gguf_dl.en.md +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/backends/gguf_dl.md +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/backends/hf-ollama-models.en.md +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/backends/hf-ollama-models.md +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/backends/install-backends.en.md +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/backends/install-backends.md +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/backends/launcher-quickstart.en.md +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/backends/launcher-quickstart.md +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/backends/launcher.en.md +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/backends/launcher.md +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/backends/llamacpp-direct.en.md +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/backends/llamacpp-direct.md +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/backends/lmstudio-direct.en.md +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/backends/lmstudio-direct.md +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/backends/verify-ollama-0.23.1.md +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/concepts/architecture.en.md +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/concepts/architecture.md +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/concepts/context-budget.en.md +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/concepts/context-budget.md +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/concepts/continuous-probing.en.md +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/concepts/continuous-probing.md +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/concepts/drift-detection.en.md +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/concepts/drift-detection.md +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/concepts/partial-stitch.en.md +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/concepts/partial-stitch.md +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/designs/agent-cli-plugin-extraction.md +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/designs/external-agents-adapter.md +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/designs/orchestration-companion.md +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/designs/v1.5-dashboard-mockup.html +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/designs/v1.6-auto-router-verification.md +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/designs/v1.6-auto-router.md +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/guides/free-tier-guide.en.md +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/guides/free-tier-guide.md +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/guides/remote-access.en.md +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/guides/remote-access.md +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/guides/security.en.md +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/guides/security.md +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/guides/troubleshooting.en.md +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/guides/troubleshooting.md +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/guides/usage-guide.en.md +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/guides/usage-guide.md +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/low-memory-integration.en.md +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/low-memory-integration.md +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/openrouter-roster/CHANGES.md +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/openrouter-roster/README.md +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/openrouter-roster/latest.json +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/retrospectives/v0.4.md +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/retrospectives/v0.5-verify.md +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/retrospectives/v0.5.md +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/retrospectives/v0.6.md +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/retrospectives/v0.7.md +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/retrospectives/v1.0-verify.md +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/retrospectives/v1.0.md +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/start/quickstart.en.md +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/start/quickstart.md +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/start/when-do-i-need-coderouter.en.md +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/docs/start/when-do-i-need-coderouter.md +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/examples/.env.example +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/examples/README.md +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/examples/providers-agent-cli.yaml +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/examples/providers-multiagent.yaml +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/examples/providers.context-budget-test.yaml +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/examples/providers.llamacpp-vllm.yaml +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/examples/providers.nvidia-nim.yaml +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/examples/providers.ollama-auto-custom.yaml +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/examples/providers.ollama-auto.yaml +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/examples/providers.ollama-free-chain.yaml +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/examples/providers.raspberrypi.yaml +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/examples/providers.yaml +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/scripts/demo_traffic.sh +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/scripts/openrouter_roster_diff.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/scripts/smoke_v2_2.sh +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/scripts/verify-providers.yaml +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/scripts/verify_ollama_0_23.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/scripts/verify_v0_5.sh +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/scripts/verify_v1_0.sh +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/__init__.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/conftest.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_adapter_anthropic.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_audit_log.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_auto_router.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_auto_router_cjk.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_backend_health.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_budget.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_capability.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_capability_degraded_payload.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_capability_registry.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_capability_registry_cache_control.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_capability_tool_choice.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_claude_code_suitability.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_cli.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_cli_bind_warning.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_cli_stats.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_config.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_config_shim_actions.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_context_budget.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_continuous_probe.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_dashboard_endpoint.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_doctor.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_doctor_apply.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_doctor_cache_probe.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_drift_actions.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_drift_detection.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_drift_detection_integration.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_env_file.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_env_security.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_errors.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_examples_yaml.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_fallback.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_fallback_anthropic.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_fallback_cache_control.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_fallback_cache_observed.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_fallback_cache_strip.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_fallback_empty_response.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_fallback_misconfig_warn.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_fallback_paid_gate.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_fallback_thinking.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_fallback_tool_choice_emulate.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_fix_h1_prometheus_drift.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_fix_h2_h6_translation.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_fix_h3_client_reuse.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_fix_h4_h5_guards.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_fix_h7_probe_restore.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_fix_h8_launcher_auth.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_fix_mA_routing.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_fix_mB_adapters.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_fix_mC_convert.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_fix_mD_logging_metrics.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_fix_mE_config_validation.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_fix_mF_ingress.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_gguf_introspect.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_guards_tool_loop.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_hardware.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_ingress_anthropic.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_ingress_count_tokens.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_ingress_profile.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_language_tax.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_language_tax_integration.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_launcher_mtp.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_launcher_mtp_fallback.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_launcher_provider_sync.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_memory_budget.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_memory_pressure.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_metrics_cache.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_metrics_collector.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_metrics_cost.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_metrics_endpoint.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_metrics_jsonl.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_metrics_prometheus.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_metrics_prometheus_cache.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_models_passthrough.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_openai_compat.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_openrouter_roster_diff.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_output_filters.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_output_filters_adapters.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_partial_stitch.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_plugins_integration.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_plugins_loader.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_plugins_registry.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_reasoning_strip.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_repair_byte_fallback.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_request_log.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_role_normalization.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_routing_adaptive.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_self_healing.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_setup_sh.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_state_store.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_token_estimation.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_token_estimation_accurate.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_tokens_saved_metric.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_tool_repair.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_tool_repair_lenient.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_tool_repair_r4.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_toolrepair_bench.py +0 -0
- {coderouter_cli-2.8.0 → coderouter_cli-2.8.1}/tests/test_translation_anthropic.py +0 -0
- {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.
|
|
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/
|
|
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/
|
|
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.
|
|
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(
|