coding-proxy 0.2.4a1__tar.gz → 0.2.4a2__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 (148) hide show
  1. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/PKG-INFO +1 -1
  2. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/pyproject.toml +1 -1
  3. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/config/config.default.yaml +5 -5
  4. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/logging/stats.py +1 -1
  5. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/model/pricing.py +2 -2
  6. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/server/dashboard.py +1 -1
  7. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/tests/test_currency.py +3 -3
  8. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/uv.lock +1 -1
  9. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/.github/workflows/ci.yml +0 -0
  10. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/.github/workflows/coverage.yml +0 -0
  11. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/.github/workflows/release.yml +0 -0
  12. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/.gitignore +0 -0
  13. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/AGENTS.md +0 -0
  14. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/CHANGELOG.md +0 -0
  15. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/CLAUDE.md +0 -0
  16. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/LICENSE +0 -0
  17. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/README.md +0 -0
  18. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/assets/dashboard-v0.2.3.png +0 -0
  19. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/docs/ci-cd.md +0 -0
  20. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/docs/framework.md +0 -0
  21. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/docs/user-guide.md +0 -0
  22. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/docs/zh-CN/README.md +0 -0
  23. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/__init__.py +0 -0
  24. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/__init__.py +0 -0
  25. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/__main__.py +0 -0
  26. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/auth/__init__.py +0 -0
  27. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/auth/providers/__init__.py +0 -0
  28. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/auth/providers/base.py +0 -0
  29. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/auth/providers/github.py +0 -0
  30. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/auth/providers/google.py +0 -0
  31. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/auth/runtime.py +0 -0
  32. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/auth/store.py +0 -0
  33. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/cli/__init__.py +0 -0
  34. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/cli/auth_commands.py +0 -0
  35. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/cli/banner.py +0 -0
  36. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/compat/__init__.py +0 -0
  37. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/compat/canonical.py +0 -0
  38. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/compat/session_store.py +0 -0
  39. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/config/__init__.py +0 -0
  40. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/config/auth_schema.py +0 -0
  41. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/config/loader.py +0 -0
  42. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/config/resiliency.py +0 -0
  43. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/config/routing.py +0 -0
  44. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/config/schema.py +0 -0
  45. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/config/server.py +0 -0
  46. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/config/vendors.py +0 -0
  47. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/convert/__init__.py +0 -0
  48. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/convert/anthropic_to_gemini.py +0 -0
  49. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/convert/anthropic_to_openai.py +0 -0
  50. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/convert/gemini_sse_adapter.py +0 -0
  51. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/convert/gemini_to_anthropic.py +0 -0
  52. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/convert/openai_to_anthropic.py +0 -0
  53. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/logging/__init__.py +0 -0
  54. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/logging/db.py +0 -0
  55. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/logging/formatters.py +0 -0
  56. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/model/__init__.py +0 -0
  57. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/model/auth.py +0 -0
  58. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/model/compat.py +0 -0
  59. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/model/constants.py +0 -0
  60. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/model/token.py +0 -0
  61. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/model/vendor.py +0 -0
  62. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/pricing.py +0 -0
  63. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/routing/__init__.py +0 -0
  64. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/routing/circuit_breaker.py +0 -0
  65. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/routing/error_classifier.py +0 -0
  66. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/routing/executor.py +0 -0
  67. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/routing/model_mapper.py +0 -0
  68. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/routing/quota_guard.py +0 -0
  69. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/routing/rate_limit.py +0 -0
  70. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/routing/retry.py +0 -0
  71. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/routing/router.py +0 -0
  72. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/routing/session_manager.py +0 -0
  73. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/routing/tier.py +0 -0
  74. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/routing/usage_parser.py +0 -0
  75. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/routing/usage_recorder.py +0 -0
  76. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/server/__init__.py +0 -0
  77. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/server/app.py +0 -0
  78. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/server/factory.py +0 -0
  79. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/server/request_normalizer.py +0 -0
  80. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/server/responses.py +0 -0
  81. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/server/routes.py +0 -0
  82. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/streaming/__init__.py +0 -0
  83. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/streaming/anthropic_compat.py +0 -0
  84. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/vendors/__init__.py +0 -0
  85. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/vendors/alibaba.py +0 -0
  86. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/vendors/anthropic.py +0 -0
  87. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/vendors/antigravity.py +0 -0
  88. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/vendors/base.py +0 -0
  89. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/vendors/copilot.py +0 -0
  90. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/vendors/copilot_models.py +0 -0
  91. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/vendors/copilot_token_manager.py +0 -0
  92. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/vendors/copilot_urls.py +0 -0
  93. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/vendors/doubao.py +0 -0
  94. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/vendors/kimi.py +0 -0
  95. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/vendors/minimax.py +0 -0
  96. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/vendors/mixins.py +0 -0
  97. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/vendors/native_anthropic.py +0 -0
  98. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/vendors/token_manager.py +0 -0
  99. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/vendors/xiaomi.py +0 -0
  100. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/src/coding/proxy/vendors/zhipu.py +0 -0
  101. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/tests/__init__.py +0 -0
  102. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/tests/test_antigravity.py +0 -0
  103. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/tests/test_app_routes.py +0 -0
  104. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/tests/test_auto_login.py +0 -0
  105. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/tests/test_banner.py +0 -0
  106. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/tests/test_circuit_breaker.py +0 -0
  107. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/tests/test_cli_usage.py +0 -0
  108. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/tests/test_compat.py +0 -0
  109. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/tests/test_config_init.py +0 -0
  110. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/tests/test_config_loader.py +0 -0
  111. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/tests/test_convert_request.py +0 -0
  112. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/tests/test_convert_response.py +0 -0
  113. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/tests/test_convert_sse.py +0 -0
  114. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/tests/test_copilot.py +0 -0
  115. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/tests/test_copilot_convert_request.py +0 -0
  116. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/tests/test_copilot_convert_response.py +0 -0
  117. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/tests/test_copilot_models.py +0 -0
  118. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/tests/test_copilot_urls.py +0 -0
  119. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/tests/test_error_classifier.py +0 -0
  120. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/tests/test_logging_dual_write.py +0 -0
  121. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/tests/test_mixins.py +0 -0
  122. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/tests/test_model_auth.py +0 -0
  123. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/tests/test_model_compat.py +0 -0
  124. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/tests/test_model_constants.py +0 -0
  125. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/tests/test_model_mapper.py +0 -0
  126. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/tests/test_model_pricing.py +0 -0
  127. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/tests/test_model_token.py +0 -0
  128. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/tests/test_model_vendor.py +0 -0
  129. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/tests/test_native_vendors.py +0 -0
  130. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/tests/test_parse_usage.py +0 -0
  131. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/tests/test_pricing.py +0 -0
  132. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/tests/test_quota_guard.py +0 -0
  133. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/tests/test_rate_limit.py +0 -0
  134. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/tests/test_request_normalizer.py +0 -0
  135. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/tests/test_router_chain.py +0 -0
  136. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/tests/test_router_executor.py +0 -0
  137. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/tests/test_runtime_reauth.py +0 -0
  138. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/tests/test_schema.py +0 -0
  139. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/tests/test_streaming_anthropic_compat.py +0 -0
  140. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/tests/test_tier.py +0 -0
  141. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/tests/test_tiers_config.py +0 -0
  142. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/tests/test_time_range.py +0 -0
  143. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/tests/test_token_logger.py +0 -0
  144. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/tests/test_token_manager.py +0 -0
  145. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/tests/test_types.py +0 -0
  146. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/tests/test_vendor_streaming.py +0 -0
  147. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/tests/test_vendors.py +0 -0
  148. {coding_proxy-0.2.4a1 → coding_proxy-0.2.4a2}/tests/test_zhipu.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: coding-proxy
3
- Version: 0.2.4a1
3
+ Version: 0.2.4a2
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
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "coding-proxy"
3
- version = "0.2.4a1"
3
+ version = "0.2.4a2"
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"
@@ -51,13 +51,13 @@ vendors:
51
51
  recovery_timeout_seconds: 300
52
52
  success_threshold: 2
53
53
  quota_guard:
54
- enabled: true
55
- token_budget: 50000000 # 5 小时 token 预算(根据订阅计划调整)
54
+ enabled: false
55
+ token_budget: 60000000 # 5 小时 token 预算(根据订阅计划调整)
56
56
  window_hours: 5.0
57
57
  threshold_percent: 99.0
58
58
  probe_interval_seconds: 300
59
59
  weekly_quota_guard:
60
- enabled: true
60
+ enabled: false
61
61
  token_budget: 800000000 # 一周 token 预算(根据订阅计划调整)
62
62
  window_hours: 168.0 # 7 天滑动窗口
63
63
  threshold_percent: 99.0
@@ -84,7 +84,7 @@ vendors:
84
84
 
85
85
  # Vendor 2: Google Antigravity Plans(中间层,默认禁用)
86
86
  - vendor: antigravity
87
- enabled: true # 启用需配置 OAuth 凭据
87
+ enabled: false # 启用需配置 OAuth 凭据
88
88
  client_id: "${GOOG_CLIENT_ID}" # Google OAuth2 Client ID
89
89
  client_secret: "${GOOG_CLIENT_SECRET}" # Google OAuth2 Client Secret
90
90
  refresh_token: "${GOOG_REFRESH_TOKEN}" # Google OAuth2 Refresh Token
@@ -96,7 +96,7 @@ vendors:
96
96
  recovery_timeout_seconds: 300
97
97
  success_threshold: 2
98
98
  quota_guard:
99
- enabled: true # 启用后按 Premium Requests 配额管理
99
+ enabled: false # 启用后按 Premium Requests 配额管理
100
100
  token_budget: 0
101
101
  window_hours: 24.0
102
102
  threshold_percent: 95.0
@@ -198,7 +198,7 @@ async def show_usage(
198
198
 
199
199
  if cost_totals:
200
200
  total_cost_str = " + ".join(
201
- f"{cur.symbol}{amt:.4f}" for cur, amt in cost_totals.items()
201
+ f"{cur.symbol}{amt:.2f}" for cur, amt in cost_totals.items()
202
202
  )
203
203
  else:
204
204
  total_cost_str = "-"
@@ -50,8 +50,8 @@ class CostValue:
50
50
  amount: float
51
51
  currency: Currency = Currency.default()
52
52
 
53
- def format(self, precision: int = 4) -> str:
54
- """格式化为 ``$0.1234`` 或 ``¥0.1234``."""
53
+ def format(self, precision: int = 2) -> str:
54
+ """格式化为 ``$0.12`` 或 ``¥0.12``."""
55
55
  return f"{self.currency.symbol}{self.amount:.{precision}f}"
56
56
 
57
57
  @property
@@ -1340,7 +1340,7 @@ def _compute_cost_str(rows: list[dict], pricing_table: Any) -> str:
1340
1340
 
1341
1341
  if not cost_totals:
1342
1342
  return "–"
1343
- return " + ".join(f"{cur.symbol}{amt:.4f}" for cur, amt in cost_totals.items())
1343
+ return " + ".join(f"{cur.symbol}{amt:.2f}" for cur, amt in cost_totals.items())
1344
1344
 
1345
1345
 
1346
1346
  # ── 路由注册 ──────────────────────────────────────────────────────────────
@@ -45,11 +45,11 @@ class TestCostValue:
45
45
 
46
46
  def test_format_usd(self):
47
47
  cv = CostValue(amount=0.3421, currency=Currency.USD)
48
- assert cv.format() == "$0.3421"
48
+ assert cv.format() == "$0.34"
49
49
 
50
50
  def test_format_cny(self):
51
51
  cv = CostValue(amount=0.0953, currency=Currency.CNY)
52
- assert cv.format() == "\u00a50.0953"
52
+ assert cv.format() == "\u00a50.10"
53
53
 
54
54
  def test_format_precision(self):
55
55
  cv = CostValue(amount=0.12345678, currency=Currency.USD)
@@ -58,7 +58,7 @@ class TestCostValue:
58
58
 
59
59
  def test_format_zero(self):
60
60
  cv = CostValue(amount=0.0, currency=Currency.USD)
61
- assert cv.format() == "$0.0000"
61
+ assert cv.format() == "$0.00"
62
62
 
63
63
  def test_equality_same_currency(self):
64
64
  a = CostValue(1.0, Currency.USD)
@@ -65,7 +65,7 @@ wheels = [
65
65
 
66
66
  [[package]]
67
67
  name = "coding-proxy"
68
- version = "0.2.4a1"
68
+ version = "0.2.4a2"
69
69
  source = { editable = "." }
70
70
  dependencies = [
71
71
  { name = "aiosqlite" },
File without changes
File without changes
File without changes
File without changes