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.
Files changed (190) hide show
  1. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/PKG-INFO +1 -1
  2. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/docs/issue.md +44 -0
  3. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/pyproject.toml +1 -1
  4. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/logging/db.py +4 -2
  5. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_session_aware.py +14 -3
  6. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/uv.lock +1 -1
  7. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/.github/workflows/ci.yml +0 -0
  8. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/.github/workflows/coverage.yml +0 -0
  9. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/.github/workflows/release.yml +0 -0
  10. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/.gitignore +0 -0
  11. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/.pre-commit-config.yaml +0 -0
  12. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/AGENTS.md +0 -0
  13. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/CHANGELOG.md +0 -0
  14. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/CLAUDE.md +0 -0
  15. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/LICENSE +0 -0
  16. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/README.md +0 -0
  17. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/assets/dashboard-v0.4.0.png +0 -0
  18. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/assets/session-v0.4.0.png +0 -0
  19. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/docs/agents/knowledge-map.md +0 -0
  20. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/docs/agents/reference-specifications.md +0 -0
  21. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/docs/arch/config-reference.md +0 -0
  22. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/docs/arch/convert.md +0 -0
  23. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/docs/arch/design-patterns.md +0 -0
  24. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/docs/arch/routing.md +0 -0
  25. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/docs/arch/testing.md +0 -0
  26. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/docs/arch/vendors.md +0 -0
  27. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/docs/ci-cd.md +0 -0
  28. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/docs/framework.md +0 -0
  29. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/docs/guide/api-reference.md +0 -0
  30. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/docs/guide/cli-reference.md +0 -0
  31. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/docs/guide/dashboard.md +0 -0
  32. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/docs/guide/monitoring.md +0 -0
  33. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/docs/guide/quickstart.md +0 -0
  34. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/docs/guide/vendors.md +0 -0
  35. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/docs/user-guide.md +0 -0
  36. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/docs/zh-CN/README.md +0 -0
  37. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/__init__.py +0 -0
  38. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/__init__.py +0 -0
  39. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/__main__.py +0 -0
  40. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/auth/__init__.py +0 -0
  41. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/auth/providers/__init__.py +0 -0
  42. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/auth/providers/base.py +0 -0
  43. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/auth/providers/github.py +0 -0
  44. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/auth/providers/google.py +0 -0
  45. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/auth/runtime.py +0 -0
  46. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/auth/store.py +0 -0
  47. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/cli/__init__.py +0 -0
  48. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/cli/auth_commands.py +0 -0
  49. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/cli/banner.py +0 -0
  50. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/compat/__init__.py +0 -0
  51. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/compat/canonical.py +0 -0
  52. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/compat/session_store.py +0 -0
  53. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/config/__init__.py +0 -0
  54. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/config/auth_schema.py +0 -0
  55. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/config/config.default.yaml +0 -0
  56. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/config/loader.py +0 -0
  57. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/config/resiliency.py +0 -0
  58. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/config/routing.py +0 -0
  59. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/config/schema.py +0 -0
  60. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/config/server.py +0 -0
  61. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/config/session_policy.py +0 -0
  62. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/config/vendors.py +0 -0
  63. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/convert/__init__.py +0 -0
  64. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/convert/anthropic_to_gemini.py +0 -0
  65. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/convert/anthropic_to_openai.py +0 -0
  66. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/convert/gemini_sse_adapter.py +0 -0
  67. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/convert/gemini_to_anthropic.py +0 -0
  68. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/convert/openai_to_anthropic.py +0 -0
  69. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/convert/vendor_channels.py +0 -0
  70. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/logging/__init__.py +0 -0
  71. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/logging/formatters.py +0 -0
  72. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/logging/stats.py +0 -0
  73. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/model/__init__.py +0 -0
  74. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/model/auth.py +0 -0
  75. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/model/compat.py +0 -0
  76. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/model/constants.py +0 -0
  77. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/model/pricing.py +0 -0
  78. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/model/token.py +0 -0
  79. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/model/vendor.py +0 -0
  80. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/native_api/__init__.py +0 -0
  81. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/native_api/config.py +0 -0
  82. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/native_api/extractors/__init__.py +0 -0
  83. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/native_api/extractors/anthropic.py +0 -0
  84. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/native_api/extractors/gemini.py +0 -0
  85. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/native_api/extractors/openai.py +0 -0
  86. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/native_api/handler.py +0 -0
  87. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/native_api/operation.py +0 -0
  88. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/native_api/routes.py +0 -0
  89. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/native_api/usage_registry.py +0 -0
  90. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/pricing.py +0 -0
  91. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/routing/__init__.py +0 -0
  92. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/routing/circuit_breaker.py +0 -0
  93. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/routing/error_classifier.py +0 -0
  94. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/routing/executor.py +0 -0
  95. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/routing/model_mapper.py +0 -0
  96. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/routing/quota_guard.py +0 -0
  97. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/routing/rate_limit.py +0 -0
  98. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/routing/retry.py +0 -0
  99. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/routing/router.py +0 -0
  100. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/routing/session_manager.py +0 -0
  101. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/routing/session_policy.py +0 -0
  102. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/routing/tier.py +0 -0
  103. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/routing/usage_parser.py +0 -0
  104. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/routing/usage_recorder.py +0 -0
  105. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/server/__init__.py +0 -0
  106. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/server/app.py +0 -0
  107. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/server/dashboard.py +0 -0
  108. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/server/factory.py +0 -0
  109. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/server/responses.py +0 -0
  110. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/server/routes.py +0 -0
  111. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/streaming/__init__.py +0 -0
  112. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/streaming/anthropic_compat.py +0 -0
  113. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/vendors/__init__.py +0 -0
  114. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/vendors/alibaba.py +0 -0
  115. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/vendors/anthropic.py +0 -0
  116. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/vendors/antigravity.py +0 -0
  117. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/vendors/base.py +0 -0
  118. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/vendors/copilot.py +0 -0
  119. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/vendors/copilot_models.py +0 -0
  120. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/vendors/copilot_token_manager.py +0 -0
  121. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/vendors/copilot_urls.py +0 -0
  122. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/vendors/doubao.py +0 -0
  123. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/vendors/kimi.py +0 -0
  124. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/vendors/minimax.py +0 -0
  125. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/vendors/mixins.py +0 -0
  126. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/vendors/native_anthropic.py +0 -0
  127. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/vendors/token_manager.py +0 -0
  128. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/vendors/xiaomi.py +0 -0
  129. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/src/coding/proxy/vendors/zhipu.py +0 -0
  130. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/__init__.py +0 -0
  131. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/e2e/__init__.py +0 -0
  132. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/e2e/conftest.py +0 -0
  133. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/e2e/test_e2e_http.py +0 -0
  134. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/e2e/test_e2e_token.py +0 -0
  135. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/e2e/test_e2e_vendor.py +0 -0
  136. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_antigravity.py +0 -0
  137. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_app_routes.py +0 -0
  138. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_auto_login.py +0 -0
  139. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_banner.py +0 -0
  140. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_circuit_breaker.py +0 -0
  141. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_cli_usage.py +0 -0
  142. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_compat.py +0 -0
  143. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_config_init.py +0 -0
  144. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_config_loader.py +0 -0
  145. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_convert_request.py +0 -0
  146. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_convert_response.py +0 -0
  147. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_convert_sse.py +0 -0
  148. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_copilot.py +0 -0
  149. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_copilot_convert_request.py +0 -0
  150. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_copilot_convert_response.py +0 -0
  151. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_copilot_models.py +0 -0
  152. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_copilot_urls.py +0 -0
  153. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_currency.py +0 -0
  154. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_error_classifier.py +0 -0
  155. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_logging_dual_write.py +0 -0
  156. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_mixins.py +0 -0
  157. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_model_auth.py +0 -0
  158. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_model_compat.py +0 -0
  159. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_model_constants.py +0 -0
  160. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_model_mapper.py +0 -0
  161. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_model_pricing.py +0 -0
  162. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_model_token.py +0 -0
  163. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_model_vendor.py +0 -0
  164. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_native_api_base_url_override.py +0 -0
  165. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_native_api_extractors.py +0 -0
  166. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_native_api_handler.py +0 -0
  167. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_native_api_operation.py +0 -0
  168. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_native_api_routes.py +0 -0
  169. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_native_vendors.py +0 -0
  170. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_parse_usage.py +0 -0
  171. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_parse_usage_gemini.py +0 -0
  172. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_pricing.py +0 -0
  173. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_quota_guard.py +0 -0
  174. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_rate_limit.py +0 -0
  175. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_router_chain.py +0 -0
  176. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_router_executor.py +0 -0
  177. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_runtime_reauth.py +0 -0
  178. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_schema.py +0 -0
  179. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_streaming_anthropic_compat.py +0 -0
  180. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_tier.py +0 -0
  181. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_tiers_config.py +0 -0
  182. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_time_range.py +0 -0
  183. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_token_logger.py +0 -0
  184. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_token_logger_native_columns.py +0 -0
  185. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_token_manager.py +0 -0
  186. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_types.py +0 -0
  187. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_vendor_channels.py +0 -0
  188. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_vendor_streaming.py +0 -0
  189. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a4}/tests/test_vendors.py +0 -0
  190. {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.1a3
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.1a3"
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) AS total_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) AS total_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
- assert alpha["total_tokens"] == (100 + 200 + 300) + (50 + 100 + 150)
190
- assert alpha["total_input"] == 100 + 200 + 300
191
- assert alpha["total_output"] == 50 + 100 + 150
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
@@ -74,7 +74,7 @@ wheels = [
74
74
 
75
75
  [[package]]
76
76
  name = "coding-proxy"
77
- version = "0.4.1a3"
77
+ version = "0.4.1a4"
78
78
  source = { editable = "." }
79
79
  dependencies = [
80
80
  { name = "aiosqlite" },
File without changes
File without changes
File without changes
File without changes