coderouter-cli 2.7.10__tar.gz → 2.8.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/CHANGELOG.md +47 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/PKG-INFO +1 -1
- coderouter_cli-2.8.0/coderouter/adapters/registry.py +60 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/config/schemas.py +12 -2
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/plugins/base.py +54 -26
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/plugins/loader.py +8 -5
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/plugins/registry.py +13 -2
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/routing/fallback.py +7 -3
- coderouter_cli-2.8.0/docs/designs/agent-cli-plugin-extraction.md +410 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/docs/designs/external-agents-adapter.md +4 -0
- coderouter_cli-2.8.0/docs/designs/orchestration-companion.md +109 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/pyproject.toml +1 -1
- coderouter_cli-2.8.0/tests/test_plugin_adapter.py +404 -0
- coderouter_cli-2.7.10/coderouter/adapters/registry.py +0 -23
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/.gitignore +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/LICENSE +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/README.en.md +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/README.md +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/__init__.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/__main__.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/adapters/__init__.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/adapters/agent_cli.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/adapters/anthropic_native.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/adapters/base.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/adapters/openai_compat.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/cli.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/cli_stats.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/config/__init__.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/config/capability_registry.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/config/env_file.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/config/loader.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/cost.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/data/__init__.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/data/model-capabilities.yaml +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/doctor.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/doctor_apply.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/env_security.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/errors.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/gguf_introspect.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/guards/__init__.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/guards/_fingerprint.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/guards/backend_health.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/guards/context_budget.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/guards/continuous_probe.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/guards/drift_actions.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/guards/drift_detection.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/guards/memory_budget.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/guards/memory_pressure.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/guards/self_healing.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/guards/tool_loop.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/hardware.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/ingress/__init__.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/ingress/anthropic_routes.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/ingress/app.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/ingress/dashboard_routes.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/ingress/launcher_routes.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/ingress/metrics_routes.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/ingress/openai_routes.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/language_tax.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/launcher_speculative.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/logging.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/metrics/__init__.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/metrics/collector.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/metrics/prometheus.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/output_filters.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/plugins/__init__.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/routing/__init__.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/routing/adaptive.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/routing/auto_router.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/routing/budget.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/routing/capability.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/state/__init__.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/state/audit_log.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/state/replay.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/state/request_log.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/state/store.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/state/suggest_rules.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/token_estimation.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/token_estimation_accurate.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/translation/__init__.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/translation/anthropic.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/translation/convert.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/coderouter/translation/tool_repair.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/docs/README.en.md +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/docs/README.md +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/docs/assets/dashboard-demo.png +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/docs/backends/claude-code-llamacpp-vllm.en.md +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/docs/backends/claude-code-llamacpp-vllm.md +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/docs/backends/external-agents.en.md +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/docs/backends/external-agents.md +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/docs/backends/gguf_dl.en.md +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/docs/backends/gguf_dl.md +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/docs/backends/hf-ollama-models.en.md +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/docs/backends/hf-ollama-models.md +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/docs/backends/install-backends.en.md +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/docs/backends/install-backends.md +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/docs/backends/launcher-quickstart.en.md +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/docs/backends/launcher-quickstart.md +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/docs/backends/launcher.en.md +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/docs/backends/launcher.md +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/docs/backends/llamacpp-direct.en.md +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/docs/backends/llamacpp-direct.md +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/docs/backends/lmstudio-direct.en.md +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/docs/backends/lmstudio-direct.md +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/docs/backends/verify-ollama-0.23.1.md +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/docs/concepts/architecture.en.md +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/docs/concepts/architecture.md +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/docs/concepts/context-budget.en.md +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/docs/concepts/context-budget.md +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/docs/concepts/continuous-probing.en.md +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/docs/concepts/continuous-probing.md +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/docs/concepts/drift-detection.en.md +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/docs/concepts/drift-detection.md +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/docs/concepts/partial-stitch.en.md +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/docs/concepts/partial-stitch.md +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/docs/designs/v1.5-dashboard-mockup.html +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/docs/designs/v1.6-auto-router-verification.md +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/docs/designs/v1.6-auto-router.md +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/docs/guides/free-tier-guide.en.md +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/docs/guides/free-tier-guide.md +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/docs/guides/language-tax.en.md +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/docs/guides/language-tax.md +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/docs/guides/remote-access.en.md +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/docs/guides/remote-access.md +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/docs/guides/security.en.md +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/docs/guides/security.md +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/docs/guides/troubleshooting.en.md +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/docs/guides/troubleshooting.md +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/docs/guides/usage-guide.en.md +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/docs/guides/usage-guide.md +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/docs/low-memory-integration.en.md +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/docs/low-memory-integration.md +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/docs/openrouter-roster/CHANGES.md +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/docs/openrouter-roster/README.md +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/docs/openrouter-roster/latest.json +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/docs/retrospectives/v0.4.md +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/docs/retrospectives/v0.5-verify.md +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/docs/retrospectives/v0.5.md +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/docs/retrospectives/v0.6.md +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/docs/retrospectives/v0.7.md +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/docs/retrospectives/v1.0-verify.md +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/docs/retrospectives/v1.0.md +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/docs/start/quickstart.en.md +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/docs/start/quickstart.md +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/docs/start/when-do-i-need-coderouter.en.md +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/docs/start/when-do-i-need-coderouter.md +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/examples/.env.example +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/examples/README.md +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/examples/providers-agent-cli.yaml +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/examples/providers-multiagent.yaml +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/examples/providers.context-budget-test.yaml +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/examples/providers.llamacpp-vllm.yaml +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/examples/providers.nvidia-nim.yaml +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/examples/providers.ollama-auto-custom.yaml +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/examples/providers.ollama-auto.yaml +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/examples/providers.ollama-free-chain.yaml +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/examples/providers.raspberrypi.yaml +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/examples/providers.yaml +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/scripts/demo_traffic.sh +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/scripts/openrouter_roster_diff.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/scripts/smoke_v2_2.sh +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/scripts/verify-providers.yaml +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/scripts/verify_ollama_0_23.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/scripts/verify_v0_5.sh +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/scripts/verify_v1_0.sh +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/__init__.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/conftest.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_adapter_anthropic.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_agent_cli.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_audit_log.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_auto_router.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_auto_router_cjk.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_backend_health.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_budget.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_capability.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_capability_degraded_payload.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_capability_registry.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_capability_registry_cache_control.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_capability_tool_choice.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_claude_code_suitability.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_cli.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_cli_bind_warning.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_cli_stats.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_config.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_config_shim_actions.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_context_budget.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_continuous_probe.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_dashboard_endpoint.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_doctor.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_doctor_apply.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_doctor_cache_probe.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_drift_actions.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_drift_detection.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_drift_detection_integration.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_env_file.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_env_security.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_errors.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_examples_yaml.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_fallback.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_fallback_anthropic.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_fallback_cache_control.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_fallback_cache_observed.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_fallback_cache_strip.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_fallback_empty_response.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_fallback_misconfig_warn.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_fallback_paid_gate.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_fallback_thinking.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_fallback_tool_choice_emulate.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_fix_h1_prometheus_drift.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_fix_h2_h6_translation.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_fix_h3_client_reuse.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_fix_h4_h5_guards.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_fix_h7_probe_restore.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_fix_h8_launcher_auth.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_fix_mA_routing.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_fix_mB_adapters.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_fix_mC_convert.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_fix_mD_logging_metrics.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_fix_mE_config_validation.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_fix_mF_ingress.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_gguf_introspect.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_guards_tool_loop.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_hardware.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_ingress_anthropic.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_ingress_count_tokens.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_ingress_profile.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_language_tax.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_language_tax_integration.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_launcher_mtp.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_launcher_mtp_fallback.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_launcher_provider_sync.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_memory_budget.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_memory_pressure.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_metrics_cache.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_metrics_collector.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_metrics_cost.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_metrics_endpoint.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_metrics_jsonl.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_metrics_prometheus.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_metrics_prometheus_cache.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_models_passthrough.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_openai_compat.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_openrouter_roster_diff.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_output_filters.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_output_filters_adapters.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_partial_stitch.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_plugins_integration.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_plugins_loader.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_plugins_registry.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_reasoning_strip.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_repair_byte_fallback.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_request_log.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_role_normalization.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_routing_adaptive.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_self_healing.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_setup_sh.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_state_store.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_token_estimation.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_token_estimation_accurate.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_tokens_saved_metric.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_tool_repair.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_tool_repair_lenient.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_tool_repair_r4.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_toolrepair_bench.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_translation_anthropic.py +0 -0
- {coderouter_cli-2.7.10 → coderouter_cli-2.8.0}/tests/test_translation_reverse.py +0 -0
|
@@ -9,6 +9,53 @@ are kept verbatim where the Japanese text itself is the subject).
|
|
|
9
9
|
|
|
10
10
|
---
|
|
11
11
|
|
|
12
|
+
## [v2.8.0] — 2026-07-11 (Plugin SDK: Adapter hook wired — Phase 2a of the agent_cli extraction)
|
|
13
|
+
|
|
14
|
+
Opens the Plugin SDK's Adapter surface: the previously dead-end `Adapter`
|
|
15
|
+
Protocol (name-only) is now a real engine-integrated hook, so an external
|
|
16
|
+
plugin package can provide new `kind` values for providers.yaml without
|
|
17
|
+
touching Core. This is Phase 2a of the agent_cli plugin-extraction design
|
|
18
|
+
(`docs/designs/agent-cli-plugin-extraction.md`): hook wiring only — the
|
|
19
|
+
in-core `agent_cli` adapter is unchanged and keeps working exactly as in
|
|
20
|
+
v2.7.10; the actual move into `coderouter-plugin-agents` is Phase 2b/2c.
|
|
21
|
+
|
|
22
|
+
### Added
|
|
23
|
+
|
|
24
|
+
- **`Adapter` plugin Protocol** (`coderouter/plugins/base.py`) — `kind: str`
|
|
25
|
+
plus synchronous `build(config: ProviderConfig) -> BaseAdapter`. A factory
|
|
26
|
+
shape (kind → adapter), unlike the per-request hooks: construction happens
|
|
27
|
+
once at startup and does no I/O. The `adapter` entry-point group
|
|
28
|
+
(`coderouter.adapter`, singular — matching the loader's group mechanics)
|
|
29
|
+
moved from the future list into the active groups; the existing two-stage
|
|
30
|
+
gate (installed + listed in `plugins.enabled`) applies as-is.
|
|
31
|
+
- **`build_adapter` plugin resolution** (`coderouter/adapters/registry.py`)
|
|
32
|
+
— resolution order is in-core kinds first (`openai_compat` / `anthropic` /
|
|
33
|
+
`agent_cli`; a plugin can never shadow them), then plugin-provided kinds,
|
|
34
|
+
then a `ValueError` listing every known kind plus an install/enable hint.
|
|
35
|
+
Both engine call sites (startup adapter cache + runtime
|
|
36
|
+
`register_provider`) pass the plugin registry.
|
|
37
|
+
- **Tests** (`tests/test_plugin_adapter.py`, new, 10) — plugin-kind
|
|
38
|
+
resolution, in-core shadowing prevention, unknown-kind error contents,
|
|
39
|
+
two-stage gate via the real entry-point loader path, runtime
|
|
40
|
+
`register_provider` with a plugin kind, and an E2E request through
|
|
41
|
+
`POST /v1/chat/completions` served by a plugin-provided adapter.
|
|
42
|
+
|
|
43
|
+
### Changed
|
|
44
|
+
|
|
45
|
+
- **`ProviderConfig.kind`: `Literal[...]` → `str`** (`config/schemas.py`) —
|
|
46
|
+
plugin kinds cannot be known at config-load time (plugins are discovered
|
|
47
|
+
after the config is parsed), so the closed Literal had to open. Fail-fast
|
|
48
|
+
for a typo'd kind moves one step later but stays at startup: the engine
|
|
49
|
+
builds adapters for **all** providers eagerly in its constructor, so an
|
|
50
|
+
unknown kind still aborts `serve` at load with a message that now lists
|
|
51
|
+
in-core and plugin kinds (strictly more helpful than the old pydantic
|
|
52
|
+
error). Recorded as a design deviation in
|
|
53
|
+
`agent-cli-plugin-extraction.md` §8.1, including the residual limitation
|
|
54
|
+
that `doctor` (HTTP-probe based) does not surface typo'd kinds.
|
|
55
|
+
- Plugin-group bookkeeping: `adapter` no longer warns as
|
|
56
|
+
"plugin-group-not-yet-active"; `PluginRegistry` gained an `adapters`
|
|
57
|
+
view alongside `input_filters` / `observers`.
|
|
58
|
+
|
|
12
59
|
## [v2.7.10] — 2026-07-11 (agent_cli Phase 1c: antigravity — Phase 1 complete)
|
|
13
60
|
|
|
14
61
|
Completes agent_cli Phase 1: `agent: antigravity` (the Google Antigravity
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: coderouter-cli
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.8.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
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"""Adapter factory — maps `kind` strings to adapter classes."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import TYPE_CHECKING
|
|
6
|
+
|
|
7
|
+
from coderouter.adapters.anthropic_native import AnthropicAdapter
|
|
8
|
+
from coderouter.adapters.base import BaseAdapter
|
|
9
|
+
from coderouter.adapters.openai_compat import OpenAICompatAdapter
|
|
10
|
+
from coderouter.config.schemas import ProviderConfig
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from coderouter.plugins.registry import PluginRegistry
|
|
14
|
+
|
|
15
|
+
# in-core kinds, in resolution order. Kept as a tuple (not derived from
|
|
16
|
+
# the if-chain below) so the "Unknown adapter kind" error message and
|
|
17
|
+
# the plugin-shadow guard have a single source of truth.
|
|
18
|
+
_IN_CORE_KINDS: tuple[str, ...] = ("openai_compat", "anthropic", "agent_cli")
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _plugin_kinds(plugin_registry: PluginRegistry | None) -> list[str]:
|
|
22
|
+
"""``kind`` values served by enabled adapter plugins, for error text."""
|
|
23
|
+
if plugin_registry is None:
|
|
24
|
+
return []
|
|
25
|
+
return [factory.kind for factory in plugin_registry.adapters]
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def build_adapter(
|
|
29
|
+
provider: ProviderConfig,
|
|
30
|
+
plugin_registry: PluginRegistry | None = None,
|
|
31
|
+
) -> BaseAdapter:
|
|
32
|
+
"""Construct an adapter from a ProviderConfig.
|
|
33
|
+
|
|
34
|
+
Resolution order (docs/designs/agent-cli-plugin-extraction.md §3.2):
|
|
35
|
+
in-core kinds first, then plugin-provided kinds, then a fail-fast
|
|
36
|
+
error. In-core kinds are checked first so a plugin can never shadow
|
|
37
|
+
a kind Core itself guarantees (``openai_compat`` / ``anthropic`` /,
|
|
38
|
+
during the Phase 2b migration window, ``agent_cli``).
|
|
39
|
+
"""
|
|
40
|
+
if provider.kind == "openai_compat":
|
|
41
|
+
return OpenAICompatAdapter(provider)
|
|
42
|
+
if provider.kind == "anthropic":
|
|
43
|
+
return AnthropicAdapter(provider)
|
|
44
|
+
if provider.kind == "agent_cli":
|
|
45
|
+
# Imported lazily so the external-agent adapter (and its subprocess /
|
|
46
|
+
# os plumbing) is only pulled in when a config actually uses it.
|
|
47
|
+
from coderouter.adapters.agent_cli import AgentCliAdapter
|
|
48
|
+
|
|
49
|
+
return AgentCliAdapter(provider)
|
|
50
|
+
if plugin_registry is not None:
|
|
51
|
+
for factory in plugin_registry.adapters:
|
|
52
|
+
if factory.kind == provider.kind:
|
|
53
|
+
return factory.build(provider)
|
|
54
|
+
raise ValueError(
|
|
55
|
+
f"Unknown adapter kind {provider.kind!r}. "
|
|
56
|
+
f"in-core kinds: {', '.join(_IN_CORE_KINDS)}; "
|
|
57
|
+
f"plugin-provided kinds: {_plugin_kinds(plugin_registry)}. "
|
|
58
|
+
f"If a plugin should provide {provider.kind!r}, ensure it is "
|
|
59
|
+
f"installed AND listed in plugins.enabled."
|
|
60
|
+
)
|
|
@@ -342,13 +342,23 @@ class ProviderConfig(BaseModel):
|
|
|
342
342
|
model_config = ConfigDict(extra="forbid")
|
|
343
343
|
|
|
344
344
|
name: str = Field(..., description="Unique identifier used in profiles.yaml")
|
|
345
|
-
|
|
345
|
+
# v2.8.0: widened from Literal["openai_compat", "anthropic", "agent_cli"]
|
|
346
|
+
# to str so a provider can name a kind served by an adapter plugin
|
|
347
|
+
# (docs/designs/agent-cli-plugin-extraction.md §3). Config loading
|
|
348
|
+
# happens before plugin discovery (coderouter/ingress/app.py
|
|
349
|
+
# ``load_config`` then ``discover_and_load``), so pydantic can't know
|
|
350
|
+
# the full set of valid kinds at this point — an unknown kind still
|
|
351
|
+
# fails fast, just one step later, in ``build_adapter`` when the
|
|
352
|
+
# engine builds its adapter cache at startup.
|
|
353
|
+
kind: str = Field(
|
|
346
354
|
default="openai_compat",
|
|
347
355
|
description=(
|
|
348
356
|
"Adapter type. 'openai_compat' covers llama.cpp / Ollama / "
|
|
349
357
|
"OpenRouter / LM Studio / Together / Groq. 'anthropic' is the "
|
|
350
358
|
"native Anthropic Messages API passthrough (v0.3.x). 'agent_cli' "
|
|
351
|
-
"invokes an external coding-agent CLI one-shot (see AgentCliConfig)."
|
|
359
|
+
"invokes an external coding-agent CLI one-shot (see AgentCliConfig). "
|
|
360
|
+
"Other values must be served by an adapter plugin listed in "
|
|
361
|
+
"plugins.enabled."
|
|
352
362
|
),
|
|
353
363
|
)
|
|
354
364
|
# base_url is required for HTTP-backed adapters (openai_compat / anthropic)
|
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
"""Plugin SDK Protocol contracts (v2.3.0).
|
|
1
|
+
"""Plugin SDK Protocol contracts (v2.3.0, Adapter wired in v2.8.0).
|
|
2
2
|
|
|
3
|
-
Six extension points are defined here.
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
:class:`
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
Six extension points are defined here. Three are wired into the engine
|
|
4
|
+
(:class:`InputFilter`, :class:`Observer` since v2.3.0; :class:`Adapter`
|
|
5
|
+
since v2.8.0 — see ``docs/designs/agent-cli-plugin-extraction.md`` §2);
|
|
6
|
+
three remain Protocol-only (:class:`Frontend`, :class:`Guard`,
|
|
7
|
+
:class:`OutputFilter`) and will get engine integration when a real
|
|
8
|
+
plugin drives the requirement — see
|
|
9
|
+
``docs/inside/plugin-architecture-draft.md`` §3 for the full design
|
|
10
|
+
rationale.
|
|
9
11
|
|
|
10
12
|
Why declare contracts ahead of integration? It lets a plugin author
|
|
11
13
|
build against the SDK *now* (and ship a working ``coderouter.frontend``
|
|
@@ -14,9 +16,11 @@ backward-incompatible Protocol revision later. ``runtime_checkable``
|
|
|
14
16
|
is used so :func:`isinstance` checks work in the loader for clearer
|
|
15
17
|
error messages.
|
|
16
18
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
19
|
+
InputFilter / Observer are async and run repeatedly on the hot path;
|
|
20
|
+
failures must NEVER block the engine response, so the engine wraps
|
|
21
|
+
every hook call in try/except and degrades gracefully (see
|
|
22
|
+
``coderouter/routing/fallback.py`` integration site). Adapter is
|
|
23
|
+
different in shape — see its docstring below.
|
|
20
24
|
"""
|
|
21
25
|
from __future__ import annotations
|
|
22
26
|
|
|
@@ -25,7 +29,8 @@ from typing import TYPE_CHECKING, Any, Protocol, runtime_checkable
|
|
|
25
29
|
if TYPE_CHECKING:
|
|
26
30
|
# Avoid circular imports at runtime — Protocol typing only needs
|
|
27
31
|
# these for documentation and static analysis.
|
|
28
|
-
from coderouter.
|
|
32
|
+
from coderouter.adapters.base import BaseAdapter
|
|
33
|
+
from coderouter.config.schemas import CodeRouterConfig, ProviderConfig
|
|
29
34
|
from coderouter.translation.anthropic import (
|
|
30
35
|
AnthropicRequest,
|
|
31
36
|
AnthropicResponse,
|
|
@@ -93,6 +98,44 @@ class Observer(Protocol):
|
|
|
93
98
|
async def on_event(self, event_type: str, payload: dict[str, Any]) -> None: ...
|
|
94
99
|
|
|
95
100
|
|
|
101
|
+
# ====================================================================
|
|
102
|
+
# Adapter hook (engine integration in v2.8.0)
|
|
103
|
+
# ====================================================================
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
@runtime_checkable
|
|
107
|
+
class Adapter(Protocol):
|
|
108
|
+
"""New ``kind`` value in providers.yaml, backed by a plugin.
|
|
109
|
+
|
|
110
|
+
The plugin declares the ``kind`` string it serves and a factory
|
|
111
|
+
that turns a matching :class:`~coderouter.config.schemas.ProviderConfig`
|
|
112
|
+
into a :class:`~coderouter.adapters.base.BaseAdapter` instance —
|
|
113
|
+
the same surface :func:`coderouter.adapters.registry.build_adapter`
|
|
114
|
+
uses for in-core kinds, so the engine treats plugin adapters
|
|
115
|
+
indistinguishably from built-ins once registered. See
|
|
116
|
+
``docs/designs/agent-cli-plugin-extraction.md`` §2 for the design
|
|
117
|
+
rationale.
|
|
118
|
+
|
|
119
|
+
Shape-wise this hook differs from :class:`InputFilter` /
|
|
120
|
+
:class:`Observer`: those are instances the engine calls repeatedly
|
|
121
|
+
on the hot path, so they're async. An adapter provider is instead
|
|
122
|
+
a **factory** consulted once per provider at engine startup (and
|
|
123
|
+
again if the provider is re-registered at runtime) — construction
|
|
124
|
+
is I/O-free, so :meth:`build` is synchronous, matching
|
|
125
|
+
``build_adapter``.
|
|
126
|
+
"""
|
|
127
|
+
|
|
128
|
+
name: str
|
|
129
|
+
# The ``kind`` value this plugin serves in providers.yaml. Distinct
|
|
130
|
+
# from ``name`` (the plugin's own identifier, used in
|
|
131
|
+
# ``plugins.enabled`` / logs) — kept 1:1 for now; a future
|
|
132
|
+
# ``kinds: tuple[str, ...]`` can generalize this if a real plugin
|
|
133
|
+
# needs to serve more than one kind.
|
|
134
|
+
kind: str
|
|
135
|
+
|
|
136
|
+
def build(self, config: ProviderConfig) -> BaseAdapter: ...
|
|
137
|
+
|
|
138
|
+
|
|
96
139
|
# ====================================================================
|
|
97
140
|
# Future hooks (Protocol-only, engine integration in v2.4+)
|
|
98
141
|
# ====================================================================
|
|
@@ -151,18 +194,3 @@ class OutputFilter(Protocol):
|
|
|
151
194
|
async def transform(
|
|
152
195
|
self, response: AnthropicResponse
|
|
153
196
|
) -> AnthropicResponse: ...
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
@runtime_checkable
|
|
157
|
-
class Adapter(Protocol):
|
|
158
|
-
"""New ``kind`` value in providers.yaml (e.g. ``bedrock-native``).
|
|
159
|
-
|
|
160
|
-
Plugins implement the same async surface as
|
|
161
|
-
:class:`coderouter.adapters.base.BaseAdapter` so the engine can
|
|
162
|
-
treat them indistinguishably from built-in adapters once the
|
|
163
|
-
loader registers the new ``kind`` mapping.
|
|
164
|
-
|
|
165
|
-
Not yet integrated — Protocol contract only.
|
|
166
|
-
"""
|
|
167
|
-
|
|
168
|
-
name: str
|
|
@@ -38,10 +38,14 @@ if TYPE_CHECKING:
|
|
|
38
38
|
|
|
39
39
|
logger = get_logger(__name__)
|
|
40
40
|
|
|
41
|
-
# Active hook groups
|
|
42
|
-
#
|
|
43
|
-
#
|
|
44
|
-
|
|
41
|
+
# Active hook groups. The engine wires these into the request flow;
|
|
42
|
+
# plugins targeting them will see their methods called at runtime.
|
|
43
|
+
# ``input_filter`` / ``observer`` since v2.3.0; ``adapter`` joined in
|
|
44
|
+
# v2.8.0 (docs/designs/agent-cli-plugin-extraction.md §2.4) — its
|
|
45
|
+
# factories are consulted from ``build_adapter``, not iterated on the
|
|
46
|
+
# hot path like the other two, but it goes through the same
|
|
47
|
+
# discover-then-enable-gate machinery below.
|
|
48
|
+
PLUGIN_GROUPS_V2_3: tuple[str, ...] = ("input_filter", "observer", "adapter")
|
|
45
49
|
|
|
46
50
|
# Hook groups whose Protocol contracts are stable but whose engine
|
|
47
51
|
# integration is deferred. Listing them here means a plugin author
|
|
@@ -51,7 +55,6 @@ PLUGIN_GROUPS_FUTURE: tuple[str, ...] = (
|
|
|
51
55
|
"frontend",
|
|
52
56
|
"guard",
|
|
53
57
|
"output_filter",
|
|
54
|
-
"adapter",
|
|
55
58
|
)
|
|
56
59
|
|
|
57
60
|
|
|
@@ -20,8 +20,8 @@ from typing import Any
|
|
|
20
20
|
class PluginRegistry:
|
|
21
21
|
"""In-memory registry of loaded plugin instances grouped by hook kind.
|
|
22
22
|
|
|
23
|
-
Use the typed ``input_filters`` / ``observers``
|
|
24
|
-
|
|
23
|
+
Use the typed ``input_filters`` / ``observers`` / ``adapters``
|
|
24
|
+
properties; plugin code should not iterate ``_by_group`` directly.
|
|
25
25
|
"""
|
|
26
26
|
|
|
27
27
|
def __init__(self) -> None:
|
|
@@ -65,6 +65,17 @@ class PluginRegistry:
|
|
|
65
65
|
"""Plugins registered as ``coderouter.observer``."""
|
|
66
66
|
return list(self._by_group.get("observer", ()))
|
|
67
67
|
|
|
68
|
+
@property
|
|
69
|
+
def adapters(self) -> list[Any]:
|
|
70
|
+
"""Plugins registered as ``coderouter.adapter`` (kind factories).
|
|
71
|
+
|
|
72
|
+
Unlike ``input_filters`` / ``observers``, these aren't called
|
|
73
|
+
repeatedly on the hot path — :func:`coderouter.adapters.registry.build_adapter`
|
|
74
|
+
consults this list once per provider to resolve a plugin-served
|
|
75
|
+
``kind`` (v2.8.0, docs/designs/agent-cli-plugin-extraction.md §2.4).
|
|
76
|
+
"""
|
|
77
|
+
return list(self._by_group.get("adapter", ()))
|
|
78
|
+
|
|
68
79
|
def is_empty(self) -> bool:
|
|
69
80
|
"""True iff no plugin instance has been registered, in any group.
|
|
70
81
|
|
|
@@ -1104,9 +1104,13 @@ class FallbackEngine:
|
|
|
1104
1104
|
# via ``add_done_callback(_observer_tasks.discard)`` in
|
|
1105
1105
|
# :meth:`_fanout_observers`.
|
|
1106
1106
|
self._observer_tasks: set[asyncio.Task[None]] = set()
|
|
1107
|
-
# Cache adapters so we don't re-instantiate per request
|
|
1107
|
+
# Cache adapters so we don't re-instantiate per request. v2.8.0:
|
|
1108
|
+
# pass the plugin registry through so a provider whose ``kind``
|
|
1109
|
+
# is served by an enabled adapter plugin resolves via
|
|
1110
|
+
# ``build_adapter``'s plugin lookup (agent-cli-plugin-extraction
|
|
1111
|
+
# §3.5) instead of raising "Unknown adapter kind".
|
|
1108
1112
|
self._adapters: dict[str, BaseAdapter] = {
|
|
1109
|
-
p.name: build_adapter(p) for p in config.providers
|
|
1113
|
+
p.name: build_adapter(p, self._plugin_registry) for p in config.providers
|
|
1110
1114
|
}
|
|
1111
1115
|
# v1.9-C: per-process adaptive routing adjuster (rolling-window
|
|
1112
1116
|
# latency + error-rate observations, debounced rank changes).
|
|
@@ -1217,7 +1221,7 @@ class FallbackEngine:
|
|
|
1217
1221
|
break
|
|
1218
1222
|
if not replaced:
|
|
1219
1223
|
self.config.providers.append(provider)
|
|
1220
|
-
self._adapters[provider.name] = build_adapter(provider)
|
|
1224
|
+
self._adapters[provider.name] = build_adapter(provider, self._plugin_registry)
|
|
1221
1225
|
|
|
1222
1226
|
try:
|
|
1223
1227
|
chain = self.config.profile_by_name(profile_name)
|