coding-proxy 0.1.0__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 (131) hide show
  1. coding_proxy-0.1.0/.github/workflows/promote.yml +163 -0
  2. coding_proxy-0.1.0/.github/workflows/release.yml +151 -0
  3. coding_proxy-0.1.0/.gitignore +17 -0
  4. coding_proxy-0.1.0/AGENTS.md +82 -0
  5. coding_proxy-0.1.0/CHANGELOG.md +34 -0
  6. coding_proxy-0.1.0/CLAUDE.md +1 -0
  7. coding_proxy-0.1.0/LICENSE +201 -0
  8. coding_proxy-0.1.0/PKG-INFO +184 -0
  9. coding_proxy-0.1.0/README.md +168 -0
  10. coding_proxy-0.1.0/config.example.yaml +273 -0
  11. coding_proxy-0.1.0/docs/framework.md +1640 -0
  12. coding_proxy-0.1.0/docs/user-guide.md +1490 -0
  13. coding_proxy-0.1.0/docs/zh-CN/README.md +168 -0
  14. coding_proxy-0.1.0/pyproject.toml +32 -0
  15. coding_proxy-0.1.0/src/coding/__init__.py +0 -0
  16. coding_proxy-0.1.0/src/coding/proxy/__init__.py +3 -0
  17. coding_proxy-0.1.0/src/coding/proxy/__main__.py +5 -0
  18. coding_proxy-0.1.0/src/coding/proxy/auth/__init__.py +13 -0
  19. coding_proxy-0.1.0/src/coding/proxy/auth/providers/__init__.py +6 -0
  20. coding_proxy-0.1.0/src/coding/proxy/auth/providers/base.py +35 -0
  21. coding_proxy-0.1.0/src/coding/proxy/auth/providers/github.py +133 -0
  22. coding_proxy-0.1.0/src/coding/proxy/auth/providers/google.py +237 -0
  23. coding_proxy-0.1.0/src/coding/proxy/auth/runtime.py +122 -0
  24. coding_proxy-0.1.0/src/coding/proxy/auth/store.py +74 -0
  25. coding_proxy-0.1.0/src/coding/proxy/cli/__init__.py +151 -0
  26. coding_proxy-0.1.0/src/coding/proxy/cli/auth_commands.py +224 -0
  27. coding_proxy-0.1.0/src/coding/proxy/compat/__init__.py +30 -0
  28. coding_proxy-0.1.0/src/coding/proxy/compat/canonical.py +193 -0
  29. coding_proxy-0.1.0/src/coding/proxy/compat/session_store.py +137 -0
  30. coding_proxy-0.1.0/src/coding/proxy/config/__init__.py +6 -0
  31. coding_proxy-0.1.0/src/coding/proxy/config/auth_schema.py +24 -0
  32. coding_proxy-0.1.0/src/coding/proxy/config/loader.py +139 -0
  33. coding_proxy-0.1.0/src/coding/proxy/config/resiliency.py +46 -0
  34. coding_proxy-0.1.0/src/coding/proxy/config/routing.py +279 -0
  35. coding_proxy-0.1.0/src/coding/proxy/config/schema.py +280 -0
  36. coding_proxy-0.1.0/src/coding/proxy/config/server.py +23 -0
  37. coding_proxy-0.1.0/src/coding/proxy/config/vendors.py +53 -0
  38. coding_proxy-0.1.0/src/coding/proxy/convert/__init__.py +14 -0
  39. coding_proxy-0.1.0/src/coding/proxy/convert/anthropic_to_gemini.py +352 -0
  40. coding_proxy-0.1.0/src/coding/proxy/convert/anthropic_to_openai.py +352 -0
  41. coding_proxy-0.1.0/src/coding/proxy/convert/gemini_sse_adapter.py +169 -0
  42. coding_proxy-0.1.0/src/coding/proxy/convert/gemini_to_anthropic.py +98 -0
  43. coding_proxy-0.1.0/src/coding/proxy/convert/openai_to_anthropic.py +88 -0
  44. coding_proxy-0.1.0/src/coding/proxy/logging/__init__.py +49 -0
  45. coding_proxy-0.1.0/src/coding/proxy/logging/db.py +308 -0
  46. coding_proxy-0.1.0/src/coding/proxy/logging/stats.py +129 -0
  47. coding_proxy-0.1.0/src/coding/proxy/model/__init__.py +93 -0
  48. coding_proxy-0.1.0/src/coding/proxy/model/auth.py +32 -0
  49. coding_proxy-0.1.0/src/coding/proxy/model/compat.py +153 -0
  50. coding_proxy-0.1.0/src/coding/proxy/model/constants.py +21 -0
  51. coding_proxy-0.1.0/src/coding/proxy/model/pricing.py +70 -0
  52. coding_proxy-0.1.0/src/coding/proxy/model/token.py +64 -0
  53. coding_proxy-0.1.0/src/coding/proxy/model/vendor.py +218 -0
  54. coding_proxy-0.1.0/src/coding/proxy/pricing.py +100 -0
  55. coding_proxy-0.1.0/src/coding/proxy/routing/__init__.py +47 -0
  56. coding_proxy-0.1.0/src/coding/proxy/routing/circuit_breaker.py +152 -0
  57. coding_proxy-0.1.0/src/coding/proxy/routing/error_classifier.py +67 -0
  58. coding_proxy-0.1.0/src/coding/proxy/routing/executor.py +453 -0
  59. coding_proxy-0.1.0/src/coding/proxy/routing/model_mapper.py +90 -0
  60. coding_proxy-0.1.0/src/coding/proxy/routing/quota_guard.py +169 -0
  61. coding_proxy-0.1.0/src/coding/proxy/routing/rate_limit.py +159 -0
  62. coding_proxy-0.1.0/src/coding/proxy/routing/retry.py +82 -0
  63. coding_proxy-0.1.0/src/coding/proxy/routing/router.py +84 -0
  64. coding_proxy-0.1.0/src/coding/proxy/routing/session_manager.py +62 -0
  65. coding_proxy-0.1.0/src/coding/proxy/routing/tier.py +171 -0
  66. coding_proxy-0.1.0/src/coding/proxy/routing/usage_parser.py +193 -0
  67. coding_proxy-0.1.0/src/coding/proxy/routing/usage_recorder.py +131 -0
  68. coding_proxy-0.1.0/src/coding/proxy/server/__init__.py +1 -0
  69. coding_proxy-0.1.0/src/coding/proxy/server/app.py +142 -0
  70. coding_proxy-0.1.0/src/coding/proxy/server/factory.py +175 -0
  71. coding_proxy-0.1.0/src/coding/proxy/server/request_normalizer.py +139 -0
  72. coding_proxy-0.1.0/src/coding/proxy/server/responses.py +74 -0
  73. coding_proxy-0.1.0/src/coding/proxy/server/routes.py +264 -0
  74. coding_proxy-0.1.0/src/coding/proxy/streaming/__init__.py +1 -0
  75. coding_proxy-0.1.0/src/coding/proxy/streaming/anthropic_compat.py +484 -0
  76. coding_proxy-0.1.0/src/coding/proxy/vendors/__init__.py +29 -0
  77. coding_proxy-0.1.0/src/coding/proxy/vendors/anthropic.py +44 -0
  78. coding_proxy-0.1.0/src/coding/proxy/vendors/antigravity.py +328 -0
  79. coding_proxy-0.1.0/src/coding/proxy/vendors/base.py +353 -0
  80. coding_proxy-0.1.0/src/coding/proxy/vendors/copilot.py +702 -0
  81. coding_proxy-0.1.0/src/coding/proxy/vendors/copilot_models.py +438 -0
  82. coding_proxy-0.1.0/src/coding/proxy/vendors/copilot_token_manager.py +167 -0
  83. coding_proxy-0.1.0/src/coding/proxy/vendors/copilot_urls.py +16 -0
  84. coding_proxy-0.1.0/src/coding/proxy/vendors/mixins.py +71 -0
  85. coding_proxy-0.1.0/src/coding/proxy/vendors/token_manager.py +128 -0
  86. coding_proxy-0.1.0/src/coding/proxy/vendors/zhipu.py +243 -0
  87. coding_proxy-0.1.0/tests/__init__.py +0 -0
  88. coding_proxy-0.1.0/tests/test_antigravity.py +339 -0
  89. coding_proxy-0.1.0/tests/test_app_routes.py +643 -0
  90. coding_proxy-0.1.0/tests/test_auto_login.py +454 -0
  91. coding_proxy-0.1.0/tests/test_circuit_breaker.py +49 -0
  92. coding_proxy-0.1.0/tests/test_cli_usage.py +110 -0
  93. coding_proxy-0.1.0/tests/test_compat.py +72 -0
  94. coding_proxy-0.1.0/tests/test_config_loader.py +512 -0
  95. coding_proxy-0.1.0/tests/test_convert_request.py +319 -0
  96. coding_proxy-0.1.0/tests/test_convert_response.py +289 -0
  97. coding_proxy-0.1.0/tests/test_convert_sse.py +483 -0
  98. coding_proxy-0.1.0/tests/test_copilot.py +871 -0
  99. coding_proxy-0.1.0/tests/test_copilot_convert_request.py +419 -0
  100. coding_proxy-0.1.0/tests/test_copilot_convert_response.py +217 -0
  101. coding_proxy-0.1.0/tests/test_copilot_models.py +193 -0
  102. coding_proxy-0.1.0/tests/test_copilot_urls.py +67 -0
  103. coding_proxy-0.1.0/tests/test_currency.py +200 -0
  104. coding_proxy-0.1.0/tests/test_error_classifier.py +176 -0
  105. coding_proxy-0.1.0/tests/test_mixins.py +105 -0
  106. coding_proxy-0.1.0/tests/test_model_auth.py +97 -0
  107. coding_proxy-0.1.0/tests/test_model_compat.py +471 -0
  108. coding_proxy-0.1.0/tests/test_model_constants.py +60 -0
  109. coding_proxy-0.1.0/tests/test_model_mapper.py +91 -0
  110. coding_proxy-0.1.0/tests/test_model_pricing.py +79 -0
  111. coding_proxy-0.1.0/tests/test_model_token.py +155 -0
  112. coding_proxy-0.1.0/tests/test_model_vendor.py +695 -0
  113. coding_proxy-0.1.0/tests/test_parse_usage.py +284 -0
  114. coding_proxy-0.1.0/tests/test_pricing.py +237 -0
  115. coding_proxy-0.1.0/tests/test_quota_guard.py +144 -0
  116. coding_proxy-0.1.0/tests/test_rate_limit.py +111 -0
  117. coding_proxy-0.1.0/tests/test_request_normalizer.py +82 -0
  118. coding_proxy-0.1.0/tests/test_router_chain.py +1093 -0
  119. coding_proxy-0.1.0/tests/test_router_executor.py +863 -0
  120. coding_proxy-0.1.0/tests/test_runtime_reauth.py +194 -0
  121. coding_proxy-0.1.0/tests/test_schema.py +154 -0
  122. coding_proxy-0.1.0/tests/test_streaming_anthropic_compat.py +673 -0
  123. coding_proxy-0.1.0/tests/test_tier.py +317 -0
  124. coding_proxy-0.1.0/tests/test_tiers_config.py +234 -0
  125. coding_proxy-0.1.0/tests/test_token_logger.py +442 -0
  126. coding_proxy-0.1.0/tests/test_token_manager.py +184 -0
  127. coding_proxy-0.1.0/tests/test_types.py +222 -0
  128. coding_proxy-0.1.0/tests/test_vendor_streaming.py +394 -0
  129. coding_proxy-0.1.0/tests/test_vendors.py +442 -0
  130. coding_proxy-0.1.0/tests/test_zhipu.py +260 -0
  131. coding_proxy-0.1.0/uv.lock +445 -0
@@ -0,0 +1,163 @@
1
+ # =============================================================================
2
+ # coding-proxy: Prerelease → Stable Promotion Workflow
3
+ # =============================================================================
4
+ # Trigger: Manual workflow_dispatch with tag_name input
5
+ # Purpose: Promote a validated TestPyPI prerelease to PyPI production
6
+ #
7
+ # Flow:
8
+ # Job 1 (validate): Verify target release exists AND is a prerelease
9
+ # Job 2 (promote): Update GitHub Release metadata + build/publish to PyPI
10
+ #
11
+ # Safety Guarantees:
12
+ # - Refuses to promote non-prerelease releases (idempotency guard)
13
+ # - Uses environment: pypi for deployment approval gate (human gate)
14
+ # - Concurrency group prevents simultaneous promotions of same tag
15
+ # - Rebuilds from git tag for deterministic, reproducible artifacts
16
+ #
17
+ # Paired with: release.yml (initial release creation)
18
+ #
19
+ # Pre-requisites (same auth options as release.yml):
20
+ # Option A — OIDC Trusted Publishing:
21
+ # 1. Create GitHub Environment: "pypi" with required reviewers
22
+ # 2. Configure Trusted Publisher on PyPI admin panel
23
+ # Option B — API Token Fallback:
24
+ # 1. Set repository secret: PYPI_API_TOKEN
25
+ # 2. (Optional) Create "pypi" environment for deployment guards
26
+ #
27
+ # References:
28
+ # [1] https://docs.github.com/en/rest/releases/releases#update-a-release
29
+ # [2] https://packaging.python.org/guides/publishing-package-distribution-releases-using-github-actions-ci-cd-workflows/
30
+ # =============================================================================
31
+
32
+ name: Promote Prerelease to PyPI
33
+
34
+ on:
35
+ workflow_dispatch:
36
+ inputs:
37
+ tag_name:
38
+ description: '待提升的 prerelease tag(如 v0.2.0a1)'
39
+ required: true
40
+ type: string
41
+
42
+ permissions:
43
+ contents: read
44
+
45
+ concurrency:
46
+ group: promote-${{ inputs.tag_name }}
47
+ cancel-in-progress: false
48
+
49
+ jobs:
50
+ # ===========================================================================
51
+ # Job 1: VALIDATE -- Confirm release exists and is a prerelease
52
+ # ===========================================================================
53
+ validate:
54
+ name: Validate prerelease status
55
+ runs-on: ubuntu-latest
56
+ timeout-minutes: 5
57
+
58
+ steps:
59
+ - name: Check release exists and is a prerelease
60
+ uses: actions/github-script@v7
61
+ id: check-release
62
+ with:
63
+ script: |
64
+ const tag = context.payload.inputs.tag_name;
65
+ const { owner, repo } = context.repo;
66
+
67
+ const release = await github.rest.releases.getReleaseByTag({
68
+ owner,
69
+ repo,
70
+ tag,
71
+ });
72
+
73
+ const isPrerelease = release.data.prerelease;
74
+ const releaseId = release.data.id;
75
+ const tagName = release.data.tag_name;
76
+
77
+ if (!isPrerelease) {
78
+ core.setFailed(
79
+ `Release ${tagName} is NOT a prerelease. ` +
80
+ `Only prereleases can be promoted to stable.`
81
+ );
82
+ }
83
+
84
+ core.setOutput('release_id', releaseId);
85
+ core.setOutput('tag_name', tagName);
86
+ core.info(`✅ Validated: release #${releaseId} (${tagName}) is a prerelease`);
87
+
88
+ # ===========================================================================
89
+ # Job 2: PROMOTE -- Update release + publish to PyPI Production
90
+ # ===========================================================================
91
+ promote:
92
+ name: Promote to PyPI Production
93
+ runs-on: ubuntu-latest
94
+ needs: validate
95
+ timeout-minutes: 15
96
+ environment:
97
+ name: pypi
98
+ url: https://pypi.org/p/coding-proxy
99
+ permissions:
100
+ contents: write # 更新 Release 元数据所需
101
+ id-token: write # OIDC Trusted Publishing 所需
102
+
103
+ steps:
104
+ # -----------------------------------------------------------------------
105
+ # Step 1: 检出精确的 git tag 用于确定性重建
106
+ # -----------------------------------------------------------------------
107
+ - name: Checkout repository at release tag
108
+ uses: actions/checkout@v4
109
+ with:
110
+ ref: ${{ needs.validate.outputs.tag_name }}
111
+ persist-credentials: false
112
+
113
+ # -----------------------------------------------------------------------
114
+ # Step 2: 更新 GitHub Release: prerelease=false, make_latest=true
115
+ # -----------------------------------------------------------------------
116
+ - name: Promote release to stable
117
+ uses: actions/github-script@v7
118
+ with:
119
+ script: |
120
+ const releaseId = ${{ needs.validate.outputs.release_id }};
121
+ const { owner, repo } = context.repo;
122
+
123
+ await github.rest.releases.update({
124
+ owner,
125
+ repo,
126
+ release_id: releaseId,
127
+ prerelease: false,
128
+ make_latest: true,
129
+ });
130
+
131
+ core.notice(
132
+ `✅ Release #${releaseId} promoted to stable (make_latest=true)`
133
+ );
134
+
135
+ # -----------------------------------------------------------------------
136
+ # Step 3: 从 tagged source 构建分发包
137
+ # -----------------------------------------------------------------------
138
+ - name: Set up Python
139
+ uses: actions/setup-python@v5
140
+ with:
141
+ python-version: "3.13"
142
+
143
+ - name: Set up uv
144
+ uses: astral-sh/setup-uv@v4
145
+ with:
146
+ enable-cache: true
147
+
148
+ - name: Install build dependencies
149
+ run: uv pip install --system build twine
150
+
151
+ - name: Build sdist and wheel
152
+ run: python -m build
153
+
154
+ - name: Check package metadata
155
+ run: twine check dist/*
156
+
157
+ # -----------------------------------------------------------------------
158
+ # Step 4: 发布到 PyPI Production
159
+ # -----------------------------------------------------------------------
160
+ - name: Publish to PyPI
161
+ uses: pypa/gh-action-pypi-publish@release/v1
162
+ with:
163
+ password: ${{ secrets.PYPI_API_TOKEN }}
@@ -0,0 +1,151 @@
1
+ # =============================================================================
2
+ # coding-proxy: PyPI Publishing Workflow (Initial Release)
3
+ # =============================================================================
4
+ # Trigger: GitHub Release publication event
5
+ # Architecture: Build-Publish Separation (PyPA security best practice)
6
+ # Paired with: promote.yml (prerelease → stable promotion gate)
7
+ # - Job 1 (build): Low privileges, produces sdist+wheel artifacts
8
+ # - Job 2 (publish-testpypi): Publish to TestPyPI (prereleases only)
9
+ # - Job 3 (publish-pypi): Publish to PyPI (stable releases / hotfixes)
10
+ #
11
+ # Routing Logic:
12
+ # - prerelease == true --> TestPyPI (with skip-existing tolerance)
13
+ # --> THEN use promote.yml to promote to PyPI after validation
14
+ # - prerelease == false --> PyPI production (direct stable release, e.g. hotfixes)
15
+ #
16
+ # Promotion Flow (see promote.yml):
17
+ # 1. Create release with prerelease: true --> builds + publishes to TestPyPI
18
+ # 2. Human validates package on TestPyPI
19
+ # 3. Run promote.yml (workflow_dispatch) --> promotes to PyPI production
20
+ #
21
+ # Pre-requisites (choose ONE authentication method):
22
+ #
23
+ # Option A — OIDC Trusted Publishing (recommended, no secrets needed):
24
+ # 1. Create GitHub Environments: "pypi" and "testpypi"
25
+ # 2. Configure Trusted Publishers on PyPI/TestPyPI admin panels
26
+ # 3. (Recommended) Set "Required reviewers" on "pypi" environment
27
+ #
28
+ # Option B — API Token Fallback (simpler initial setup):
29
+ # 1. Set repository secrets: PYPI_API_TOKEN and/or TEST_PYPI_API_TOKEN
30
+ # 2. (Optional) Create "pypi"/"testpypi" environments for deployment guards
31
+ # If environments are not created, remove the `environment:` blocks below.
32
+ #
33
+ # References:
34
+ # [1] https://packaging.python.org/guides/publishing-package-distribution-releases-using-github-actions-ci-cd-workflows/
35
+ # [2] https://github.com/pypa/gh-action-pypi-publish
36
+ # [3] https://docs.pypi.org/trusted-publishers/using-a-publisher/
37
+ # =============================================================================
38
+
39
+ name: Release / Publish to PyPI
40
+
41
+ on:
42
+ release:
43
+ types: [published]
44
+
45
+ permissions:
46
+ contents: read
47
+
48
+ concurrency:
49
+ group: ${{ github.workflow }}-${{ github.ref }}
50
+ cancel-in-progress: true
51
+
52
+ jobs:
53
+ # ===========================================================================
54
+ # Job 1: BUILD -- Produce distribution artifacts (low privilege isolation)
55
+ # ===========================================================================
56
+ build:
57
+ name: Build distributions
58
+ runs-on: ubuntu-latest
59
+ timeout-minutes: 10
60
+
61
+ steps:
62
+ - name: Checkout repository
63
+ uses: actions/checkout@v4
64
+ with:
65
+ persist-credentials: false
66
+
67
+ - name: Set up Python
68
+ uses: actions/setup-python@v5
69
+ with:
70
+ python-version: "3.13"
71
+
72
+ - name: Set up uv
73
+ uses: astral-sh/setup-uv@v4
74
+ with:
75
+ enable-cache: true
76
+
77
+ - name: Install build dependencies
78
+ run: uv pip install --system build twine
79
+
80
+ - name: Build sdist and wheel
81
+ run: python -m build
82
+
83
+ - name: Check package metadata
84
+ run: twine check dist/*
85
+
86
+ - name: Upload build artifacts
87
+ uses: actions/upload-artifact@v4
88
+ with:
89
+ name: dist
90
+ path: dist/
91
+ retention-days: 14
92
+
93
+ # ===========================================================================
94
+ # Job 2: PUBLISH TO TESTPYPI -- Prerelease / staging releases only
95
+ # ===========================================================================
96
+ publish-testpypi:
97
+ name: Publish to TestPyPI
98
+ runs-on: ubuntu-latest
99
+ needs: build
100
+ if: github.event.release.prerelease == true
101
+ timeout-minutes: 10
102
+ environment:
103
+ name: testpypi
104
+ url: https://test.pypi.org/p/coding-proxy
105
+ permissions:
106
+ id-token: write
107
+ contents: read
108
+
109
+ steps:
110
+ - name: Download build artifacts
111
+ uses: actions/download-artifact@v4
112
+ with:
113
+ name: dist
114
+ path: dist/
115
+
116
+ - name: Publish to TestPyPI
117
+ uses: pypa/gh-action-pypi-publish@release/v1
118
+ with:
119
+ password: ${{ secrets.TEST_PYPI_API_TOKEN }}
120
+ repository-url: https://test.pypi.org/legacy/
121
+ skip-existing: true
122
+ attestations: false # TestPyPI 不支持 attestations,必须显式禁用
123
+ verbose: true # 启用详细日志以获取 400 错误响应体
124
+
125
+ # ===========================================================================
126
+ # Job 3: PUBLISH TO PYPI -- Production releases only
127
+ # ===========================================================================
128
+ publish-pypi:
129
+ name: Publish to PyPI
130
+ runs-on: ubuntu-latest
131
+ needs: build
132
+ if: github.event.release.prerelease == false
133
+ timeout-minutes: 10
134
+ environment:
135
+ name: pypi
136
+ url: https://pypi.org/p/coding-proxy
137
+ permissions:
138
+ id-token: write
139
+ contents: read
140
+
141
+ steps:
142
+ - name: Download build artifacts
143
+ uses: actions/download-artifact@v4
144
+ with:
145
+ name: dist
146
+ path: dist/
147
+
148
+ - name: Publish to PyPI
149
+ uses: pypa/gh-action-pypi-publish@release/v1
150
+ with:
151
+ password: ${{ secrets.PYPI_API_TOKEN }}
@@ -0,0 +1,17 @@
1
+ __pycache__/
2
+ *.pyc
3
+ *.pyo
4
+ .venv/
5
+ *.db
6
+ *.sqlite
7
+ *.egg-info/
8
+ dist/
9
+ build/
10
+ *.whl
11
+ .uv/
12
+
13
+ # Custom
14
+ .idea/
15
+ .temp/
16
+ config.yaml
17
+ .claude/.prompts.md
@@ -0,0 +1,82 @@
1
+ # AGENTS.md
2
+
3
+ ## Collaboration Protocol (协作协议)
4
+
5
+ 本文件旨在规范 AI Agent(Claude Code、Antigravity 等)在本项目中的代码与文档协作行为。
6
+
7
+ - **Core Language**: Output MUST be in **Chinese (Simplified)** unless serving code/technical constraints.
8
+ - **Tone**: Professional, precise, and evidence-based.
9
+
10
+ ## Project Positioning (项目定位)
11
+
12
+ 参考 README.md
13
+
14
+ ## Engineering Code of Conduct (工程行为准则)
15
+
16
+ **Core Philosophy**: **Entropy Reduction (熵减)**. 通过上下文锚定、复用驱动与标准化流水线,对抗软件系统的无序熵增。
17
+
18
+ ### 道 (Mindset - 认知心法)
19
+
20
+ - **Context-Driven (上下文驱动)**: 上下文是第一性要素 (Context Quality First)。任何变更需建立在深度理解之上(CDD),拒绝基于关键字匹配的机械式修改。
21
+ - **Minimal Intervention (最小干预)**: 遵循奥卡姆剃刀与 YAGNI 原则,仅实施必要的变更,推崇演进式设计 (Evolutionary Design) 而非过度设计。
22
+ - **Evidence-Based (循证工程)**: 杜绝主观臆断,核心决策需以权威文献(IEEE 格式)为佐证,构建 Feedback Loops 以验证假设。
23
+ - **Systemic Integrity (系统完整性)**: 具备全局视角与二阶思维 (Second-Order Thinking),评估变更对上下游依赖及整个生态(Engine, Adapter, Agent, UI)的“涟漪效应”,优先保障整体稳定性与逻辑自洽。
24
+
25
+ ### 法 (Strategy - 架构原则)
26
+
27
+ - **Plan Node Default (默认规划模式)**: 面对任何非琐碎任务(预估步骤 > 3 或涉及架构级决策),**必须**率先进入 Plan 模式。规划产物需明确界定:功能边界、边缘 Case 应对策略、与现有逻辑的交互锚点以及预计改动的爆炸半径。
28
+ - **Subagent Strategy (子代理并发策略)**: 面对高复杂度命题,严禁主 Agent 单点统揽。应贯彻“算力换空间”思路,果断编排 Subagent 进行任务拆解与并行攻坚,主 Agent 的职责需严格收敛于上下文协同与最终成果的组装整合。
29
+ - **Verification Before Done (交付前验证定式)**: 严禁在缺乏确凿运行证据的情况下标记任务为“已完成”。交付阶段**强制要求**提供客观自证材料:Diff 变更分析、测试用例覆盖、实施日志截图及核心链路边缘 Case 验证结果,并时刻以“方案是否能通过 Staff Engineer 严格审查”的视角自检。
30
+ - **Reuse-Driven (复用驱动)**: Composition over Construction。系统变更**必须**主动参考业界经典设计模式与最佳实践。在进入实质性编码前,需率先对相关领域的成熟范式进行深度调研,并结合当前项目上下文输出充分的关联分析与方案梳理。坚决贯彻“拿来主义”,优先通过组合与集成来构建系统,防范闭门造车与重复造轮子。
31
+ - **Boundary Management (边界管理)**: 严控模块/Agent 间的职责边界与契约,确保高内聚低耦合,防范隐式依赖穿透。
32
+ - **Orthogonal Decomposition (正交分解)**: 坚持“正交地提取概念主体”。识别系统中独立变化的维度并进行解耦(如机制与策略分离),确保单一概念主体的变更具备局部性,避免逻辑纠缠。
33
+ - **Feedback Loops (反馈闭环)**:构建“设计-实现-验证”的完整闭环,确保每一项工程行动都能产生可观测的反馈信号(测试、日志、监控),以验证假设并指导迭代。
34
+ - **Evolutionary Design (演进式设计)**: 将系统视为有机体,通过将 AI 错误转化为经验约束 (Negative Prompts) 和持久化知识,实现系统的自我进化与熵减。
35
+ - **Second-Order Thinking (二阶思维)**:不只关注变更的直接结果,更要预测“结果的结果”(如引入缓存导致的陈旧数据、重试机制引发的雪崩),未雨绸缪防范隐性风险。
36
+ - **Single Source of Truth (单一事实源)**:严格维护唯一的权威定义源。引用时**必须**使用轻量级指针 (Link/ID) 而非数据副本 (Copy-Paste),从根源消除断裂 (Split-Brain) 风险。
37
+ - **Proactive Navigation (主动导航)**: 智能体不应止步于被动响应,需即时转化为“领航者”。在交付任务结果的同时,**必须**基于上下文预判并提出**下一步最佳行动建议 (Next Best Action)**。不仅交付“答案”,更要交付“路径”,消除用户决策的认知摩擦,确保持续的熵减动量。
38
+
39
+ ### 术 (Tactics - 执行规范)
40
+
41
+ - **Vibe Coding Pipeline**: 遵循 **Specification-Driven (规划驱动)** + **Context-Anchored (上下文锚定)** + **AI-Pair (AI 结对)** 模式,将开发固化为可审计的流水线,避免代码腐化为无法维护的“大泥球 (Big Ball of Mud)”。
42
+ - **Visual Documentation (图文并茂)**: 对于复杂逻辑,优先使用 Mermaid 图表(Sequence/Flowchart/Class)辅助说明,构建“图文并茂”的直观文档。
43
+ - **Direct Hyperlinking (直接跳转)**: 在文档中提及 Repo 内其他资源(文档/代码)时,**必须**构建可跳转的相对路径链接(如 `[Doc Name](./path.md)`),严禁使用“死文本”引用,以降低信息检索熵。
44
+ - **Operational Excellence (卓越运营)**:
45
+ 1. **Git Hygiene**: 如非显性要求,严禁调用 git commit;
46
+ 2. **Temp Management**: 临时产物(执行计划等)一律收敛至 `.temp/` 并及时清理;
47
+ 3. **Link Validity**: 确保所有引用的 URL 可访问且具备明确的上下文价值;
48
+ 4. **Git Commit**: 在需要提交变更到 Git 时,一律使用 Shell 调用 Claude Code 的自定义 Slash Command: `/commit` 进行 git commit 操作(若环境中未安装 Claude Code,则直接读取 `~/.claude/commands/commit.md`,按照其中的规则进行 git commit 操作)。不要执行 Rebase。
49
+ - **Package Management Standardization (包管理规范)**:
50
+ 1. **Python**: 严禁使用 pip/poetry,**必须**统一使用 `uv` 进行包管理与脚本执行(如 `uv run`);
51
+ 2. **JavaScript/TypeScript**: 严禁使用 npm/yarn,**必须**统一使用 `pnpm` 进行包管理与脚本执行。
52
+ - **Database Management**: 谨慎操作,数据迁移、测试等操作严禁将现有数据删除。
53
+
54
+ ## Documentation Standards (文档规范)
55
+
56
+ ### Mermaid Visualization Norms (Mermaid 可视化规范)
57
+
58
+ - **色彩语义与兼容性**:为图表节点配置具备语义辨识度的色彩,并确保在深色模式(Dark Mode)下具有极高的对比度与清晰度。
59
+ - **逻辑模块化解构**:针对业务跨度较大的架构流程,强制采用 `subgraph` 容器进行层级解构与边界划分,以增强图表的自解说(Self-explaining)能力。
60
+
61
+ ### Reference Specifications (IEEE)
62
+
63
+ 为保障工程决策的可追溯性与学术严谨性,核心引用需遵循 **IEEE 标准引用格式**。
64
+
65
+ > **模版准则**:[编号] 作者缩写. 姓, "文章标题," _刊名/会议名缩写 (斜体)_, 卷号, 期数, 页码, 年份.
66
+
67
+ ```latex
68
+ [1] A. Author, B. Author, and C. Author, "Title of paper," *Abbrev. Title of Journal*, vol. X, no. Y, pp. XX–XX, Year.
69
+ ```
70
+
71
+ **引用实践**
72
+
73
+ - **文内锚定**:采用标准上标链接形式:`描述内容<sup>[[1]](#ref1)</sup>`。
74
+ - **文献索引**:底层采用 HTML 锚点 `id` 实现跳转稳定性。
75
+
76
+ ```latex
77
+ <a id="ref1"></a>[1] A. Vaswani et al., "Attention is all you need," Adv. Neural Inf. Process. Syst., vol. 30, pp. 5998–6008, 2017.
78
+ ```
79
+
80
+ ## Knowledge Map (知识索引)
81
+
82
+ (WIP)
@@ -0,0 +1,34 @@
1
+ # Changelog
2
+
3
+ 本文件基于 [Keep a Changelog](https://keepachangelog.com/zh-CN/) 规范维护,版本号遵循 [语义化版本](https://semver.org/lang/zh-CN/)。
4
+
5
+ ## [Unreleased]
6
+
7
+ ## [v0.1.0] — 2026-04-05
8
+
9
+ ### ✨ 亮点特性
10
+
11
+ > **coding-proxy MVP 版本发布!** 一行环境变量,让 Claude Code 拥有永不宕机的多后端智能代理——主服务故障时毫秒级自动切换至备用通道,编码心流零中断。
12
+
13
+ | 特性 | 价值 |
14
+ | :--------------------- | :------------------------------------------------------------------------------------------------------- |
15
+ | **N-tiers 故障转移** | 灵活编排的供应商优先级与降级链路;<br/>默认 Claude → GitHub Copilot → Antigravity → GLM 全链路自动降级; |
16
+ | **智能熔断器** | 状态机防护雪崩,指数退避自动恢复; |
17
+ | **Token 用量成本看板** | SQLite 本地存储,CLI 多维统计(按天/供应商/模型); |
18
+ | **OAuth2 内置集成** | GitHub Device Flow / Google OAuth 开箱即用,令牌自动轮转; |
19
+ | **协议双向转换** | Anthropic ↔ OpenAI/Gemini 双向无缝翻译; |
20
+ | **模型名自助映射** | 自定义模型转发规则,`claude-*` → `glm-*` 一键切; |
21
+ | **零侵入轻量透明代理** | 开箱即用,配置 `ANTHROPIC_BASE_URL` 即接入,FastAPI 异步架构,交互全透明; |
22
+ | **SSE 流式全链路** | 流式请求完整透传,跨协议 SSE 转换零感知; |
23
+ | **双窗口配额守卫** | 5h 滑动窗口 + 周配额双重护盾,超额前主动预警; |
24
+
25
+ ### 🔧 更多特性
26
+
27
+ - 模型定价表支持,按供应商/模型细粒度成本追踪;
28
+ - 指数退避重试机制,可配置最大重试次数与退避策略;
29
+ - Vendor 自动兼容性降级决策;
30
+ - 速率限制头解析与智能等待,精确计算恢复时间;
31
+ - Copilot 421 Misdirection 自动重试;
32
+ - 优雅停机与资源清理,进程退出无残留;
33
+
34
+ [0.1.0]: https://github.com/ThreeFish-AI/coding-proxy/releases/tag/v0.1.0
@@ -0,0 +1 @@
1
+ AGENTS.md
@@ -0,0 +1,201 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "[]"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recommend that a
185
+ file or class name and description of purpose be included on the
186
+ same "printed page" as the copyright notice for easier
187
+ identification within third-party archives.
188
+
189
+ Copyright [yyyy] [name of copyright owner]
190
+
191
+ Licensed under the Apache License, Version 2.0 (the "License");
192
+ you may not use this file except in compliance with the License.
193
+ You may obtain a copy of the License at
194
+
195
+ http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+ Unless required by applicable law or agreed to in writing, software
198
+ distributed under the License is distributed on an "AS IS" BASIS,
199
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ See the License for the specific language governing permissions and
201
+ limitations under the License.