coding-proxy 0.4.1a3__tar.gz → 0.4.1a4__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.
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/PKG-INFO +1 -1
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/docs/issue.md +44 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/pyproject.toml +1 -1
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/logging/db.py +4 -2
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_session_aware.py +14 -3
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/uv.lock +1 -1
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/.github/workflows/ci.yml +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/.github/workflows/coverage.yml +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/.github/workflows/release.yml +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/.gitignore +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/.pre-commit-config.yaml +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/AGENTS.md +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/CHANGELOG.md +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/CLAUDE.md +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/LICENSE +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/README.md +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/assets/dashboard-v0.4.0.png +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/assets/session-v0.4.0.png +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/docs/agents/knowledge-map.md +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/docs/agents/reference-specifications.md +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/docs/arch/config-reference.md +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/docs/arch/convert.md +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/docs/arch/design-patterns.md +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/docs/arch/routing.md +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/docs/arch/testing.md +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/docs/arch/vendors.md +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/docs/ci-cd.md +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/docs/framework.md +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/docs/guide/api-reference.md +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/docs/guide/cli-reference.md +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/docs/guide/dashboard.md +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/docs/guide/monitoring.md +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/docs/guide/quickstart.md +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/docs/guide/vendors.md +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/docs/user-guide.md +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/docs/zh-CN/README.md +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/__init__.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/__init__.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/__main__.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/auth/__init__.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/auth/providers/__init__.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/auth/providers/base.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/auth/providers/github.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/auth/providers/google.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/auth/runtime.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/auth/store.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/cli/__init__.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/cli/auth_commands.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/cli/banner.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/compat/__init__.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/compat/canonical.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/compat/session_store.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/config/__init__.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/config/auth_schema.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/config/config.default.yaml +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/config/loader.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/config/resiliency.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/config/routing.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/config/schema.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/config/server.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/config/session_policy.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/config/vendors.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/convert/__init__.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/convert/anthropic_to_gemini.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/convert/anthropic_to_openai.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/convert/gemini_sse_adapter.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/convert/gemini_to_anthropic.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/convert/openai_to_anthropic.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/convert/vendor_channels.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/logging/__init__.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/logging/formatters.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/logging/stats.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/model/__init__.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/model/auth.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/model/compat.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/model/constants.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/model/pricing.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/model/token.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/model/vendor.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/native_api/__init__.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/native_api/config.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/native_api/extractors/__init__.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/native_api/extractors/anthropic.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/native_api/extractors/gemini.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/native_api/extractors/openai.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/native_api/handler.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/native_api/operation.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/native_api/routes.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/native_api/usage_registry.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/pricing.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/routing/__init__.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/routing/circuit_breaker.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/routing/error_classifier.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/routing/executor.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/routing/model_mapper.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/routing/quota_guard.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/routing/rate_limit.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/routing/retry.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/routing/router.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/routing/session_manager.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/routing/session_policy.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/routing/tier.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/routing/usage_parser.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/routing/usage_recorder.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/server/__init__.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/server/app.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/server/dashboard.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/server/factory.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/server/responses.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/server/routes.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/streaming/__init__.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/streaming/anthropic_compat.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/vendors/__init__.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/vendors/alibaba.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/vendors/anthropic.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/vendors/antigravity.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/vendors/base.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/vendors/copilot.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/vendors/copilot_models.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/vendors/copilot_token_manager.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/vendors/copilot_urls.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/vendors/doubao.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/vendors/kimi.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/vendors/minimax.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/vendors/mixins.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/vendors/native_anthropic.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/vendors/token_manager.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/vendors/xiaomi.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/vendors/zhipu.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/__init__.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/e2e/__init__.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/e2e/conftest.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/e2e/test_e2e_http.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/e2e/test_e2e_token.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/e2e/test_e2e_vendor.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_antigravity.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_app_routes.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_auto_login.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_banner.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_circuit_breaker.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_cli_usage.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_compat.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_config_init.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_config_loader.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_convert_request.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_convert_response.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_convert_sse.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_copilot.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_copilot_convert_request.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_copilot_convert_response.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_copilot_models.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_copilot_urls.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_currency.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_error_classifier.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_logging_dual_write.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_mixins.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_model_auth.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_model_compat.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_model_constants.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_model_mapper.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_model_pricing.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_model_token.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_model_vendor.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_native_api_base_url_override.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_native_api_extractors.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_native_api_handler.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_native_api_operation.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_native_api_routes.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_native_vendors.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_parse_usage.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_parse_usage_gemini.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_pricing.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_quota_guard.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_rate_limit.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_router_chain.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_router_executor.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_runtime_reauth.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_schema.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_streaming_anthropic_compat.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_tier.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_tiers_config.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_time_range.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_token_logger.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_token_logger_native_columns.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_token_manager.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_types.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_vendor_channels.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_vendor_streaming.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_vendors.py +0 -0
- {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_zhipu.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: coding-proxy
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.1a4
|
|
4
4
|
Summary: A High-Availability, Transparent, and Smart Multi-Vendor Proxy for Claude Code. Support Claude Plans, GitHub Copilot, Google Antigravity, ZAI/GLM, MiniMax, Qwen, Xiaomi, Kimi, Doubao...
|
|
5
5
|
Project-URL: Source Code, https://github.com/ThreeFish-AI/coding-proxy
|
|
6
6
|
Project-URL: User Guide, https://github.com/ThreeFish-AI/coding-proxy/blob/master/docs/user-guide.md
|
|
@@ -186,3 +186,47 @@ litellm 按 Google AI Studio 格式构造请求:
|
|
|
186
186
|
|
|
187
187
|
- litellm 在 Gemini 其他端点(`generateContent` / `countTokens`)同样存在 `_check_custom_proxy` 丢失 `v1beta/` 前缀的 bug;本次仅放宽了 `operation.py` 中的路径正则(让分类器能识别此类异常路径),未对这些端点做格式转换,因为非 embedding 端点的 Google AI Studio / Vertex AI 请求体差异较小,多数上游兼容。如未来出现类似失配再做针对性适配。
|
|
188
188
|
- 若上游网关同时支持 OpenAI `/v1/embeddings` 与 Vertex AI 路径,建议优先在客户端配置 OpenAI 兼容路径,减少协议转换链路。
|
|
189
|
+
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
## Dashboard Sessions 页 `Tokens` 列漏算缓存 Token
|
|
193
|
+
|
|
194
|
+
**问题描述**
|
|
195
|
+
|
|
196
|
+
Dashboard 的 **Sessions** 标签页中,每条会话的 `Tokens` 列与展开详情卡的 `Tokens` 值,仅统计 `input + output`,遗漏了 `cache_creation`(写缓存)与 `cache_read`(读缓存)。在长链路 Anthropic Prompt Cache 场景下,读取命中常常是 input/output 的数倍,导致 Sessions 页总量被显著低估,与 Overview 标签页(卡片、Token 时序图)跨页口径分裂。
|
|
197
|
+
|
|
198
|
+
**表因**
|
|
199
|
+
|
|
200
|
+
前端 `dashboard.py:1597 / 1614` 直接渲染 `s.total_tokens`,该值由 `/api/dashboard/sessions` 透传自 `token_logger.query_recent_sessions()` 的聚合结果。
|
|
201
|
+
|
|
202
|
+
**根因**
|
|
203
|
+
|
|
204
|
+
`src/coding/proxy/logging/db.py` 中两条按 `session_key` 分组的聚合 SQL 使用了不完整的求和口径:
|
|
205
|
+
|
|
206
|
+
```sql
|
|
207
|
+
SUM(input_tokens + output_tokens) AS total_tokens -- 第 607 行(query_recent_sessions)
|
|
208
|
+
SUM(input_tokens + output_tokens) AS total_tokens -- 第 634 行(query_session_profile)
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
而同文件内 `query_usage()`(第 465–466 行分别 `SUM(...)` 四列)与 `query_total_tokens_by_vendor()`(第 584 行 `SUM(input + output + cache_creation + cache_read)`)已采用完整四项口径,构成了同文件内的口径双标。
|
|
212
|
+
|
|
213
|
+
**处理方式**
|
|
214
|
+
|
|
215
|
+
复用 `query_total_tokens_by_vendor` 的四项求和表达式,将两处 `total_tokens` 改写为:
|
|
216
|
+
|
|
217
|
+
```sql
|
|
218
|
+
SUM(input_tokens + output_tokens
|
|
219
|
+
+ cache_creation_tokens + cache_read_tokens) AS total_tokens
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
不改动 API 返回结构、不新增字段、不改前端 detail-card——前端 `fmtTokens(s.total_tokens)` 调用无须变更。同时在 `tests/test_session_aware.py` 的 `test_query_recent_sessions_basic` / `test_query_session_profile_found` 中追加 `cache_creation_tokens` / `cache_read_tokens` 入参与完整口径断言,覆盖回归。
|
|
223
|
+
|
|
224
|
+
**后续防范**
|
|
225
|
+
|
|
226
|
+
- SQL 聚合层涉及"总 Tokens"概念时,必须保持**单一权威定义**(Single Source of Truth):要么所有视图共用同一求和表达式,要么抽取为常量片段集中引用,杜绝多处独立维护造成的语义漂移。
|
|
227
|
+
- 未来若引入新的 token 维度(如 reasoning_tokens、tool_tokens 等),需要全文检索 `SUM(input_tokens + output_tokens` 这一历史模式并同步补齐,避免出现新的口径分裂点。
|
|
228
|
+
|
|
229
|
+
**同类问题影响与处理注意事项**
|
|
230
|
+
|
|
231
|
+
- 历次 PR 中 cache token 字段的引入是渐进式的(schema 已有四列、`log()` 入参齐全、Overview 已全口径消费),但部分聚合视图的口径升级被遗漏;任何向 `usage_log` 增列后,**必须**审计所有 `SUM(input_tokens` / `SUM(output_tokens` 出现处的聚合表达式是否需要同步更新。
|
|
232
|
+
- 跨标签页同一指标(如"总 Tokens")的口径一致性,建议在添加新视图时主动与 Overview 现有口径做交叉核对,必要时在 SQL 注释中标注口径来源,便于后续 review。
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "coding-proxy"
|
|
3
|
-
version = "0.4.
|
|
3
|
+
version = "0.4.1a4"
|
|
4
4
|
description = "A High-Availability, Transparent, and Smart Multi-Vendor Proxy for Claude Code. Support Claude Plans, GitHub Copilot, Google Antigravity, ZAI/GLM, MiniMax, Qwen, Xiaomi, Kimi, Doubao..."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.12"
|
|
@@ -604,7 +604,8 @@ class TokenLogger:
|
|
|
604
604
|
MIN(ts) AS first_seen_ts,
|
|
605
605
|
MAX(ts) AS last_active_ts,
|
|
606
606
|
COUNT(*) AS total_requests,
|
|
607
|
-
SUM(input_tokens + output_tokens
|
|
607
|
+
SUM(input_tokens + output_tokens
|
|
608
|
+
+ cache_creation_tokens + cache_read_tokens) AS total_tokens,
|
|
608
609
|
SUM(input_tokens) AS total_input,
|
|
609
610
|
SUM(output_tokens) AS total_output,
|
|
610
611
|
GROUP_CONCAT(DISTINCT model_served) AS models,
|
|
@@ -631,7 +632,8 @@ class TokenLogger:
|
|
|
631
632
|
MIN(ts) AS first_seen_ts,
|
|
632
633
|
MAX(ts) AS last_active_ts,
|
|
633
634
|
COUNT(*) AS total_requests,
|
|
634
|
-
SUM(input_tokens + output_tokens
|
|
635
|
+
SUM(input_tokens + output_tokens
|
|
636
|
+
+ cache_creation_tokens + cache_read_tokens) AS total_tokens,
|
|
635
637
|
SUM(input_tokens) AS total_input,
|
|
636
638
|
SUM(output_tokens) AS total_output,
|
|
637
639
|
GROUP_CONCAT(DISTINCT model_served) AS models,
|
|
@@ -160,6 +160,8 @@ async def test_query_recent_sessions_basic(logger):
|
|
|
160
160
|
model_served="claude-sonnet",
|
|
161
161
|
input_tokens=100 * (i + 1),
|
|
162
162
|
output_tokens=50 * (i + 1),
|
|
163
|
+
cache_creation_tokens=10 * (i + 1),
|
|
164
|
+
cache_read_tokens=1000 * (i + 1),
|
|
163
165
|
session_key="session-alpha",
|
|
164
166
|
duration_ms=100 + i * 50,
|
|
165
167
|
)
|
|
@@ -186,9 +188,15 @@ async def test_query_recent_sessions_basic(logger):
|
|
|
186
188
|
|
|
187
189
|
alpha = next(s for s in sessions if s["session_key"] == "session-alpha")
|
|
188
190
|
assert alpha["total_requests"] == 3
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
191
|
+
expected_input = 100 + 200 + 300
|
|
192
|
+
expected_output = 50 + 100 + 150
|
|
193
|
+
expected_cache_creation = 10 + 20 + 30
|
|
194
|
+
expected_cache_read = 1000 + 2000 + 3000
|
|
195
|
+
assert alpha["total_tokens"] == (
|
|
196
|
+
expected_input + expected_output + expected_cache_creation + expected_cache_read
|
|
197
|
+
)
|
|
198
|
+
assert alpha["total_input"] == expected_input
|
|
199
|
+
assert alpha["total_output"] == expected_output
|
|
192
200
|
assert "claude-sonnet" in alpha["models"]
|
|
193
201
|
assert "anthropic" in alpha["vendors"]
|
|
194
202
|
assert alpha["success_rate"] == 100.0
|
|
@@ -269,12 +277,15 @@ async def test_query_session_profile_found(logger):
|
|
|
269
277
|
model_served="m",
|
|
270
278
|
input_tokens=100,
|
|
271
279
|
output_tokens=50,
|
|
280
|
+
cache_creation_tokens=20,
|
|
281
|
+
cache_read_tokens=400,
|
|
272
282
|
session_key="profile-test",
|
|
273
283
|
)
|
|
274
284
|
profile = await logger.query_session_profile("profile-test")
|
|
275
285
|
assert profile is not None
|
|
276
286
|
assert profile["session_key"] == "profile-test"
|
|
277
287
|
assert profile["total_requests"] == 1
|
|
288
|
+
assert profile["total_tokens"] == 100 + 50 + 20 + 400
|
|
278
289
|
|
|
279
290
|
|
|
280
291
|
@pytest.mark.asyncio
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/convert/anthropic_to_gemini.py
RENAMED
|
File without changes
|
{coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/convert/anthropic_to_openai.py
RENAMED
|
File without changes
|
{coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/convert/gemini_sse_adapter.py
RENAMED
|
File without changes
|
{coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/convert/gemini_to_anthropic.py
RENAMED
|
File without changes
|
{coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/convert/openai_to_anthropic.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/native_api/extractors/__init__.py
RENAMED
|
File without changes
|
{coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/native_api/extractors/anthropic.py
RENAMED
|
File without changes
|
{coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/native_api/extractors/gemini.py
RENAMED
|
File without changes
|
{coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/native_api/extractors/openai.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/streaming/anthropic_compat.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/vendors/copilot_token_manager.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|