coding-proxy 0.4.1a3__tar.gz → 0.4.1a5__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 (194) hide show
  1. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/AGENTS.md +8 -6
  2. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/PKG-INFO +1 -1
  3. coding_proxy-0.4.1a5/docs/agents/browser-validation.md +172 -0
  4. {coding_proxy-0.4.1a3/docs → coding_proxy-0.4.1a5/docs/agents}/issue.md +44 -0
  5. coding_proxy-0.4.1a5/docs/agents/knowledge-map.md +95 -0
  6. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/docs/arch/vendors.md +1 -1
  7. {coding_proxy-0.4.1a3/docs → coding_proxy-0.4.1a5/docs/ops}/ci-cd.md +6 -6
  8. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/pyproject.toml +1 -1
  9. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/convert/vendor_channels.py +55 -16
  10. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/logging/db.py +4 -2
  11. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/routing/executor.py +3 -1
  12. coding_proxy-0.4.1a5/src/coding/proxy/vendors/zhipu.py +188 -0
  13. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/tests/test_session_aware.py +14 -3
  14. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/tests/test_vendor_channels.py +78 -0
  15. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/tests/test_vendors.py +2 -2
  16. coding_proxy-0.4.1a5/tests/test_zhipu.py +627 -0
  17. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/uv.lock +1 -1
  18. coding_proxy-0.4.1a3/docs/agents/knowledge-map.md +0 -3
  19. coding_proxy-0.4.1a3/src/coding/proxy/vendors/zhipu.py +0 -36
  20. coding_proxy-0.4.1a3/tests/test_zhipu.py +0 -294
  21. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/.github/workflows/ci.yml +0 -0
  22. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/.github/workflows/coverage.yml +0 -0
  23. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/.github/workflows/release.yml +0 -0
  24. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/.gitignore +0 -0
  25. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/.pre-commit-config.yaml +0 -0
  26. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/CHANGELOG.md +0 -0
  27. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/CLAUDE.md +0 -0
  28. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/LICENSE +0 -0
  29. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/README.md +0 -0
  30. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/assets/dashboard-v0.4.0.png +0 -0
  31. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/assets/session-v0.4.0.png +0 -0
  32. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/docs/agents/reference-specifications.md +0 -0
  33. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/docs/arch/config-reference.md +0 -0
  34. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/docs/arch/convert.md +0 -0
  35. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/docs/arch/design-patterns.md +0 -0
  36. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/docs/arch/routing.md +0 -0
  37. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/docs/arch/testing.md +0 -0
  38. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/docs/framework.md +0 -0
  39. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/docs/guide/api-reference.md +0 -0
  40. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/docs/guide/cli-reference.md +0 -0
  41. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/docs/guide/dashboard.md +0 -0
  42. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/docs/guide/monitoring.md +0 -0
  43. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/docs/guide/quickstart.md +0 -0
  44. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/docs/guide/vendors.md +0 -0
  45. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/docs/user-guide.md +0 -0
  46. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/docs/zh-CN/README.md +0 -0
  47. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/__init__.py +0 -0
  48. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/__init__.py +0 -0
  49. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/__main__.py +0 -0
  50. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/auth/__init__.py +0 -0
  51. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/auth/providers/__init__.py +0 -0
  52. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/auth/providers/base.py +0 -0
  53. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/auth/providers/github.py +0 -0
  54. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/auth/providers/google.py +0 -0
  55. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/auth/runtime.py +0 -0
  56. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/auth/store.py +0 -0
  57. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/cli/__init__.py +0 -0
  58. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/cli/auth_commands.py +0 -0
  59. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/cli/banner.py +0 -0
  60. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/compat/__init__.py +0 -0
  61. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/compat/canonical.py +0 -0
  62. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/compat/session_store.py +0 -0
  63. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/config/__init__.py +0 -0
  64. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/config/auth_schema.py +0 -0
  65. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/config/config.default.yaml +0 -0
  66. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/config/loader.py +0 -0
  67. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/config/resiliency.py +0 -0
  68. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/config/routing.py +0 -0
  69. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/config/schema.py +0 -0
  70. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/config/server.py +0 -0
  71. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/config/session_policy.py +0 -0
  72. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/config/vendors.py +0 -0
  73. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/convert/__init__.py +0 -0
  74. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/convert/anthropic_to_gemini.py +0 -0
  75. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/convert/anthropic_to_openai.py +0 -0
  76. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/convert/gemini_sse_adapter.py +0 -0
  77. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/convert/gemini_to_anthropic.py +0 -0
  78. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/convert/openai_to_anthropic.py +0 -0
  79. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/logging/__init__.py +0 -0
  80. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/logging/formatters.py +0 -0
  81. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/logging/stats.py +0 -0
  82. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/model/__init__.py +0 -0
  83. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/model/auth.py +0 -0
  84. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/model/compat.py +0 -0
  85. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/model/constants.py +0 -0
  86. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/model/pricing.py +0 -0
  87. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/model/token.py +0 -0
  88. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/model/vendor.py +0 -0
  89. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/native_api/__init__.py +0 -0
  90. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/native_api/config.py +0 -0
  91. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/native_api/extractors/__init__.py +0 -0
  92. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/native_api/extractors/anthropic.py +0 -0
  93. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/native_api/extractors/gemini.py +0 -0
  94. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/native_api/extractors/openai.py +0 -0
  95. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/native_api/handler.py +0 -0
  96. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/native_api/operation.py +0 -0
  97. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/native_api/routes.py +0 -0
  98. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/native_api/usage_registry.py +0 -0
  99. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/pricing.py +0 -0
  100. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/routing/__init__.py +0 -0
  101. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/routing/circuit_breaker.py +0 -0
  102. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/routing/error_classifier.py +0 -0
  103. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/routing/model_mapper.py +0 -0
  104. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/routing/quota_guard.py +0 -0
  105. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/routing/rate_limit.py +0 -0
  106. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/routing/retry.py +0 -0
  107. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/routing/router.py +0 -0
  108. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/routing/session_manager.py +0 -0
  109. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/routing/session_policy.py +0 -0
  110. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/routing/tier.py +0 -0
  111. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/routing/usage_parser.py +0 -0
  112. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/routing/usage_recorder.py +0 -0
  113. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/server/__init__.py +0 -0
  114. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/server/app.py +0 -0
  115. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/server/dashboard.py +0 -0
  116. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/server/factory.py +0 -0
  117. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/server/responses.py +0 -0
  118. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/server/routes.py +0 -0
  119. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/streaming/__init__.py +0 -0
  120. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/streaming/anthropic_compat.py +0 -0
  121. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/vendors/__init__.py +0 -0
  122. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/vendors/alibaba.py +0 -0
  123. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/vendors/anthropic.py +0 -0
  124. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/vendors/antigravity.py +0 -0
  125. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/vendors/base.py +0 -0
  126. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/vendors/copilot.py +0 -0
  127. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/vendors/copilot_models.py +0 -0
  128. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/vendors/copilot_token_manager.py +0 -0
  129. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/vendors/copilot_urls.py +0 -0
  130. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/vendors/doubao.py +0 -0
  131. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/vendors/kimi.py +0 -0
  132. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/vendors/minimax.py +0 -0
  133. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/vendors/mixins.py +0 -0
  134. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/vendors/native_anthropic.py +0 -0
  135. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/vendors/token_manager.py +0 -0
  136. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/src/coding/proxy/vendors/xiaomi.py +0 -0
  137. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/tests/__init__.py +0 -0
  138. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/tests/e2e/__init__.py +0 -0
  139. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/tests/e2e/conftest.py +0 -0
  140. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/tests/e2e/test_e2e_http.py +0 -0
  141. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/tests/e2e/test_e2e_token.py +0 -0
  142. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/tests/e2e/test_e2e_vendor.py +0 -0
  143. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/tests/test_antigravity.py +0 -0
  144. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/tests/test_app_routes.py +0 -0
  145. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/tests/test_auto_login.py +0 -0
  146. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/tests/test_banner.py +0 -0
  147. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/tests/test_circuit_breaker.py +0 -0
  148. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/tests/test_cli_usage.py +0 -0
  149. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/tests/test_compat.py +0 -0
  150. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/tests/test_config_init.py +0 -0
  151. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/tests/test_config_loader.py +0 -0
  152. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/tests/test_convert_request.py +0 -0
  153. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/tests/test_convert_response.py +0 -0
  154. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/tests/test_convert_sse.py +0 -0
  155. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/tests/test_copilot.py +0 -0
  156. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/tests/test_copilot_convert_request.py +0 -0
  157. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/tests/test_copilot_convert_response.py +0 -0
  158. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/tests/test_copilot_models.py +0 -0
  159. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/tests/test_copilot_urls.py +0 -0
  160. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/tests/test_currency.py +0 -0
  161. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/tests/test_error_classifier.py +0 -0
  162. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/tests/test_logging_dual_write.py +0 -0
  163. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/tests/test_mixins.py +0 -0
  164. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/tests/test_model_auth.py +0 -0
  165. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/tests/test_model_compat.py +0 -0
  166. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/tests/test_model_constants.py +0 -0
  167. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/tests/test_model_mapper.py +0 -0
  168. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/tests/test_model_pricing.py +0 -0
  169. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/tests/test_model_token.py +0 -0
  170. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/tests/test_model_vendor.py +0 -0
  171. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/tests/test_native_api_base_url_override.py +0 -0
  172. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/tests/test_native_api_extractors.py +0 -0
  173. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/tests/test_native_api_handler.py +0 -0
  174. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/tests/test_native_api_operation.py +0 -0
  175. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/tests/test_native_api_routes.py +0 -0
  176. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/tests/test_native_vendors.py +0 -0
  177. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/tests/test_parse_usage.py +0 -0
  178. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/tests/test_parse_usage_gemini.py +0 -0
  179. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/tests/test_pricing.py +0 -0
  180. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/tests/test_quota_guard.py +0 -0
  181. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/tests/test_rate_limit.py +0 -0
  182. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/tests/test_router_chain.py +0 -0
  183. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/tests/test_router_executor.py +0 -0
  184. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/tests/test_runtime_reauth.py +0 -0
  185. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/tests/test_schema.py +0 -0
  186. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/tests/test_streaming_anthropic_compat.py +0 -0
  187. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/tests/test_tier.py +0 -0
  188. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/tests/test_tiers_config.py +0 -0
  189. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/tests/test_time_range.py +0 -0
  190. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/tests/test_token_logger.py +0 -0
  191. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/tests/test_token_logger_native_columns.py +0 -0
  192. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/tests/test_token_manager.py +0 -0
  193. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/tests/test_types.py +0 -0
  194. {coding_proxy-0.4.1a3 → coding_proxy-0.4.1a5}/tests/test_vendor_streaming.py +0 -0
@@ -33,15 +33,13 @@
33
33
  ### 术 (Tactics - 执行规范)
34
34
 
35
35
  - **Structured AI-Pair Pipeline (规范化 AI 结对流水线)**: 遵循 **Specification-Driven (规约驱动)** + **Context-Anchored (上下文锚定)** + **AI-Pair (AI 结对)** 模式,将开发固化为可审计的流水线,避免代码腐化为无法维护的“大泥球 (Big Ball of Mud)”。
36
- - **Visual Documentation (图文并茂)**: 对于复杂逻辑,优先使用 Mermaid 图表(Sequence/Flowchart/Class)辅助说明,构建“图文并茂”的直观文档。
37
- - **Direct Hyperlinking (直接跳转)**: 在文档中提及 Repo 内其他资源(文档/代码)时,**必须**构建可跳转的相对路径链接(如 `[Doc Name](./path.md)`),严禁使用“死文本”引用,以降低信息检索熵。
38
36
  - **Operational Excellence (卓越运营)**:
39
37
  1. **Git Discipline**: 默认严禁调用 git commit;当用户显式要求提交时,一律使用 Claude Code 的自定义 Slash Command: `/commit-no-push` 进行操作(若非 Claude Code 运行环境,则读取 /commit-no-push 命令中的规则执行)。严禁执行 Rebase;
40
38
  2. **Temp Management**: 临时产物(执行计划等)一律收敛至 `.temp/` 并及时清理;
41
39
  3. **Link Validity**: 确保所有引用的 URL 可访问且具备明确的上下文价值;
42
40
  4. **Testing**: 统一在 tests/ 下维护测试用例,区分单元测试(unit)和集成测试(integration),所有测试的本地运行总时间控制在 3 min 以内;
43
41
  5. **Pre-commit Hooks**: 首次克隆仓库使用 `uv run pre-commit install` 激活本地 Git hooks,使 Ruff lint(含 auto-fix)、Ruff format 及通用代码卫生检查在每次 commit 前自动运行。若 hooks 自动修复了问题,提交会被中断,执行 `git add -p` 审阅修复内容后重新提交即可;
44
- 6. **Issue**: 在 docs/issue.md 中维护你处理过的 Issue 摘要(问题描述、表因根因、处理方式、后续防范、同类问题影响与处理注意事项等),便于同类问题的跨上下文处理;注意识别相同 Issue,不要同 Issue 多处维护;
42
+ 6. **Issue**: 在 [issue.md](docs/agents/issue.md) 中维护你处理过的 Issue 摘要(问题描述、表因根因、处理方式、后续防范、同类问题影响与处理注意事项等),便于同类问题的跨上下文处理;注意识别相同 Issue,不要同 Issue 多处维护;
45
43
  - **Package Management Standardization (包管理规范)**:
46
44
  1. **Python**: 严禁使用 pip/poetry,**必须**统一使用 `uv` 进行包管理与脚本执行(如 `uv run`);
47
45
  2. **JavaScript/TypeScript**: 严禁使用 npm/yarn,**必须**统一使用 `pnpm` 进行包管理与脚本执行;
@@ -49,7 +47,11 @@
49
47
  - **Browser Validation Protocol (浏览器验证准则)**:Agent 不得自行完成、绕过或模拟任何 OAuth / SSO 认证流程,所有登录态均来源于用户已认证的 Chrome 主 profile(真实用户登录态)。完整协议(连通性自检、凭证管理、E2E 集成、实机回归等)详见 [浏览器验证协议](./docs/agents/browser-validation.md);
50
48
  1. **安全红线**:禁止在 Sandbox 浏览器中跳转 Google 同意屏;禁止以模拟用户或第三方账号替代真实登录态;禁止要求用户在 chat 中粘贴密码、Cookie 或验证码;
51
49
  - **Knowledge Map (知识索引)**:项目所有文档索引统一维护在 [知识索引](./docs/agents/knowledge-map.md),并在文档目录变更时即时同步跟新;
52
- - **Documentation Standards (文档规范)**:采用**Mermaid Visualization Norms (Mermaid 可视化规范)**;
53
- 1. **色彩语义与兼容性**:为图表节点配置具备语义辨识度的色彩,并确保在深色模式(Dark Mode)下具有极高的对比度与清晰度;
54
- 2. **逻辑模块化解构**:针对业务跨度较大的架构流程,强制采用 `subgraph` 容器进行层级解构与边界划分,以增强图表的自解说(Self-explaining)能力;
50
+ - **Documentation Standards (文档规范)**:
51
+ 1. **Visual Documentation (图文并茂)**: 对于复杂逻辑,优先 **Mermaid Visualization Norms (Mermaid 可视化规范)**,构建“图文并茂”的直观文档;
52
+ - **色彩语义与兼容性**:为图表节点配置具备语义辨识度的色彩,并确保在深色模式(Dark Mode)下具有极高的对比度与清晰度;
53
+ - **逻辑模块化解构**:针对业务跨度较大的架构流程,强制采用 `subgraph` 容器进行层级解构与边界划分,以增强图表的自解说(Self-explaining)能力;
54
+ 2. **语言叙事**:用语精准,叙事完备,行文专业,聚焦核心,篇幅精炼,形象具体,体现真实作用与用户吸引性,字数恰当;
55
+ 3. **Direct Hyperlinking (直接跳转)**: 在文档中提及 Repo 内其他资源(文档/代码)时,**必须**构建可跳转的相对路径链接(如 `[Doc Name](./path.md)`),严禁使用“死文本”引用,以降低信息检索熵;
56
+ 4. **实操截图**:文档需要引入必要的浏览器实操截图时,需自行通过默认浏览器打开相关页面,通过实操现场截图并保留到文档路径进行文档引用;
55
57
  - **Reference Specifications (IEEE)**:为保障工程决策的可追溯性与学术严谨性,核心引用需遵循 [reference-specifications.md](docs/agents/reference-specifications.md)IEEE 标准引用格式;
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: coding-proxy
3
- Version: 0.4.1a3
3
+ Version: 0.4.1a5
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
@@ -0,0 +1,172 @@
1
+ # Browser Validation Protocol(浏览器验证协议)
2
+
3
+ > 由 [AGENTS.md §Browser Validation Protocol](../../AGENTS.md) 锚定的浏览器自动化与认证态使用协议。本协议是工程行为准则的子集,**任何 AI Agent 在执行浏览器自动化任务前必须完整遵循**。
4
+ >
5
+ > **协议版本**:v1.0 | **生效范围**:所有面向本仓库的 AI Agent 协作场景
6
+ >
7
+ > **关联工具**:`chrome-devtools` MCP、`claude-in-chrome` MCP、`playwright` MCP
8
+
9
+ [TOC]
10
+
11
+ ---
12
+
13
+ ## 1. 协议目的
14
+
15
+ 为 AI Agent 在浏览器自动化场景下提供**统一、可审计、不可绕过**的认证态使用规范,解决以下问题:
16
+
17
+ - AI Agent 不应也不可代用户决策"我是谁"——所有登录态归属问题必须由用户本人主导
18
+ - 浏览器自动化能力一旦失控,可能在用户毫不知情时产生不可撤销的副作用(消息发送、订单提交、权限变更等)
19
+ - OAuth / SSO 同意屏在自动化上下文中存在被绕过的潜在风险,违反平台 ToS 与基本伦理
20
+
21
+ 本协议通过"原则—红线—操作流程—验证"四层结构,将上述问题约束在工程可控范围内。
22
+
23
+ ---
24
+
25
+ ## 2. 核心原则
26
+
27
+ | 原则 | 具体含义 |
28
+ | -------------------------- | ----------------------------------------------------------------------------------------------------- |
29
+ | **登录态归属于用户** | Agent 不得自行完成、绕过或模拟任何 OAuth / SSO 认证流程;所有登录态来源于用户已认证的 Chrome 主 profile |
30
+ | **真实主 profile 优先** | 浏览器自动化默认接入用户日常使用的 Chrome 主 profile,复用其 Cookie / Session / SSO 状态 |
31
+ | **可审计、可回放** | 浏览器路径关键操作(点击、表单填写、跳转)应留下可被 GIF 回放或日志追溯的痕迹 |
32
+ | **最小副作用** | 优先以只读方式(查看、提取、断言)完成任务;写操作(提交、发送)需在协议第 5 节框架下显式确认 |
33
+
34
+ ---
35
+
36
+ ## 3. 安全红线
37
+
38
+ > 以下条款**不可协商**,违反任一条款即视为协议违反。
39
+
40
+ 1. **禁止跳转 Google 同意屏**:在 Sandbox / 自动化浏览器环境内**严禁**触发 Google OAuth 同意屏跳转。同意屏只能在用户主 profile 的真实浏览会话中由用户本人完成。
41
+ 2. **禁止模拟身份**:禁止以模拟用户身份、虚构 Cookie、第三方账号或测试账号替代真实登录态完成任务。
42
+ 3. **禁止凭证泄露**:禁止要求用户在 chat 中粘贴密码、Cookie、Session Token、二维码扫描结果或任何形式的验证码(含 6 位数字、短信、TOTP)。
43
+ 4. **禁止跨账号操作**:在多用户环境下,Agent 不得在未经显式确认的情况下切换 profile 或账号身份。
44
+ 5. **禁止规避 ToS**:不得通过 Headless 模式、UA 伪装、Captcha 自动求解等方式规避目标站点的服务条款。
45
+ 6. **禁止下载执行**:浏览器路径触发的任何文件下载需在主对话中显式确认;下载文件不得自动执行或注入到项目目录。
46
+
47
+ ---
48
+
49
+ ## 4. 连通性自检(Connectivity Probe)
50
+
51
+ 执行浏览器自动化任务前,Agent **必须**完成以下自检序列:
52
+
53
+ | 步骤 | 操作 | 通过判据 |
54
+ | --------------------- | ----------------------------------------------------------------- | --------------------------------------------------------- |
55
+ | 4.1 工具可用性 | 列出当前会话可用的 MCP 工具 | 至少存在 `chrome-devtools` / `claude-in-chrome` 之一 |
56
+ | 4.2 主 profile 加载 | 通过工具调用获取当前 Tab 列表或 Page 列表 | 返回非空,且 Tab 标题来自用户真实浏览历史而非空白会话 |
57
+ | 4.3 目标域名可达 | 通过 `navigate_page` 或 `browser_navigate` 访问目标域名首页 | HTTP 200 / 已登录态正常加载 |
58
+ | 4.4 登录态识别 | 在目标域名首页定位"已登录"标识(头像、用户名、退出按钮) | 能在 Snapshot / AOM 中找到一致标识 |
59
+ | 4.5 异常路径分类 | 若 4.4 失败,按"未登录 vs 会话过期 vs 拒绝服务"分类,**不**自动重登 | 输出明确分类,转入第 5 节的用户接力流程 |
60
+
61
+ > **失败处置**:自检任一步骤失败,Agent **必须**停止任务、向用户输出诊断结论,**不得**尝试 OAuth / 凭证补救。
62
+
63
+ ---
64
+
65
+ ## 5. 凭证管理(Credential Lifecycle)
66
+
67
+ ### 5.1 发现路径
68
+
69
+ 凭证通过以下路径**被动**发现,Agent **不**主动读取、导出或日志化:
70
+
71
+ - 浏览器 Cookie / LocalStorage(仅由浏览器引擎内部使用)
72
+ - 浏览器扩展(如 Claude in Chrome)持有的 Session
73
+ - 用户在 chat 中以"我刚登录了 X"形式给出的事实陈述(非凭证本身)
74
+
75
+ ### 5.2 过期检测信号
76
+
77
+ | 信号 | 处置 |
78
+ | ---------------------------------------- | ----------------------------------------------- |
79
+ | HTTP 401 / 403 | 转 5.3 接力流程 |
80
+ | 重定向到登录页(含 `/login`、`/signin`) | 转 5.3 接力流程 |
81
+ | 同意屏触发(OAuth scope 变更) | **立即停止**,由用户在主 profile 完成同意 |
82
+ | Captcha 出现 | **立即停止**,输出"需用户介入" |
83
+
84
+ ### 5.3 用户接力流程(Re-authentication Handoff)
85
+
86
+ ```
87
+ 1. Agent 检测到登录态失效
88
+ 2. Agent 向用户输出:(a)失效域名 (b)建议在用户主 profile 完成登录的指引
89
+ 3. Agent 暂停浏览器任务,**不**触发任何登录流程
90
+ 4. 用户在真实浏览器完成登录后,回到 chat 通知 Agent
91
+ 5. Agent 重新执行第 4 节连通性自检
92
+ 6. 自检通过后恢复任务
93
+ ```
94
+
95
+ ### 5.4 凭证刷新约束
96
+
97
+ - Agent **不**调用任何 refresh_token / device_code 接口
98
+ - Agent **不**触发邮箱链接、短信验证码、TOTP 输入
99
+ - 凭证刷新由用户在原始登录路径自主完成
100
+
101
+ ---
102
+
103
+ ## 6. E2E 集成(End-to-End Integration)
104
+
105
+ ### 6.1 与项目 OAuth 模块的边界
106
+
107
+ 本项目内置 GitHub Device Flow 与 Google OAuth 模块(`src/coding/proxy/auth/`)。浏览器协议与之的边界如下:
108
+
109
+ - **项目 OAuth 模块**:服务端运行时凭证管理,由 `coding-proxy auth login/reauth` CLI 触发,目标是给 **proxy 自身**获取上游 API 凭证
110
+ - **本协议**:客户端浏览器自动化场景,目标是让 **Agent 协助用户**完成日常任务(如查文档、填表单)
111
+
112
+ 二者**互不调用**:Agent 不调用 `coding-proxy auth` 替用户完成项目 OAuth;项目 OAuth 流程也不依赖本协议第 4 节自检。
113
+
114
+ ### 6.2 与 CLI 命令的协同
115
+
116
+ | 场景 | 由谁触发 |
117
+ | ------------------------------- | ------------------------- |
118
+ | 给 proxy 注入 GitHub PAT | 用户运行 `auth login` |
119
+ | 给 proxy 注入 Google OAuth | 用户运行 `auth login` |
120
+ | 凭证过期重认证 | 用户运行 `auth reauth` |
121
+ | 浏览器查看 GitHub Token 状态 | Agent 通过本协议浏览器访问 |
122
+
123
+ ### 6.3 测试用例的浏览器隔离
124
+
125
+ - 单元测试(`tests/unit/`)**不**触发任何浏览器路径
126
+ - 集成测试(`tests/integration/`)**不**触发任何浏览器路径
127
+ - 浏览器路径仅在交互式 Agent 会话中触发,不进入 CI 自动化测试链路
128
+
129
+ ---
130
+
131
+ ## 7. 实机回归(Real-Device Regression)
132
+
133
+ ### 7.1 提交前的浏览器路径自检清单
134
+
135
+ 涉及浏览器路径的改动在提交前需手工核验:
136
+
137
+ - [ ] 第 4 节连通性自检在用户主 profile 通过
138
+ - [ ] 第 3 节安全红线未被触碰(特别是同意屏、密码粘贴)
139
+ - [ ] 浏览器路径的关键操作有 GIF / Snapshot 留痕
140
+ - [ ] 失败路径输出明确的用户接力指引
141
+
142
+ ### 7.2 与 CI 的边界
143
+
144
+ CI 流水线(详见 [ops/ci-cd.md](../ops/ci-cd.md))**不**触发浏览器自动化路径。所有浏览器侧验证均在本地实机完成。
145
+
146
+ ### 7.3 回归失败上报
147
+
148
+ 若实机回归失败:
149
+
150
+ 1. 在 [docs/issue.md](../issue.md) 记录现象、根因、防范
151
+ 2. 若涉及协议本身缺陷,提交 PR 修订本文件并同步 [AGENTS.md](../../AGENTS.md) 锚点
152
+ 3. 不通过的 Agent 行为应在 [knowledge-map.md](./knowledge-map.md) 标注为已知问题
153
+
154
+ ---
155
+
156
+ ## 8. 引用规范
157
+
158
+ - 本协议章节可被 [AGENTS.md](../../AGENTS.md) / [CLAUDE.md](../../CLAUDE.md) 通过标题锚点形式引用
159
+ - 修订本协议**必须**在 [docs/issue.md](../issue.md) 留存背景与决策记录
160
+ - 协议条款发生变更时,需同步检查 [AGENTS.md §Browser Validation Protocol](../../AGENTS.md) 的兜底原则与本协议是否一致
161
+
162
+ ---
163
+
164
+ ## 附录 A:术语对照
165
+
166
+ | 术语 | 说明 |
167
+ | ------------------- | ----------------------------------------------------------------- |
168
+ | 主 profile | 用户日常使用的 Chrome / Edge 浏览器档案,含真实登录态 |
169
+ | Sandbox 浏览器 | 自动化工具启动的临时/隔离浏览器,无真实用户态 |
170
+ | 同意屏(Consent) | OAuth 流程中用户授予权限范围的页面 |
171
+ | 接力流程 | Agent 停止 → 用户介入完成 → Agent 恢复 的三段式协作 |
172
+ | 实机回归 | 在用户真实终端(非 CI)完成的端到端验证 |
@@ -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。
@@ -0,0 +1,95 @@
1
+ # Knowledge Map(知识索引)
2
+
3
+ > 项目所有文档的统一入口与权威索引。由 [AGENTS.md §Knowledge Map](../../AGENTS.md) 锚定,文档目录变更时**必须**即时同步更新本文件。
4
+ >
5
+ > **使用方式**:按"受众 × 目的"二维定位所需文档;不确定起点时,从「入口导航」开始。
6
+
7
+ [TOC]
8
+
9
+ ---
10
+
11
+ ## 1. 入口导航
12
+
13
+ | 文档 | 角色 | 受众 |
14
+ | --------------------------------------------- | ----------------------------------------------- | --------------- |
15
+ | [README.md](../../README.md) | 项目首页(英文版门面) | 公开访客 |
16
+ | [docs/zh-CN/README.md](../zh-CN/README.md) | 项目首页中文镜像(与英文版功能对等) | 中文公开访客 |
17
+ | [docs/user-guide.md](../user-guide.md) | 用户操作上位导航 + 配置概览速查 | 终端用户 |
18
+ | [docs/framework.md](../framework.md) | 架构枢纽(项目动机、设计目标、模块清单) | 架构师/贡献者 |
19
+
20
+ ---
21
+
22
+ ## 2. 用户向([docs/guide/](../guide/))
23
+
24
+ > 面向最终用户的操作手册,按"安装 → 配置 → 运行 → 观测 → 排障"线性铺陈。
25
+
26
+ | 文档 | 主旨 |
27
+ | ------------------------------------------------- | --------------------------------------------------- |
28
+ | [guide/quickstart.md](../guide/quickstart.md) | 环境要求、安装、最小配置、启动、Claude Code 集成 |
29
+ | [guide/vendors.md](../guide/vendors.md) | 全部 9 种供应商配置详情、模型映射、定价表 |
30
+ | [guide/cli-reference.md](../guide/cli-reference.md) | start / status / usage / reset / auth 全部命令 |
31
+ | [guide/api-reference.md](../guide/api-reference.md) | /v1/messages、health、status、reset、dashboard 等 |
32
+ | [guide/dashboard.md](../guide/dashboard.md) | Web 可视化看板功能与交互 |
33
+ | [guide/monitoring.md](../guide/monitoring.md) | 日志、用量统计、性能调优、常见场景、故障排查 |
34
+
35
+ ---
36
+
37
+ ## 3. 架构向([docs/arch/](../arch/))
38
+
39
+ > 面向贡献者与维护者的架构与实现细节,从 [framework.md](../framework.md) 正交分解而来。
40
+
41
+ | 文档 | 主旨 |
42
+ | ----------------------------------------------------- | ----------------------------------------------------- |
43
+ | [arch/config-reference.md](../arch/config-reference.md) | 配置参数权威定义(Single Source of Truth) |
44
+ | [arch/design-patterns.md](../arch/design-patterns.md) | 13 种设计模式详解(熔断器、状态机、Composite 等) |
45
+ | [arch/routing.md](../arch/routing.md) | 路由引擎 12 个子模块职责 |
46
+ | [arch/vendors.md](../arch/vendors.md) | Vendor 类层次结构与 9 种实现 |
47
+ | [arch/convert.md](../arch/convert.md) | Anthropic ↔ Gemini ↔ OpenAI 三向格式转换 |
48
+ | [arch/testing.md](../arch/testing.md) | 测试覆盖矩阵与工具链 |
49
+
50
+ ---
51
+
52
+ ## 4. 运维向([docs/ops/](../ops/))
53
+
54
+ > 面向运维与发布工程的流程文档。
55
+
56
+ | 文档 | 主旨 |
57
+ | ----------------------------------- | ------------------------------------------------- |
58
+ | [ops/ci-cd.md](../ops/ci-cd.md) | 发布流程、热修复、回滚、CI/CD 故障排查 |
59
+
60
+ ---
61
+
62
+ ## 5. Agent 协作([docs/agents/](./))
63
+
64
+ > AGENTS.md 工程行为准则的卫星文件,定义 AI Agent 协作过程中的规范与协议。
65
+
66
+ | 文档 | 主旨 |
67
+ | --------------------------------------------------------------- | --------------------------------------------- |
68
+ | [agents/knowledge-map.md](./knowledge-map.md) | 本文件——项目文档统一索引 |
69
+ | [agents/reference-specifications.md](./reference-specifications.md) | IEEE 文献引用格式模板与实践指南 |
70
+ | [agents/browser-validation.md](./browser-validation.md) | 浏览器验证协议(连通性自检、凭证管理、E2E) |
71
+
72
+ ---
73
+
74
+ ## 6. 问题档案
75
+
76
+ | 文档 | 主旨 |
77
+ | --------------------------------- | ----------------------------------------------------- |
78
+ | [docs/issue.md](../issue.md) | 已处理 Issue 摘要档案(表因、根因、防范) |
79
+
80
+ ---
81
+
82
+ ## 7. 工程规范(顶层)
83
+
84
+ | 文档 | 主旨 |
85
+ | --------------------------------- | ----------------------------------------------------- |
86
+ | [AGENTS.md](../../AGENTS.md) | 工程行为准则与 AI Agent 协作协议(与 CLAUDE.md 同源) |
87
+ | [CHANGELOG.md](../../CHANGELOG.md)| 版本历史与变更日志 |
88
+
89
+ ---
90
+
91
+ ## 维护约束
92
+
93
+ 1. **同步原则**:新增/删除/重命名 `docs/` 下任意 .md 文件时,**必须**同步本索引。
94
+ 2. **路径基准**:本文件位于 `docs/agents/`,所有相对路径以此为基准(向上一级 `../` 访问 `docs/`,向上两级 `../../` 访问仓库根)。
95
+ 3. **链接验证**:维护者修改本文件后应通过 grep 自检:所有 `[...](path)` 中的 `path` 文件存在。
@@ -1,7 +1,7 @@
1
1
  # 供应商模块(vendors/)
2
2
 
3
3
  > 路径约定:相对于 `src/coding/proxy/`
4
- > 定位:从 [framework.md](./framework.md) 提取,详述供应商分类体系与各供应商实现。
4
+ > 定位:从 [framework.md](../framework.md) 提取,详述供应商分类体系与各供应商实现。
5
5
 
6
6
  [TOC]
7
7
 
@@ -211,7 +211,7 @@ CI 流水线中使用的工具及其版本均与项目实际配置严格对齐
211
211
 
212
212
  | 工具 | 版本 / 引用 | 来源 (Action) | 与项目配置的对齐关系 |
213
213
  | -------------- | ----------------------------------- | ---------------------------------------- | -------------------------------------------------------------------------- |
214
- | Python | `["3.12", "3.13", "3.14"]` (matrix) | `actions/setup-python@v5` | 对齐 [`pyproject.toml`](../pyproject.toml) 中 `requires-python = ">=3.12"` |
214
+ | Python | `["3.12", "3.13", "3.14"]` (matrix) | `actions/setup-python@v5` | 对齐 [`pyproject.toml`](../../pyproject.toml) 中 `requires-python = ">=3.12"` |
215
215
  | uv | latest (v4) | `astral-sh/setup-uv@v4` | 项目强制包管理器(见 AGENTS.md 包管理规范) |
216
216
  | build | latest | `uv pip install --system build` | PEP 517 构建前端,后端为 hatchling |
217
217
  | twine | latest | `uv pip install --system twine` | 包元数据校验与上传工具 |
@@ -435,7 +435,7 @@ flowchart TD
435
435
 
436
436
  ### 4.1 promote.yml 工作流架构
437
437
 
438
- [`promote.yml`](../.github/workflows/promote.yml) 由两个 Job 组成,形成 **Validate → Promote** 的串行管线:
438
+ [`promote.yml`](../../.github/workflows/promote.yml) 由两个 Job 组成,形成 **Validate → Promote** 的串行管线:
439
439
 
440
440
  #### Job 1:validate(验证门控)
441
441
 
@@ -629,7 +629,7 @@ flowchart TD
629
629
  | 问题现象 | 可能原因 | 排查步骤 | 解决方案 |
630
630
  | ------------------------------- | ------------------------------------------------------ | ----------------------------------------------------- | --------------------------------------------------------- |
631
631
  | `release.yml` 未触发 | Release 创建时未触发 `published` 事件(如 Draft 状态) | 检查 Actions 页面是否有该 workflow run | 确保 Release 为非 Draft 状态;或重新发布 |
632
- | `build` Job 失败 | `twine check` 报错(包元数据不合规) | 查看 build Job 日志中的 twine 输出 | 修复 [`pyproject.toml`](../pyproject.toml) 中的元数据字段 |
632
+ | `build` Job 失败 | `twine check` 报错(包元数据不合规) | 查看 build Job 日志中的 twine 输出 | 修复 [`pyproject.toml`](../../pyproject.toml) 中的元数据字段 |
633
633
  | publish 失败 (HTTP 400) | 包名或版本号冲突(目标仓库已有同版本) | 查看 verbose 日志中的响应体(已启用 `verbose: true`) | 检查 TestPyPI/PyPI 是否已有同版本;使用递增版本号 |
634
634
  | publish 失败 (HTTP 403) | 认证失败(Token 无效或缺失) | 检查 Job 日志中的认证错误详情 | 验证 Secret 配置或 Trusted Publisher 设置(参见 §7.2) |
635
635
  | `promote.yml` validate 失败 | Target release 不是 prerelease(已是 stable) | 查看 validate Job 错误信息 | 确认输入的 `tag_name` 对应的是 prerelease release |
@@ -701,7 +701,7 @@ CI 流水线中的工具版本选择并非随意,每一项都与项目配置
701
701
 
702
702
  | CI 配置 | 项目配置 | 对齐关系 |
703
703
  | ------------------------------------------------ | --------------------------------------------------------------------- | --------------------------------------------------------------------------- |
704
- | `python-version: "${{ matrix.python-version }}"` | `requires-python = ">=3.12"` in [`pyproject.toml`](../pyproject.toml) | CI 构建环境必须满足项目的最低 Python 版本要求(matrix: 3.12 / 3.13 / 3.14) |
704
+ | `python-version: "${{ matrix.python-version }}"` | `requires-python = ">=3.12"` in [`pyproject.toml`](../../pyproject.toml) | CI 构建环境必须满足项目的最低 Python 版本要求(matrix: 3.12 / 3.13 / 3.14) |
705
705
  | `hatchling.build` (build-backend) | `[build-system] requires = ["hatchling"]` | 构建后端声明必须一致 |
706
706
  | `uv pip install --system` | AGENTS.md 强制使用 `uv` | GitHub Actions Runner 默认无激活的 virtualenv,需 `--system` 标志 |
707
707
  | `retention-days: 14` | — | Artifact 保留两周,覆盖正常的验证窗口期(通常 1-3 天) |
@@ -714,7 +714,7 @@ CI 流水线中的工具版本选择并非随意,每一项都与项目配置
714
714
 
715
715
  ### 8.1 release.yml 结构索引
716
716
 
717
- [`.github/workflows/release.yml`](../.github/workflows/release.yml) 文件结构一览:
717
+ [`.github/workflows/release.yml`](../../.github/workflows/release.yml) 文件结构一览:
718
718
 
719
719
  | 行范围 | 区块 | 内容摘要 |
720
720
  | ------- | ----------------------- | ---------------------------------------------------------------------------------------------------- |
@@ -729,7 +729,7 @@ CI 流水线中的工具版本选择并非随意,每一项都与项目配置
729
729
 
730
730
  ### 8.2 promote.yml 结构索引
731
731
 
732
- [`.github/workflows/promote.yml`](../.github/workflows/promote.yml) 文件结构一览:
732
+ [`.github/workflows/promote.yml`](../../.github/workflows/promote.yml) 文件结构一览:
733
733
 
734
734
  | 行范围 | 区块 | 内容摘要 |
735
735
  | ------ | --------------- | -------------------------------------------------------------- |
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "coding-proxy"
3
- version = "0.4.1a3"
3
+ version = "0.4.1a5"
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"
@@ -367,6 +367,57 @@ def _strip_cache_control(body: dict[str, Any]) -> int:
367
367
  return removed
368
368
 
369
369
 
370
+ # ── zhipu 共享清洗函数 ──────────────────────────────────────────
371
+
372
+ # 跨供应商转换时主动剥离的顶层参数(首选 tier 场景由 _prepare_request 原样透传,
373
+ # GLM 原生支持 thinking / 静默忽略 cache_control 和 reasoning_effort,不会触发 400)。
374
+ _ZHIPU_UNSUPPORTED_PARAMS: frozenset[str] = frozenset(
375
+ {"thinking", "extended_thinking", "reasoning_effort"}
376
+ )
377
+
378
+
379
+ def normalize_for_zhipu(body: dict[str, Any]) -> tuple[dict[str, Any], list[str]]:
380
+ """为 zhipu GLM 的 Anthropic 兼容端点清洗请求体(就地,不 deep copy).
381
+
382
+ 为跨供应商转换通道 ``prepare_copilot_to_zhipu`` 提供请求体清洗。
383
+
384
+ 清洗内容:
385
+ 1. 剥离 cache_control 字段(GLM 静默忽略,主动剥离以减少噪音)
386
+ 2. 移除顶层 thinking/extended_thinking/reasoning_effort 参数(GLM 原生支持
387
+ thinking、静默忽略 reasoning_effort,但跨供应商场景下这些参数来自原供应商
388
+ 的协议语义,主动剥离以确保请求语义一致性)
389
+ 3. 强制 tool_use/tool_result 配对约束
390
+
391
+ 不包含 thinking blocks 剥离:跨供应商场景下 history 中的 thinking blocks
392
+ 来自原供应商(签名失效),由调用方在调用本函数之前通过
393
+ ``strip_thinking_blocks`` 单独处理。
394
+
395
+ 所有操作均为幂等,安全地在已清洗的请求体上重复调用。
396
+
397
+ Returns:
398
+ (body, adaptations) — body 为就地修改后的同一引用,adaptations 为变换描述列表。
399
+ """
400
+ adaptations: list[str] = []
401
+
402
+ # Step 1: 剥离 cache_control
403
+ removed_cc = _strip_cache_control(body)
404
+ if removed_cc:
405
+ adaptations.append(f"removed_{removed_cc}_cache_control_fields")
406
+
407
+ # Step 2: 移除不支持的顶层参数
408
+ for param in _ZHIPU_UNSUPPORTED_PARAMS:
409
+ if param in body:
410
+ del body[param]
411
+ adaptations.append(f"removed_{param}_param")
412
+
413
+ # Step 3: 强制 tool_use/tool_result 配对
414
+ pairing_fixes = enforce_anthropic_tool_pairing(body.get("messages", []))
415
+ if pairing_fixes:
416
+ adaptations.extend(pairing_fixes)
417
+
418
+ return body, adaptations
419
+
420
+
370
421
  def _remove_vendor_blocks(body: dict[str, Any], block_types: set[str]) -> int:
371
422
  """从 messages[].content[] 中就地移除指定 type 的内容块.
372
423
 
@@ -544,26 +595,14 @@ def prepare_copilot_to_zhipu(
544
595
  prepared = copy.deepcopy(body)
545
596
  adaptations: list[str] = []
546
597
 
547
- # Step 1: 剥离 thinking/redacted_thinking
598
+ # Step 1: 剥离 thinking/redacted_thinking 块(跨供应商签名失效)
548
599
  stripped = strip_thinking_blocks(prepared)
549
600
  if stripped:
550
601
  adaptations.append(f"stripped_{stripped}_thinking_blocks")
551
602
 
552
- # Step 2: 移除 cache_control 字段
553
- removed_cc = _strip_cache_control(prepared)
554
- if removed_cc:
555
- adaptations.append(f"removed_{removed_cc}_cache_control_fields")
556
-
557
- # Step 3: 移除顶层 thinking/extended_thinking 参数(GLM-5 不支持)
558
- for param in ("thinking", "extended_thinking"):
559
- if param in prepared:
560
- del prepared[param]
561
- adaptations.append(f"removed_{param}_param")
562
-
563
- # Step 4: 强制 tool_use/tool_result 配对
564
- pairing_fixes = enforce_anthropic_tool_pairing(prepared.get("messages", []))
565
- if pairing_fixes:
566
- adaptations.extend(pairing_fixes)
603
+ # Step 2: 共享清洗(cache_control、不支持的顶层参数、tool pairing)
604
+ _, norm_adaptations = normalize_for_zhipu(prepared)
605
+ adaptations.extend(norm_adaptations)
567
606
 
568
607
  return prepared, adaptations
569
608
 
@@ -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,
@@ -602,9 +602,11 @@ class _RouteExecutor:
602
602
 
603
603
  if not is_last and is_semantic:
604
604
  logger.warning(
605
- "Tier %s semantic rejection (%s), trying next tier without recording failure",
605
+ "Tier %s semantic rejection (type=%s, msg=%s), "
606
+ "trying next tier without recording failure",
606
607
  tier.name,
607
608
  resp.error_type or resp.status_code,
609
+ (resp.error_message or "N/A")[:200],
608
610
  )
609
611
  failed_tier_name = tier.name
610
612
  continue