coding-proxy 0.3.0a3__tar.gz → 0.3.1a2__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 (179) hide show
  1. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/AGENTS.md +2 -1
  2. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/CHANGELOG.md +29 -10
  3. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/PKG-INFO +9 -1
  4. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/README.md +8 -0
  5. coding_proxy-0.3.1a2/docs/issue.md +99 -0
  6. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/docs/zh-CN/README.md +8 -0
  7. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/pyproject.toml +1 -1
  8. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/config/config.default.yaml +3 -0
  9. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/convert/vendor_channels.py +281 -38
  10. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/routing/error_classifier.py +14 -0
  11. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/routing/executor.py +13 -11
  12. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/routing/model_mapper.py +0 -20
  13. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/routing/usage_parser.py +0 -30
  14. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/server/dashboard.py +5 -4
  15. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/tests/test_error_classifier.py +38 -0
  16. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/tests/test_model_mapper.py +0 -18
  17. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/tests/test_parse_usage.py +0 -62
  18. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/tests/test_router_executor.py +205 -15
  19. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/tests/test_vendor_channels.py +1047 -25
  20. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/uv.lock +1 -1
  21. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/.github/workflows/ci.yml +0 -0
  22. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/.github/workflows/coverage.yml +0 -0
  23. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/.github/workflows/release.yml +0 -0
  24. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/.gitignore +0 -0
  25. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/.pre-commit-config.yaml +0 -0
  26. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/CLAUDE.md +0 -0
  27. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/LICENSE +0 -0
  28. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/assets/dashboard-v0.2.4.png +0 -0
  29. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/docs/arch/config-reference.md +0 -0
  30. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/docs/arch/convert.md +0 -0
  31. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/docs/arch/design-patterns.md +0 -0
  32. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/docs/arch/routing.md +0 -0
  33. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/docs/arch/testing.md +0 -0
  34. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/docs/arch/vendors.md +0 -0
  35. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/docs/ci-cd.md +0 -0
  36. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/docs/framework.md +0 -0
  37. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/docs/guide/api-reference.md +0 -0
  38. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/docs/guide/cli-reference.md +0 -0
  39. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/docs/guide/dashboard.md +0 -0
  40. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/docs/guide/monitoring.md +0 -0
  41. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/docs/guide/quickstart.md +0 -0
  42. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/docs/guide/vendors.md +0 -0
  43. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/docs/user-guide.md +0 -0
  44. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/__init__.py +0 -0
  45. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/__init__.py +0 -0
  46. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/__main__.py +0 -0
  47. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/auth/__init__.py +0 -0
  48. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/auth/providers/__init__.py +0 -0
  49. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/auth/providers/base.py +0 -0
  50. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/auth/providers/github.py +0 -0
  51. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/auth/providers/google.py +0 -0
  52. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/auth/runtime.py +0 -0
  53. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/auth/store.py +0 -0
  54. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/cli/__init__.py +0 -0
  55. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/cli/auth_commands.py +0 -0
  56. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/cli/banner.py +0 -0
  57. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/compat/__init__.py +0 -0
  58. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/compat/canonical.py +0 -0
  59. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/compat/session_store.py +0 -0
  60. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/config/__init__.py +0 -0
  61. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/config/auth_schema.py +0 -0
  62. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/config/loader.py +0 -0
  63. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/config/resiliency.py +0 -0
  64. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/config/routing.py +0 -0
  65. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/config/schema.py +0 -0
  66. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/config/server.py +0 -0
  67. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/config/vendors.py +0 -0
  68. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/convert/__init__.py +0 -0
  69. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/convert/anthropic_to_gemini.py +0 -0
  70. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/convert/anthropic_to_openai.py +0 -0
  71. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/convert/gemini_sse_adapter.py +0 -0
  72. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/convert/gemini_to_anthropic.py +0 -0
  73. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/convert/openai_to_anthropic.py +0 -0
  74. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/logging/__init__.py +0 -0
  75. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/logging/db.py +0 -0
  76. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/logging/formatters.py +0 -0
  77. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/logging/stats.py +0 -0
  78. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/model/__init__.py +0 -0
  79. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/model/auth.py +0 -0
  80. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/model/compat.py +0 -0
  81. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/model/constants.py +0 -0
  82. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/model/pricing.py +0 -0
  83. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/model/token.py +0 -0
  84. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/model/vendor.py +0 -0
  85. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/native_api/__init__.py +0 -0
  86. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/native_api/config.py +0 -0
  87. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/native_api/extractors/__init__.py +0 -0
  88. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/native_api/extractors/anthropic.py +0 -0
  89. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/native_api/extractors/gemini.py +0 -0
  90. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/native_api/extractors/openai.py +0 -0
  91. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/native_api/handler.py +0 -0
  92. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/native_api/operation.py +0 -0
  93. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/native_api/routes.py +0 -0
  94. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/native_api/usage_registry.py +0 -0
  95. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/pricing.py +0 -0
  96. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/routing/__init__.py +0 -0
  97. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/routing/circuit_breaker.py +0 -0
  98. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/routing/quota_guard.py +0 -0
  99. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/routing/rate_limit.py +0 -0
  100. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/routing/retry.py +0 -0
  101. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/routing/router.py +0 -0
  102. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/routing/session_manager.py +0 -0
  103. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/routing/tier.py +0 -0
  104. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/routing/usage_recorder.py +0 -0
  105. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/server/__init__.py +0 -0
  106. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/server/app.py +0 -0
  107. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/server/factory.py +0 -0
  108. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/server/responses.py +0 -0
  109. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/server/routes.py +0 -0
  110. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/streaming/__init__.py +0 -0
  111. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/streaming/anthropic_compat.py +0 -0
  112. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/vendors/__init__.py +0 -0
  113. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/vendors/alibaba.py +0 -0
  114. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/vendors/anthropic.py +0 -0
  115. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/vendors/antigravity.py +0 -0
  116. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/vendors/base.py +0 -0
  117. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/vendors/copilot.py +0 -0
  118. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/vendors/copilot_models.py +0 -0
  119. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/vendors/copilot_token_manager.py +0 -0
  120. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/vendors/copilot_urls.py +0 -0
  121. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/vendors/doubao.py +0 -0
  122. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/vendors/kimi.py +0 -0
  123. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/vendors/minimax.py +0 -0
  124. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/vendors/mixins.py +0 -0
  125. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/vendors/native_anthropic.py +0 -0
  126. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/vendors/token_manager.py +0 -0
  127. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/vendors/xiaomi.py +0 -0
  128. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/src/coding/proxy/vendors/zhipu.py +0 -0
  129. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/tests/__init__.py +0 -0
  130. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/tests/test_antigravity.py +0 -0
  131. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/tests/test_app_routes.py +0 -0
  132. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/tests/test_auto_login.py +0 -0
  133. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/tests/test_banner.py +0 -0
  134. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/tests/test_circuit_breaker.py +0 -0
  135. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/tests/test_cli_usage.py +0 -0
  136. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/tests/test_compat.py +0 -0
  137. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/tests/test_config_init.py +0 -0
  138. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/tests/test_config_loader.py +0 -0
  139. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/tests/test_convert_request.py +0 -0
  140. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/tests/test_convert_response.py +0 -0
  141. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/tests/test_convert_sse.py +0 -0
  142. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/tests/test_copilot.py +0 -0
  143. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/tests/test_copilot_convert_request.py +0 -0
  144. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/tests/test_copilot_convert_response.py +0 -0
  145. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/tests/test_copilot_models.py +0 -0
  146. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/tests/test_copilot_urls.py +0 -0
  147. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/tests/test_currency.py +0 -0
  148. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/tests/test_logging_dual_write.py +0 -0
  149. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/tests/test_mixins.py +0 -0
  150. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/tests/test_model_auth.py +0 -0
  151. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/tests/test_model_compat.py +0 -0
  152. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/tests/test_model_constants.py +0 -0
  153. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/tests/test_model_pricing.py +0 -0
  154. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/tests/test_model_token.py +0 -0
  155. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/tests/test_model_vendor.py +0 -0
  156. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/tests/test_native_api_base_url_override.py +0 -0
  157. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/tests/test_native_api_extractors.py +0 -0
  158. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/tests/test_native_api_handler.py +0 -0
  159. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/tests/test_native_api_operation.py +0 -0
  160. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/tests/test_native_api_routes.py +0 -0
  161. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/tests/test_native_vendors.py +0 -0
  162. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/tests/test_parse_usage_gemini.py +0 -0
  163. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/tests/test_pricing.py +0 -0
  164. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/tests/test_quota_guard.py +0 -0
  165. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/tests/test_rate_limit.py +0 -0
  166. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/tests/test_router_chain.py +0 -0
  167. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/tests/test_runtime_reauth.py +0 -0
  168. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/tests/test_schema.py +0 -0
  169. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/tests/test_streaming_anthropic_compat.py +0 -0
  170. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/tests/test_tier.py +0 -0
  171. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/tests/test_tiers_config.py +0 -0
  172. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/tests/test_time_range.py +0 -0
  173. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/tests/test_token_logger.py +0 -0
  174. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/tests/test_token_logger_native_columns.py +0 -0
  175. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/tests/test_token_manager.py +0 -0
  176. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/tests/test_types.py +0 -0
  177. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/tests/test_vendor_streaming.py +0 -0
  178. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/tests/test_vendors.py +0 -0
  179. {coding_proxy-0.3.0a3 → coding_proxy-0.3.1a2}/tests/test_zhipu.py +0 -0
@@ -47,10 +47,11 @@
47
47
  3. **Link Validity**: 确保所有引用的 URL 可访问且具备明确的上下文价值;
48
48
  4. **Git Commit**: 在需要提交变更到 Git 时,一律使用 Shell 调用 Claude Code 的自定义 Slash Command: `/commit` 进行 git commit 操作(若环境中未安装 Claude Code,则直接读取 `~/.claude/commands/commit.md`,按照其中的规则进行 git commit 操作)。不要执行 Rebase。
49
49
  5. **Pre-commit Hooks**: 克隆仓库后执行 `uv run pre-commit install` 激活本地 Git hooks,使 Ruff lint(含 auto-fix)、Ruff format 及通用代码卫生检查在每次 commit 前自动运行。若 hooks 自动修复了问题,提交会被中断,执行 `git add -p` 审阅修复内容后重新提交即可。
50
+ 6. **Issue**: 在 docs/issue.md 中维护你处理过的 Issue 摘要(问题描述、表因根因、处理方式、后续防范、同类问题影响与处理注意实现等),便于同类问题的跨上下文处理;注意识别相同 Issue,不要同 Issue 多处维护。
50
51
  - **Package Management Standardization (包管理规范)**:
51
52
  1. **Python**: 严禁使用 pip/poetry,**必须**统一使用 `uv` 进行包管理与脚本执行(如 `uv run`);
52
53
  2. **JavaScript/TypeScript**: 严禁使用 npm/yarn,**必须**统一使用 `pnpm` 进行包管理与脚本执行。
53
- - **Database Management**: 谨慎操作,数据迁移、测试等操作严禁将现有数据删除。
54
+ - **Database Management**: 谨慎操作,数据迁移、测试等操作严禁将现有数据删除,谨慎操作数据迁移的回滚,防止数据被清理。
54
55
 
55
56
  ## Documentation Standards (文档规范)
56
57
 
@@ -4,16 +4,35 @@
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
- - feat(server): 默认监听端口 `8046` `3392`,避免与常见企业端口段冲突;BREAKING: 已将端口固化进客户端 `ANTHROPIC_BASE_URL` / SDK `base_url` / 监控看板 URL 的用户需同步更新,或显式通过 `--port 8046` / `server.port: 8046` 回退到旧值;
8
- - feat(native-api): 原生 API 透传三家 provider (`openai` / `gemini` / `anthropic`) `enabled` 默认由 `false` `true` 开箱即用;`config.default.yaml` 顶层追加 `native_api:` 实体配置块(首次启动自动拷贝至 `~/.coding-proxy/config.yaml`,用户直接编辑 `base_url` 即可将上游切换至第三方代理);同时新增 `NATIVE_OPENAI_BASE_URL` / `NATIVE_GEMINI_BASE_URL` / `NATIVE_ANTHROPIC_BASE_URL` 三枚环境变量覆写通道(空串/纯空白视作未设置),三级优先级 **env > yaml > 内置默认** 由 `NativeApiConfig._apply_env_overrides` `@model_validator(mode="after")` 统一注入;BREAKING: 升级后 `/api/{openai,gemini,anthropic}/**` 默认暴露,proxy 仍不保管凭据(`Authorization` / `x-api-key` / `?key=` 均由客户端透传),如需关闭显式设置 `native_api.<provider>.enabled: false`;
9
- - feat(native-api): 新增 `/api/{openai,gemini,anthropic}/**` 原生 LLM API 全量 catch-all 透传通道——客户端只需改 SDK `base_url` 即可复用 proxy 链路访问 OpenAI / Gemini / Anthropic 官方 API,认证完全透传不保管凭据;核心由 `NativeProxyHandler` + `OperationClassifier` + `NativeUsageExtractor` Registry 三件套组成,与既有 `/v1/messages` Claude Code 链路正交共存、零回归;首版覆盖 chat / completions / responses / embeddings / audio / image / count_tokens / moderations / cachedContents / messages / batches 等全量端点;
10
- - feat(usage): `usage_log` 新增 `client_category` / `operation` / `endpoint` / `extra_usage_json` 四列(全部 `DEFAULT`、幂等迁移),区分 Claude Code 场景(`'cc'`)与原生 API 场景(`'api'`),承载规范化操作名与非规范 token 字段(reasoning / audio / thoughts / server_tool_use 等);`query_usage` 支持按新列过滤,`_PERIOD_SQL` 聚合追加 `client_category, operation` 维度;
11
- - feat(usage-parser): `parse_usage_from_chunk` 扩展识别 Gemini SSE `usageMetadata.*`(promptTokenCount / candidatesTokenCount / cachedContentTokenCount / thoughtsTokenCount / toolUsePromptTokenCount),新增 `gemini_usage_metadata` evidence kind,既有 Anthropic/OpenAI 分支行为零变更;
12
- - refactor(vendor-channels): 彻底收敛跨供应商兼容性逻辑——删除 `server/request_normalizer.py` 入口通用规范化层,将 `srvtoolu_*` ID 重写、`server_tool_use_delta` 私有块剥离全部迁入源→目标绑定通道(`prepare_zhipu_to_anthropic`、`prepare_zhipu_to_copilot`);新增 `infer_source_vendor_from_body` 内容感知源推断,在无会话状态的首次请求场景下兜底识别源供应商;`_RouteExecutor._determine_source_vendor` 扩充为三级优先级(failed_tier → session_state → body inference),确保未注册转换对不触发任何清洗;
13
- - refactor(count-tokens): `/v1/messages/count_tokens` 端点移除无条件 `strip_thinking_blocks` 过度防御,改为基于 `infer_source_vendor_from_body` + `get_transition_channel` 的按需通道清洗,语义与 `/v1/messages` 对齐;
14
- - fix(request-normalizer): 重设计 zhipu→anthropic 跨供应商 tool_use/tool_result 配对修复——以单遍自包含 `enforce_anthropic_tool_pairing` 替代原有多步串联管线(剥离→重定位→孤儿修复),消除步骤间隐式依赖导致的孤儿 tool_use 漏修问题,彻底根治 `tool_use ids were found without tool_result blocks` 400 异常;
15
- - refactor(vendor-channels): 将供应商转换通道从「目标 vendor 专属」重构为「源→目标绑定」模型——注册表键从 `target_vendor` 改为 `(source, target)` 二元组,通道函数从 `prepare_for_X` 重命名为 `prepare_X_to_Y`,触发逻辑从 `_needs_vendor_channel` 替换为 `_determine_source_vendor`(基于请求内 `failed_tier_name` 和会话历史推断源 vendor),未注册的转换对(如 anthropic→zhipu)不触发任何通道;
16
- - feat(vendor-channels): 新增 zhipu→anthropic、zhipu→copilot、copilot→zhipu 三条源→目标绑定转换通道,在跨供应商故障转移时自动清理源 vendor 产物(thinking 块、cache_control 字段、thinking 参数、tool_use/tool_result 配对),消除 `likely format incompatibility (400 + tool_results)` 错误;
7
+ - fix(vendor-channels): 新增 zhipu vendor 自清理通道,修复 GLM-5 自循环 400 + tool_results 偶发降级;
8
+ - fix(vendor-channels): 修复 `_rewrite_srvtoolu_ids` 块顺序敏感性导致 inline tool_result 漏改名,进而 enforce 阶段 dict key tool_use_ids 错位、anthropic `tool_use ids without tool_result blocks immediately after` cascade failover 问题(改为两遍扫描:先收集 id_map,再统一改写所有 tool_result.tool_use_id 引用);
9
+ - fix(vendor-channels): `enforce_anthropic_tool_pairing` 增加全局 sanity check pass,主循环边角错位让 dangling tool_use 漏过校验时兜底合成 is_error 占位并打 `pairing_sanity_repaired` 标签,避免 anthropic 二次报错;
10
+
11
+ ### Bug Fixes
12
+
13
+ - fix(vendor-channels): 新增 `anthropic zhipu` 跨供应商转换通道,修复 Anthropic beta 功能(web search, computer use)产生的 `server_tool_use` 块导致 zhipu 400 错误的问题;
14
+ - fix(error-classifier): 增强语义拒绝检测,识别 zhipu 等供应商返回的中文错误消息(如「API 调用参数有误」code=1210),确保正确触发故障转移;
15
+ - fix(vendor-channels): `_remove_vendor_blocks` 增加空内容占位保护,防止内容块全部剥离后消息结构不合法。
16
+
17
+ ## [v0.3.0](https://github.com/ThreeFish-AI/coding-proxy/releases/tag/v0.3.0) — 2026-04-20
18
+
19
+ > [!IMPORTANT]
20
+ >
21
+ > **🚀 OpenAI、Anthropic、Gemini 原生 API 进驻 Coding Proxy!**
22
+ >
23
+ > 服务对象不在局限 Claude Code,凡兼容 OpenAI、Anthropic、Gemini 三巨头 API 协议的客户端,出口 LLM 流量可统一收敛到 Coding Proxy。
24
+
25
+ ### ✨ 核心亮点
26
+
27
+ - feat(native-api): 新增 `/api/{openai,gemini,anthropic}/**` 原生 LLM API 全量 catch-all 透传通道;
28
+ - feat(dashboard): 新增实时 Web Dashboard 页面,聚合展示流量与用量统计;
29
+ - feat(usage): `usage` 区分 Claude Code 场景(`'cc'`)与原生 API 场景(`'api'`);
30
+ - refactor(vendor-channels): 将供应商转换通道从目标专属重构为源→目标绑定模型;
31
+ - docs(user-guide): 补充 POST /v1/messages 完整 API 参考文档;
32
+
33
+ ### 🔧 更多特性
34
+
35
+ - feat(server): 默认监听端口 `8046` → `3392`,规范化 [Negentropy](https://github.com/ThreeFish-AI/negentropy) 体系端口;
17
36
 
18
37
  ## [v0.2.3](https://github.com/ThreeFish-AI/coding-proxy/releases/tag/v0.2.3) — 2026-04-16
19
38
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: coding-proxy
3
- Version: 0.3.0a3
3
+ Version: 0.3.1a2
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
@@ -113,6 +113,14 @@ export ANTHROPIC_BASE_URL=http://127.0.0.1:3392
113
113
  claude
114
114
  ```
115
115
 
116
+ ### 5. Peek at the Dashboard
117
+
118
+ Curious about your real-time token spend, latency, and circuit breaker pulse? Pop open your browser and head to:
119
+
120
+ ```bash
121
+ open http://127.0.0.1:3392/dashboard
122
+ ```
123
+
116
124
  ---
117
125
 
118
126
  ## 🛠️ The CLI Console Guide
@@ -86,6 +86,14 @@ export ANTHROPIC_BASE_URL=http://127.0.0.1:3392
86
86
  claude
87
87
  ```
88
88
 
89
+ ### 5. Peek at the Dashboard
90
+
91
+ Curious about your real-time token spend, latency, and circuit breaker pulse? Pop open your browser and head to:
92
+
93
+ ```bash
94
+ open http://127.0.0.1:3392/dashboard
95
+ ```
96
+
89
97
  ---
90
98
 
91
99
  ## 🛠️ The CLI Console Guide
@@ -0,0 +1,99 @@
1
+ # Issue 处理档案
2
+
3
+ > 维护已处理过的 Issue 摘要(问题描述、表因根因、处理方式、后续防范、同类问题影响与处理注意事项),便于同类问题的跨上下文处理。识别相同 Issue 时应在原条目追加复盘,避免同 Issue 多处维护。
4
+
5
+ ---
6
+
7
+ ## zhipu 自循环 400 + tool_results 偶发降级
8
+
9
+ **问题描述**
10
+
11
+ 生产日志反复出现下述链路: 请求一开始命中 zhipu 主 tier, 但在含 `tool_results` 的多轮工具调用场景下偶发返回 400, 触发到 copilot 二级 tier。具体日志特征:
12
+
13
+ ```
14
+ WARNING Tier zhipu likely format incompatibility (400 + tool_results), trying next tier without recording failure
15
+ WARNING Tier zhipu semantic rejection (400), trying next tier without recording failure
16
+ DEBUG Applied transition channel zhipu → copilot: rewritten_38_srvtoolu_ids, stripped_16_thinking_blocks, removed_3_cache_control_fields, misplaced_tool_result_relocated
17
+ ```
18
+
19
+ zhipu → copilot 通道的 adaptations 列表暴露了上一轮 zhipu 响应中存在的非标准产物 (`srvtoolu_*` ID、自签 thinking、错位的 `tool_result`)。
20
+
21
+ **表因**
22
+
23
+ zhipu 自身偶发返回 400, 但错误体非 JSON 结构, 由 `_is_likely_request_format_error()` 判定为「格式不兼容」并跳过当前 tier。
24
+
25
+ **根因**
26
+
27
+ 1. zhipu 是 `NativeAnthropicVendor` 薄透传供应商, **不做任何请求体预处理**。
28
+ 2. `executor._determine_source_vendor` 三条优先级路径均以 `source != target_name` 过滤掉了同 vendor 自转换。
29
+ 3. `VENDOR_TRANSITIONS` 注册表中无 `("zhipu", "zhipu")` 条目。
30
+
31
+ 后果: GLM-5 偶发产出非标准产物 (assistant 内联 `tool_result`、`server_tool_use_delta` 流式残块) 后, Claude Code 把这些产物原样回送下一轮请求时, **没有任何清洗发生**, 直接被转发到 zhipu 自身, 命中 zhipu 端的输入校验返回 400。
32
+
33
+ **处理方式**
34
+
35
+ - 在 `vendor_channels.py` 新增 `prepare_zhipu_self_cleanup` 函数, 仅修复 zhipu 自身拒绝的两类产物:
36
+ 1. 剥离 `server_tool_use_delta` 流式残块
37
+ 2. `enforce_anthropic_tool_pairing` 把 assistant 内联 `tool_result` 重定位到紧随 user 消息
38
+ - 显式 **保留** zhipu 原生支持的特性: `srvtoolu_*` ID、`server_tool_use` 类型、自签 thinking signature、`cache_control` (cache_read 已在生产实证)、顶层 `thinking` 参数。
39
+ - 在 `VENDOR_TRANSITIONS` 注册 `("zhipu", "zhipu") = prepare_zhipu_self_cleanup`。
40
+ - 在 `executor._determine_source_vendor` 三条优先级路径中, 把「`source != target`」过滤替换为「通道已注册」门控 (`get_transition_channel(...) is not None`), 让自转换通道在显式注册时启用, 未注册时退化为原行为。
41
+
42
+ **后续防范**
43
+
44
+ - 新增 `NativeAnthropicVendor` 子类 (minimax / kimi / doubao / xiaomi / alibaba 等) 时, 若上游 vendor 偶发产出违反 Anthropic 规范的产物, 可按需注册同名自清理通道, executor 无需任何额外改动。
45
+ - 同 vendor 自转换通道应**精确剪裁**: 仅修复 vendor 自身拒绝的产物, 不要套用跨 vendor 通道的全量清理 (会误伤 vendor 原生支持的特性, 如 cache_control 损失带来 cache_read miss)。
46
+
47
+ **同类问题影响与处理注意事项**
48
+
49
+ - `enforce_anthropic_tool_pairing` 仅识别 `tool_use` 类型 (不含 `server_tool_use`), 因为 `server_tool_use` 由 vendor 自身执行, 不需要客户端 `tool_result`。构造测试或类似清洗逻辑时需注意此差别。
50
+ - `_is_likely_request_format_error()` 把「400 + tool_results + 非结构化错误体」一律标记为格式不兼容并跳过 tier 不计熔断器, 这层兜底虽能维持可用性但会**掩盖** vendor 自身的间歇性问题, 让根因更难发现。处理类似 400 偶发时, 应优先看 `Applied transition channel` 日志中的 adaptations 列表, 它能精确暴露上游响应中的非标准产物。
51
+
52
+ ---
53
+
54
+ ## anthropic 报 messages.X tool_use 缺 tool_result (zhipu→anthropic 故障转移失败)
55
+
56
+ **问题描述**
57
+
58
+ zhipu 完成响应后, executor 故障转移至 anthropic 时反复失败 (HTTP 400):
59
+
60
+ ```
61
+ DEBUG Applied transition channel zhipu → anthropic: rewritten_86_srvtoolu_ids, misplaced_tool_result_relocated, stripped_18_thinking_blocks
62
+ WARNING anthropic stream error: status=400 ... messages.3: `tool_use` ids were found without `tool_result` blocks immediately after: toolu_normalized_3.
63
+ INFO Failover: anthropic → zhipu (reason: HTTP 400)
64
+ ```
65
+
66
+ adaptations 列表显示 `misplaced_tool_result_relocated` 但**没有** `orphaned_tool_use_repaired`, 即 enforce 单遍扫描视角下认为所有 tool_use 都已配对; 但 anthropic 仍报 messages.X 缺 tool_result, 导致请求级 cascade failover 反复回到 zhipu。
67
+
68
+ **表因**
69
+
70
+ `prepare_zhipu_to_anthropic` 链路输出的请求体中, 某个 assistant 的 `tool_use` 在紧邻的 user 消息中没有匹配的 `tool_result` 块。
71
+
72
+ **根因**
73
+
74
+ `_rewrite_srvtoolu_ids` 采用单遍正向扫描: 在同一次循环中一边收集 srvtoolu_* → toolu_normalized_* 的 id_map, 一边改写遇到的 `tool_result.tool_use_id`。GLM-5 流式偶发将 inline tool_result 输出在本消息 `server_tool_use` 之前 (block 顺序异常), 导致:
75
+
76
+ 1. 处理 inline tool_result 时, id_map 尚未填入对应 srvtoolu_* → 漏改名, inline 仍保留 `srvtoolu_X`
77
+ 2. 处理本消息 server_tool_use 时, 填入 id_map 并把 tool_use 改名为 `toolu_normalized_X`
78
+ 3. 进入 `enforce_anthropic_tool_pairing` 时:
79
+ - A 步 extracted dict key = `srvtoolu_X` (inline 保留的旧 ID)
80
+ - B 步 tool_use_ids = `[toolu_normalized_X]` (已改名)
81
+ - F 步 `uid in extracted` 检查失败 (key 错位), 但若 next user 已含其他 stale tool_result 让 existing_result_ids "巧合" 命中, F 步会跳过 synth → 不触发 orphan 标签
82
+ - 最终 anthropic 看到 messages.X 真的缺 toolu_normalized_X 的 tool_result → 400
83
+
84
+ **处理方式**
85
+
86
+ - `_rewrite_srvtoolu_ids` 改为**两遍扫描**: Pass 1 仅遍历 assistant 消息, 收集 id_map 并改写 tool_use 自身的 id 与 type; Pass 2 全量遍历所有消息 (含 user / 异常 assistant 内联), 统一改写所有 `tool_result.tool_use_id` 引用。彻底消除 block 顺序敏感性。
87
+ - `enforce_anthropic_tool_pairing` 主循环结束后追加**全局 sanity check pass**: 重新遍历每条 assistant, 验证其 tool_use_ids 全部在 next user 的 tool_result 中存在; 发现遗漏直接合成 is_error 占位并打 `pairing_sanity_repaired` 标签。作为防御深度抵御未来其他主循环边角错位。
88
+ - A 步对 `tool_use_id` 缺失的破损 inline tool_result 也计入 relocated_count (避免 silent drop 影响 adaptations 标签可观测性)。
89
+
90
+ **后续防范**
91
+
92
+ - 任何"按出现顺序填充字典 + 同遍引用查询"的两阶段操作都应警惕**顺序耦合**问题。两遍扫描 (collect → apply) 是消除此类 bug 的标准 pattern。
93
+ - 关键校验函数应有**主循环 + 全局 sanity check** 的双层结构, 单层校验在边角场景下容易被绕过。
94
+ - 处理 anthropic `tool_use ids without tool_result blocks immediately after` 类 cascade failover 时, **adaptations 标签能否复现日志**是定位 root cause 的强信号: 若 enforce 视角与 anthropic 视角不一致 (有 misplaced 但无 orphan, anthropic 仍报错), 必有上游 _rewrite / id 改写阶段的隐藏漏洞。
95
+
96
+ **同类问题影响与处理注意事项**
97
+
98
+ - 任何对 messages 进行 ID 重写的转换链 (如 `_rewrite_srvtoolu_ids`、`anthropic_to_openai`、`anthropic_to_gemini`) 都应使用两遍扫描或一次性收集后再批量改写, 以保证 block 顺序无关性。
99
+ - enforce 类校验函数若依赖 dict key 与 list 元素的**等同性**, 必须先确保两者在同一参考系下 (改名前 vs 改名后); 否则错位会以 "看起来 OK 实际有漏" 的方式静默泄漏到下游。
@@ -86,6 +86,14 @@ export ANTHROPIC_BASE_URL=http://127.0.0.1:3392
86
86
  claude
87
87
  ```
88
88
 
89
+ ### 5. 打开监控看板
90
+
91
+ 想实时观测 Token 消耗、延迟以及各层熔断状态?在浏览器中打开:
92
+
93
+ ```bash
94
+ open http://127.0.0.1:3392/dashboard
95
+ ```
96
+
89
97
  ---
90
98
 
91
99
  ## 🛠️ CLI 控制台指南
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "coding-proxy"
3
- version = "0.3.0a3"
3
+ version = "0.3.1a2"
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"
@@ -485,6 +485,9 @@ pricing:
485
485
  - vendor: gemini
486
486
  model: text-embedding-004
487
487
  input_cost_per_mtok: $0.10
488
+ - vendor: gemini
489
+ model: text-embedding-005
490
+ input_cost_per_mtok: $0.10
488
491
  # ── Google Antigravity(参照 Anthropic 定价估算) ──
489
492
  - vendor: antigravity
490
493
  model: claude-opus-4-6-thinking