workbuddy2api 2.0.1__tar.gz → 2.0.3__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.
- {workbuddy2api-2.0.1 → workbuddy2api-2.0.3}/PKG-INFO +83 -37
- {workbuddy2api-2.0.1 → workbuddy2api-2.0.3}/README.md +82 -36
- {workbuddy2api-2.0.1 → workbuddy2api-2.0.3}/pyproject.toml +1 -1
- {workbuddy2api-2.0.1 → workbuddy2api-2.0.3}/src/codebuddy_proxy/__main__.py +85 -15
- {workbuddy2api-2.0.1 → workbuddy2api-2.0.3}/src/codebuddy_proxy/codebuddy_client_demo.py +48 -3
- {workbuddy2api-2.0.1 → workbuddy2api-2.0.3}/src/workbuddy2api.egg-info/PKG-INFO +83 -37
- {workbuddy2api-2.0.1 → workbuddy2api-2.0.3}/LICENSE +0 -0
- {workbuddy2api-2.0.1 → workbuddy2api-2.0.3}/setup.cfg +0 -0
- {workbuddy2api-2.0.1 → workbuddy2api-2.0.3}/src/codebuddy_proxy/anthropic_adapter.py +0 -0
- {workbuddy2api-2.0.1 → workbuddy2api-2.0.3}/src/codebuddy_proxy/desensitize.py +0 -0
- {workbuddy2api-2.0.1 → workbuddy2api-2.0.3}/src/codebuddy_proxy/dsml_parser.py +0 -0
- {workbuddy2api-2.0.1 → workbuddy2api-2.0.3}/src/codebuddy_proxy/projection_metadata.py +0 -0
- {workbuddy2api-2.0.1 → workbuddy2api-2.0.3}/src/codebuddy_proxy/responses_adapter.py +0 -0
- {workbuddy2api-2.0.1 → workbuddy2api-2.0.3}/src/codebuddy_proxy/responses_projection.py +0 -0
- {workbuddy2api-2.0.1 → workbuddy2api-2.0.3}/src/workbuddy2api.egg-info/SOURCES.txt +0 -0
- {workbuddy2api-2.0.1 → workbuddy2api-2.0.3}/src/workbuddy2api.egg-info/dependency_links.txt +0 -0
- {workbuddy2api-2.0.1 → workbuddy2api-2.0.3}/src/workbuddy2api.egg-info/entry_points.txt +0 -0
- {workbuddy2api-2.0.1 → workbuddy2api-2.0.3}/src/workbuddy2api.egg-info/requires.txt +0 -0
- {workbuddy2api-2.0.1 → workbuddy2api-2.0.3}/src/workbuddy2api.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: workbuddy2api
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.3
|
|
4
4
|
Summary: Local OpenAI/Responses/Anthropic compatible proxy for CodeBuddy
|
|
5
5
|
Requires-Python: >=3.10
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
@@ -30,21 +30,40 @@ Dynamic: license-file
|
|
|
30
30
|
|
|
31
31
|
## 安装
|
|
32
32
|
|
|
33
|
-
推荐使用 [uv](https://docs.astral.sh/uv/)
|
|
33
|
+
推荐使用 [uv](https://docs.astral.sh/uv/) 从 PyPI 运行:
|
|
34
34
|
|
|
35
35
|
```bash
|
|
36
36
|
# 安装 uv
|
|
37
37
|
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
38
38
|
|
|
39
|
-
#
|
|
40
|
-
uv run codebuddy_proxy
|
|
39
|
+
# 运行最新可用版本(uv 会自动创建环境并安装依赖)
|
|
40
|
+
uv run --with workbuddy2api python -m codebuddy_proxy \
|
|
41
|
+
--log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
42
|
+
|
|
43
|
+
# 强制刷新缓存后运行最新版本
|
|
44
|
+
uv run --refresh-package workbuddy2api --with workbuddy2api \
|
|
45
|
+
python -m codebuddy_proxy \
|
|
46
|
+
--log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
41
47
|
```
|
|
42
48
|
|
|
43
|
-
|
|
49
|
+
后续启动无需手动激活虚拟环境,重复执行上述 `uv run` 命令即可。
|
|
50
|
+
|
|
51
|
+
### 本地源码启动
|
|
52
|
+
|
|
53
|
+
在项目根目录执行以下命令,使用当前工作区源码而不是 PyPI 中的已发布版本:
|
|
44
54
|
|
|
45
55
|
```bash
|
|
46
|
-
|
|
47
|
-
|
|
56
|
+
# 同步本地项目依赖
|
|
57
|
+
uv sync
|
|
58
|
+
|
|
59
|
+
# 启动本地源码
|
|
60
|
+
uv run python -m codebuddy_proxy --desensitize
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
首次使用需要登录时:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
uv run python -m codebuddy_proxy --login --desensitize
|
|
48
67
|
```
|
|
49
68
|
|
|
50
69
|
## 快速开始
|
|
@@ -52,11 +71,11 @@ python codebuddy_proxy.py
|
|
|
52
71
|
### 1. 启动 proxy
|
|
53
72
|
|
|
54
73
|
```bash
|
|
55
|
-
#
|
|
56
|
-
uv run codebuddy_proxy
|
|
74
|
+
# 使用最新版本(推荐)
|
|
75
|
+
uv run --with workbuddy2api python -m codebuddy_proxy --desensitize
|
|
57
76
|
|
|
58
|
-
#
|
|
59
|
-
python codebuddy_proxy
|
|
77
|
+
# 首次使用:登录并启动
|
|
78
|
+
uv run --with workbuddy2api python -m codebuddy_proxy --login --desensitize
|
|
60
79
|
```
|
|
61
80
|
|
|
62
81
|
默认监听 `http://127.0.0.1:8787`
|
|
@@ -118,7 +137,7 @@ codex --profile codebuddy "你的任务"
|
|
|
118
137
|
--port PORT 监听端口(默认 8787)
|
|
119
138
|
--endpoint ENDPOINT CodeBuddy 后端地址
|
|
120
139
|
--session-file PATH 会话文件路径(默认 ~/.codebuddy-session.json)
|
|
121
|
-
--log-file PATH JSONL 日志文件(默认
|
|
140
|
+
--log-file PATH JSONL 日志文件(默认 ~/.workbuddy2api/codebuddy-proxy.jsonl)
|
|
122
141
|
--desensitize 启用脱敏处理(推荐)
|
|
123
142
|
--optimize-context 启用消息压缩优化(Codex CLI 推荐)
|
|
124
143
|
--login 启动时执行浏览器登录
|
|
@@ -142,7 +161,8 @@ CODEBUDDY_PROXY_LOG_FILE # 等同 --log-file
|
|
|
142
161
|
### 首次使用(需要登录)
|
|
143
162
|
|
|
144
163
|
```bash
|
|
145
|
-
uv run codebuddy_proxy
|
|
164
|
+
uv run --with workbuddy2api python -m codebuddy_proxy --login \
|
|
165
|
+
--log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
146
166
|
```
|
|
147
167
|
|
|
148
168
|
浏览器打开后登录,成功后 proxy 自动启动。
|
|
@@ -150,29 +170,34 @@ uv run codebuddy_proxy.py --login
|
|
|
150
170
|
### 日常使用(自动读取登录态)
|
|
151
171
|
|
|
152
172
|
```bash
|
|
153
|
-
uv run codebuddy_proxy
|
|
173
|
+
uv run --with workbuddy2api python -m codebuddy_proxy --desensitize \
|
|
174
|
+
--log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
154
175
|
```
|
|
155
176
|
|
|
156
177
|
### Codex CLI 场景(启用压缩优化)
|
|
157
178
|
|
|
158
179
|
```bash
|
|
159
|
-
uv run codebuddy_proxy
|
|
180
|
+
uv run --with workbuddy2api python -m codebuddy_proxy --desensitize --optimize-context \
|
|
181
|
+
--log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
160
182
|
```
|
|
161
183
|
|
|
162
184
|
### 多账号切换
|
|
163
185
|
|
|
164
186
|
```bash
|
|
165
187
|
# 账号 1
|
|
166
|
-
uv run codebuddy_proxy
|
|
188
|
+
uv run --with workbuddy2api python -m codebuddy_proxy --session-file ~/.codebuddy-work.json --login \
|
|
189
|
+
--log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
167
190
|
|
|
168
191
|
# 账号 2
|
|
169
|
-
uv run codebuddy_proxy
|
|
192
|
+
uv run --with workbuddy2api python -m codebuddy_proxy --session-file ~/.codebuddy-personal.json --login \
|
|
193
|
+
--log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
170
194
|
```
|
|
171
195
|
|
|
172
196
|
### 监听所有网卡(局域网共享)
|
|
173
197
|
|
|
174
198
|
```bash
|
|
175
|
-
uv run codebuddy_proxy
|
|
199
|
+
uv run --with workbuddy2api python -m codebuddy_proxy --host 0.0.0.0 --desensitize \
|
|
200
|
+
--log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
176
201
|
```
|
|
177
202
|
|
|
178
203
|
## API 接口
|
|
@@ -371,7 +396,8 @@ upstream chunk → response.output_text.delta
|
|
|
371
396
|
|
|
372
397
|
```bash
|
|
373
398
|
# 必须启用 --desensitize,否则几乎每次都被拦截
|
|
374
|
-
uv run codebuddy_proxy
|
|
399
|
+
uv run --with workbuddy2api python -m codebuddy_proxy --desensitize \
|
|
400
|
+
--log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
375
401
|
|
|
376
402
|
# 在 Claude Code / CC Switch 中配置
|
|
377
403
|
# Base URL: http://127.0.0.1:8787/v1/messages
|
|
@@ -381,7 +407,8 @@ uv run codebuddy_proxy.py --desensitize
|
|
|
381
407
|
|
|
382
408
|
```bash
|
|
383
409
|
# 同时启用脱敏和消息压缩(最佳配置)
|
|
384
|
-
uv run codebuddy_proxy
|
|
410
|
+
uv run --with workbuddy2api python -m codebuddy_proxy --desensitize --optimize-context \
|
|
411
|
+
--log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
385
412
|
|
|
386
413
|
# 在 Codex CLI 配置文件中
|
|
387
414
|
# base_url: http://127.0.0.1:8787/v1/responses
|
|
@@ -391,7 +418,8 @@ uv run codebuddy_proxy.py --desensitize --optimize-context
|
|
|
391
418
|
|
|
392
419
|
```bash
|
|
393
420
|
# 启用脱敏以避免合规术语被误拦
|
|
394
|
-
uv run codebuddy_proxy
|
|
421
|
+
uv run --with workbuddy2api python -m codebuddy_proxy --desensitize \
|
|
422
|
+
--log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
395
423
|
|
|
396
424
|
# 示例请求
|
|
397
425
|
curl http://127.0.0.1:8787/v1/chat/completions \
|
|
@@ -465,10 +493,12 @@ curl http://127.0.0.1:8787/v1/chat/completions \
|
|
|
465
493
|
|
|
466
494
|
```bash
|
|
467
495
|
# 启用消息压缩
|
|
468
|
-
uv run codebuddy_proxy
|
|
496
|
+
uv run --with workbuddy2api python -m codebuddy_proxy --optimize-context \
|
|
497
|
+
--log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
469
498
|
|
|
470
499
|
# 同时启用两个功能(推荐用于 Codex CLI)
|
|
471
|
-
uv run codebuddy_proxy
|
|
500
|
+
uv run --with workbuddy2api python -m codebuddy_proxy --desensitize --optimize-context \
|
|
501
|
+
--log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
472
502
|
```
|
|
473
503
|
|
|
474
504
|
#### 工作原理
|
|
@@ -512,7 +542,7 @@ uv run codebuddy_proxy.py --desensitize --optimize-context
|
|
|
512
542
|
启用功能后,日志会记录压缩统计:
|
|
513
543
|
|
|
514
544
|
```bash
|
|
515
|
-
grep projection_applied
|
|
545
|
+
grep projection_applied "$HOME/.workbuddy2api/codebuddy-proxy.jsonl" | jq .
|
|
516
546
|
```
|
|
517
547
|
|
|
518
548
|
示例输出:
|
|
@@ -543,26 +573,36 @@ grep projection_applied logs/codebuddy-proxy.jsonl | jq .
|
|
|
543
573
|
### 日志
|
|
544
574
|
|
|
545
575
|
日志包含:
|
|
546
|
-
-
|
|
547
|
-
-
|
|
576
|
+
- 文本日志:`$HOME/.workbuddy2api/proxy.log`(按天滚动,保留 30 天)
|
|
577
|
+
- 结构化日志:`$HOME/.workbuddy2api/codebuddy-proxy.jsonl`(按天滚动,保留 30 天,完整请求/响应)
|
|
578
|
+
|
|
579
|
+
JSONL 每条记录包含 `app_version`、`system_version`、`python_version` 和 `machine` 字段;启动时还会记录 `startup` 事件。
|
|
580
|
+
|
|
581
|
+
也可以指定日志文件的绝对路径:
|
|
582
|
+
|
|
583
|
+
```bash
|
|
584
|
+
uv run --with workbuddy2api python -m codebuddy_proxy \
|
|
585
|
+
--desensitize \
|
|
586
|
+
--log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
587
|
+
```
|
|
548
588
|
|
|
549
589
|
查看日志:
|
|
550
590
|
|
|
551
591
|
```bash
|
|
552
592
|
# 实时查看
|
|
553
|
-
tail -f
|
|
593
|
+
tail -f "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
554
594
|
|
|
555
595
|
# 查看流式事件
|
|
556
|
-
tail -100
|
|
596
|
+
tail -100 "$HOME/.workbuddy2api/codebuddy-proxy.jsonl" | jq 'select(.event | startswith("stream"))'
|
|
557
597
|
|
|
558
598
|
# 统计超时
|
|
559
|
-
jq 'select(.event=="stream_timeout")'
|
|
599
|
+
jq 'select(.event=="stream_timeout")' "$HOME/.workbuddy2api/codebuddy-proxy.jsonl" | wc -l
|
|
560
600
|
|
|
561
601
|
# 验证脱敏
|
|
562
|
-
grep desensitize_applied
|
|
602
|
+
grep desensitize_applied "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
563
603
|
|
|
564
604
|
# 验证压缩(查看统计数据)
|
|
565
|
-
grep projection_applied
|
|
605
|
+
grep projection_applied "$HOME/.workbuddy2api/codebuddy-proxy.jsonl" | jq .
|
|
566
606
|
```
|
|
567
607
|
|
|
568
608
|
### 找不到 session 文件
|
|
@@ -570,7 +610,8 @@ grep projection_applied logs/codebuddy-proxy.jsonl | jq .
|
|
|
570
610
|
首次使用需要登录:
|
|
571
611
|
|
|
572
612
|
```bash
|
|
573
|
-
uv run codebuddy_proxy
|
|
613
|
+
uv run --with workbuddy2api python -m codebuddy_proxy --login \
|
|
614
|
+
--log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
574
615
|
```
|
|
575
616
|
|
|
576
617
|
### 401 认证失败
|
|
@@ -578,7 +619,8 @@ uv run codebuddy_proxy.py --login
|
|
|
578
619
|
Token 过期,重新登录:
|
|
579
620
|
|
|
580
621
|
```bash
|
|
581
|
-
uv run codebuddy_proxy
|
|
622
|
+
uv run --with workbuddy2api python -m codebuddy_proxy --login \
|
|
623
|
+
--log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
582
624
|
```
|
|
583
625
|
|
|
584
626
|
### 审核拦截
|
|
@@ -586,20 +628,23 @@ uv run codebuddy_proxy.py --login
|
|
|
586
628
|
启用脱敏:
|
|
587
629
|
|
|
588
630
|
```bash
|
|
589
|
-
uv run codebuddy_proxy
|
|
631
|
+
uv run --with workbuddy2api python -m codebuddy_proxy --desensitize \
|
|
632
|
+
--log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
590
633
|
```
|
|
591
634
|
|
|
592
635
|
如果仍然被拦截,尝试压缩优化(仅 `/v1/responses`):
|
|
593
636
|
|
|
594
637
|
```bash
|
|
595
|
-
uv run codebuddy_proxy
|
|
638
|
+
uv run --with workbuddy2api python -m codebuddy_proxy --desensitize --optimize-context \
|
|
639
|
+
--log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
596
640
|
```
|
|
597
641
|
|
|
598
642
|
### 端口被占用
|
|
599
643
|
|
|
600
644
|
```bash
|
|
601
645
|
lsof -i :8787
|
|
602
|
-
uv run codebuddy_proxy
|
|
646
|
+
uv run --with workbuddy2api python -m codebuddy_proxy --port 8788 \
|
|
647
|
+
--log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
603
648
|
```
|
|
604
649
|
|
|
605
650
|
### SOCKS proxy 错误
|
|
@@ -614,7 +659,8 @@ env | grep -i proxy
|
|
|
614
659
|
|
|
615
660
|
```bash
|
|
616
661
|
unset http_proxy https_proxy all_proxy
|
|
617
|
-
uv run codebuddy_proxy
|
|
662
|
+
uv run --with workbuddy2api python -m codebuddy_proxy \
|
|
663
|
+
--log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
618
664
|
```
|
|
619
665
|
|
|
620
666
|
## 技术细节
|
|
@@ -15,21 +15,40 @@
|
|
|
15
15
|
|
|
16
16
|
## 安装
|
|
17
17
|
|
|
18
|
-
推荐使用 [uv](https://docs.astral.sh/uv/)
|
|
18
|
+
推荐使用 [uv](https://docs.astral.sh/uv/) 从 PyPI 运行:
|
|
19
19
|
|
|
20
20
|
```bash
|
|
21
21
|
# 安装 uv
|
|
22
22
|
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
23
23
|
|
|
24
|
-
#
|
|
25
|
-
uv run codebuddy_proxy
|
|
24
|
+
# 运行最新可用版本(uv 会自动创建环境并安装依赖)
|
|
25
|
+
uv run --with workbuddy2api python -m codebuddy_proxy \
|
|
26
|
+
--log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
27
|
+
|
|
28
|
+
# 强制刷新缓存后运行最新版本
|
|
29
|
+
uv run --refresh-package workbuddy2api --with workbuddy2api \
|
|
30
|
+
python -m codebuddy_proxy \
|
|
31
|
+
--log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
26
32
|
```
|
|
27
33
|
|
|
28
|
-
|
|
34
|
+
后续启动无需手动激活虚拟环境,重复执行上述 `uv run` 命令即可。
|
|
35
|
+
|
|
36
|
+
### 本地源码启动
|
|
37
|
+
|
|
38
|
+
在项目根目录执行以下命令,使用当前工作区源码而不是 PyPI 中的已发布版本:
|
|
29
39
|
|
|
30
40
|
```bash
|
|
31
|
-
|
|
32
|
-
|
|
41
|
+
# 同步本地项目依赖
|
|
42
|
+
uv sync
|
|
43
|
+
|
|
44
|
+
# 启动本地源码
|
|
45
|
+
uv run python -m codebuddy_proxy --desensitize
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
首次使用需要登录时:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
uv run python -m codebuddy_proxy --login --desensitize
|
|
33
52
|
```
|
|
34
53
|
|
|
35
54
|
## 快速开始
|
|
@@ -37,11 +56,11 @@ python codebuddy_proxy.py
|
|
|
37
56
|
### 1. 启动 proxy
|
|
38
57
|
|
|
39
58
|
```bash
|
|
40
|
-
#
|
|
41
|
-
uv run codebuddy_proxy
|
|
59
|
+
# 使用最新版本(推荐)
|
|
60
|
+
uv run --with workbuddy2api python -m codebuddy_proxy --desensitize
|
|
42
61
|
|
|
43
|
-
#
|
|
44
|
-
python codebuddy_proxy
|
|
62
|
+
# 首次使用:登录并启动
|
|
63
|
+
uv run --with workbuddy2api python -m codebuddy_proxy --login --desensitize
|
|
45
64
|
```
|
|
46
65
|
|
|
47
66
|
默认监听 `http://127.0.0.1:8787`
|
|
@@ -103,7 +122,7 @@ codex --profile codebuddy "你的任务"
|
|
|
103
122
|
--port PORT 监听端口(默认 8787)
|
|
104
123
|
--endpoint ENDPOINT CodeBuddy 后端地址
|
|
105
124
|
--session-file PATH 会话文件路径(默认 ~/.codebuddy-session.json)
|
|
106
|
-
--log-file PATH JSONL 日志文件(默认
|
|
125
|
+
--log-file PATH JSONL 日志文件(默认 ~/.workbuddy2api/codebuddy-proxy.jsonl)
|
|
107
126
|
--desensitize 启用脱敏处理(推荐)
|
|
108
127
|
--optimize-context 启用消息压缩优化(Codex CLI 推荐)
|
|
109
128
|
--login 启动时执行浏览器登录
|
|
@@ -127,7 +146,8 @@ CODEBUDDY_PROXY_LOG_FILE # 等同 --log-file
|
|
|
127
146
|
### 首次使用(需要登录)
|
|
128
147
|
|
|
129
148
|
```bash
|
|
130
|
-
uv run codebuddy_proxy
|
|
149
|
+
uv run --with workbuddy2api python -m codebuddy_proxy --login \
|
|
150
|
+
--log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
131
151
|
```
|
|
132
152
|
|
|
133
153
|
浏览器打开后登录,成功后 proxy 自动启动。
|
|
@@ -135,29 +155,34 @@ uv run codebuddy_proxy.py --login
|
|
|
135
155
|
### 日常使用(自动读取登录态)
|
|
136
156
|
|
|
137
157
|
```bash
|
|
138
|
-
uv run codebuddy_proxy
|
|
158
|
+
uv run --with workbuddy2api python -m codebuddy_proxy --desensitize \
|
|
159
|
+
--log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
139
160
|
```
|
|
140
161
|
|
|
141
162
|
### Codex CLI 场景(启用压缩优化)
|
|
142
163
|
|
|
143
164
|
```bash
|
|
144
|
-
uv run codebuddy_proxy
|
|
165
|
+
uv run --with workbuddy2api python -m codebuddy_proxy --desensitize --optimize-context \
|
|
166
|
+
--log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
145
167
|
```
|
|
146
168
|
|
|
147
169
|
### 多账号切换
|
|
148
170
|
|
|
149
171
|
```bash
|
|
150
172
|
# 账号 1
|
|
151
|
-
uv run codebuddy_proxy
|
|
173
|
+
uv run --with workbuddy2api python -m codebuddy_proxy --session-file ~/.codebuddy-work.json --login \
|
|
174
|
+
--log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
152
175
|
|
|
153
176
|
# 账号 2
|
|
154
|
-
uv run codebuddy_proxy
|
|
177
|
+
uv run --with workbuddy2api python -m codebuddy_proxy --session-file ~/.codebuddy-personal.json --login \
|
|
178
|
+
--log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
155
179
|
```
|
|
156
180
|
|
|
157
181
|
### 监听所有网卡(局域网共享)
|
|
158
182
|
|
|
159
183
|
```bash
|
|
160
|
-
uv run codebuddy_proxy
|
|
184
|
+
uv run --with workbuddy2api python -m codebuddy_proxy --host 0.0.0.0 --desensitize \
|
|
185
|
+
--log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
161
186
|
```
|
|
162
187
|
|
|
163
188
|
## API 接口
|
|
@@ -356,7 +381,8 @@ upstream chunk → response.output_text.delta
|
|
|
356
381
|
|
|
357
382
|
```bash
|
|
358
383
|
# 必须启用 --desensitize,否则几乎每次都被拦截
|
|
359
|
-
uv run codebuddy_proxy
|
|
384
|
+
uv run --with workbuddy2api python -m codebuddy_proxy --desensitize \
|
|
385
|
+
--log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
360
386
|
|
|
361
387
|
# 在 Claude Code / CC Switch 中配置
|
|
362
388
|
# Base URL: http://127.0.0.1:8787/v1/messages
|
|
@@ -366,7 +392,8 @@ uv run codebuddy_proxy.py --desensitize
|
|
|
366
392
|
|
|
367
393
|
```bash
|
|
368
394
|
# 同时启用脱敏和消息压缩(最佳配置)
|
|
369
|
-
uv run codebuddy_proxy
|
|
395
|
+
uv run --with workbuddy2api python -m codebuddy_proxy --desensitize --optimize-context \
|
|
396
|
+
--log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
370
397
|
|
|
371
398
|
# 在 Codex CLI 配置文件中
|
|
372
399
|
# base_url: http://127.0.0.1:8787/v1/responses
|
|
@@ -376,7 +403,8 @@ uv run codebuddy_proxy.py --desensitize --optimize-context
|
|
|
376
403
|
|
|
377
404
|
```bash
|
|
378
405
|
# 启用脱敏以避免合规术语被误拦
|
|
379
|
-
uv run codebuddy_proxy
|
|
406
|
+
uv run --with workbuddy2api python -m codebuddy_proxy --desensitize \
|
|
407
|
+
--log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
380
408
|
|
|
381
409
|
# 示例请求
|
|
382
410
|
curl http://127.0.0.1:8787/v1/chat/completions \
|
|
@@ -450,10 +478,12 @@ curl http://127.0.0.1:8787/v1/chat/completions \
|
|
|
450
478
|
|
|
451
479
|
```bash
|
|
452
480
|
# 启用消息压缩
|
|
453
|
-
uv run codebuddy_proxy
|
|
481
|
+
uv run --with workbuddy2api python -m codebuddy_proxy --optimize-context \
|
|
482
|
+
--log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
454
483
|
|
|
455
484
|
# 同时启用两个功能(推荐用于 Codex CLI)
|
|
456
|
-
uv run codebuddy_proxy
|
|
485
|
+
uv run --with workbuddy2api python -m codebuddy_proxy --desensitize --optimize-context \
|
|
486
|
+
--log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
457
487
|
```
|
|
458
488
|
|
|
459
489
|
#### 工作原理
|
|
@@ -497,7 +527,7 @@ uv run codebuddy_proxy.py --desensitize --optimize-context
|
|
|
497
527
|
启用功能后,日志会记录压缩统计:
|
|
498
528
|
|
|
499
529
|
```bash
|
|
500
|
-
grep projection_applied
|
|
530
|
+
grep projection_applied "$HOME/.workbuddy2api/codebuddy-proxy.jsonl" | jq .
|
|
501
531
|
```
|
|
502
532
|
|
|
503
533
|
示例输出:
|
|
@@ -528,26 +558,36 @@ grep projection_applied logs/codebuddy-proxy.jsonl | jq .
|
|
|
528
558
|
### 日志
|
|
529
559
|
|
|
530
560
|
日志包含:
|
|
531
|
-
-
|
|
532
|
-
-
|
|
561
|
+
- 文本日志:`$HOME/.workbuddy2api/proxy.log`(按天滚动,保留 30 天)
|
|
562
|
+
- 结构化日志:`$HOME/.workbuddy2api/codebuddy-proxy.jsonl`(按天滚动,保留 30 天,完整请求/响应)
|
|
563
|
+
|
|
564
|
+
JSONL 每条记录包含 `app_version`、`system_version`、`python_version` 和 `machine` 字段;启动时还会记录 `startup` 事件。
|
|
565
|
+
|
|
566
|
+
也可以指定日志文件的绝对路径:
|
|
567
|
+
|
|
568
|
+
```bash
|
|
569
|
+
uv run --with workbuddy2api python -m codebuddy_proxy \
|
|
570
|
+
--desensitize \
|
|
571
|
+
--log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
572
|
+
```
|
|
533
573
|
|
|
534
574
|
查看日志:
|
|
535
575
|
|
|
536
576
|
```bash
|
|
537
577
|
# 实时查看
|
|
538
|
-
tail -f
|
|
578
|
+
tail -f "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
539
579
|
|
|
540
580
|
# 查看流式事件
|
|
541
|
-
tail -100
|
|
581
|
+
tail -100 "$HOME/.workbuddy2api/codebuddy-proxy.jsonl" | jq 'select(.event | startswith("stream"))'
|
|
542
582
|
|
|
543
583
|
# 统计超时
|
|
544
|
-
jq 'select(.event=="stream_timeout")'
|
|
584
|
+
jq 'select(.event=="stream_timeout")' "$HOME/.workbuddy2api/codebuddy-proxy.jsonl" | wc -l
|
|
545
585
|
|
|
546
586
|
# 验证脱敏
|
|
547
|
-
grep desensitize_applied
|
|
587
|
+
grep desensitize_applied "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
548
588
|
|
|
549
589
|
# 验证压缩(查看统计数据)
|
|
550
|
-
grep projection_applied
|
|
590
|
+
grep projection_applied "$HOME/.workbuddy2api/codebuddy-proxy.jsonl" | jq .
|
|
551
591
|
```
|
|
552
592
|
|
|
553
593
|
### 找不到 session 文件
|
|
@@ -555,7 +595,8 @@ grep projection_applied logs/codebuddy-proxy.jsonl | jq .
|
|
|
555
595
|
首次使用需要登录:
|
|
556
596
|
|
|
557
597
|
```bash
|
|
558
|
-
uv run codebuddy_proxy
|
|
598
|
+
uv run --with workbuddy2api python -m codebuddy_proxy --login \
|
|
599
|
+
--log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
559
600
|
```
|
|
560
601
|
|
|
561
602
|
### 401 认证失败
|
|
@@ -563,7 +604,8 @@ uv run codebuddy_proxy.py --login
|
|
|
563
604
|
Token 过期,重新登录:
|
|
564
605
|
|
|
565
606
|
```bash
|
|
566
|
-
uv run codebuddy_proxy
|
|
607
|
+
uv run --with workbuddy2api python -m codebuddy_proxy --login \
|
|
608
|
+
--log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
567
609
|
```
|
|
568
610
|
|
|
569
611
|
### 审核拦截
|
|
@@ -571,20 +613,23 @@ uv run codebuddy_proxy.py --login
|
|
|
571
613
|
启用脱敏:
|
|
572
614
|
|
|
573
615
|
```bash
|
|
574
|
-
uv run codebuddy_proxy
|
|
616
|
+
uv run --with workbuddy2api python -m codebuddy_proxy --desensitize \
|
|
617
|
+
--log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
575
618
|
```
|
|
576
619
|
|
|
577
620
|
如果仍然被拦截,尝试压缩优化(仅 `/v1/responses`):
|
|
578
621
|
|
|
579
622
|
```bash
|
|
580
|
-
uv run codebuddy_proxy
|
|
623
|
+
uv run --with workbuddy2api python -m codebuddy_proxy --desensitize --optimize-context \
|
|
624
|
+
--log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
581
625
|
```
|
|
582
626
|
|
|
583
627
|
### 端口被占用
|
|
584
628
|
|
|
585
629
|
```bash
|
|
586
630
|
lsof -i :8787
|
|
587
|
-
uv run codebuddy_proxy
|
|
631
|
+
uv run --with workbuddy2api python -m codebuddy_proxy --port 8788 \
|
|
632
|
+
--log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
588
633
|
```
|
|
589
634
|
|
|
590
635
|
### SOCKS proxy 错误
|
|
@@ -599,7 +644,8 @@ env | grep -i proxy
|
|
|
599
644
|
|
|
600
645
|
```bash
|
|
601
646
|
unset http_proxy https_proxy all_proxy
|
|
602
|
-
uv run codebuddy_proxy
|
|
647
|
+
uv run --with workbuddy2api python -m codebuddy_proxy \
|
|
648
|
+
--log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
603
649
|
```
|
|
604
650
|
|
|
605
651
|
## 技术细节
|
|
@@ -8,20 +8,22 @@ Features:
|
|
|
8
8
|
- Robust timeout handling with async iterators
|
|
9
9
|
|
|
10
10
|
Usage with uv:
|
|
11
|
-
uv run codebuddy_proxy
|
|
12
|
-
uv run codebuddy_proxy
|
|
13
|
-
uv run codebuddy_proxy
|
|
11
|
+
uv run --with workbuddy2api python -m codebuddy_proxy
|
|
12
|
+
uv run --with workbuddy2api python -m codebuddy_proxy --desensitize
|
|
13
|
+
uv run --with workbuddy2api python -m codebuddy_proxy --host 0.0.0.0 --port 8787
|
|
14
14
|
"""
|
|
15
15
|
|
|
16
16
|
import argparse
|
|
17
17
|
import base64
|
|
18
18
|
import hashlib
|
|
19
19
|
import io
|
|
20
|
+
import importlib.metadata
|
|
20
21
|
import json
|
|
21
22
|
import logging
|
|
22
23
|
import logging.handlers
|
|
23
24
|
import os
|
|
24
25
|
import pathlib
|
|
26
|
+
import platform
|
|
25
27
|
import sys
|
|
26
28
|
import time
|
|
27
29
|
import uuid
|
|
@@ -101,10 +103,40 @@ def setup_logging(log_dir: pathlib.Path) -> logging.Logger:
|
|
|
101
103
|
return logger
|
|
102
104
|
|
|
103
105
|
|
|
106
|
+
def setup_json_logging(log_file: pathlib.Path) -> logging.Logger:
|
|
107
|
+
"""配置 JSONL 滚动日志:按天分片,保留30天。"""
|
|
108
|
+
logger = logging.getLogger("codebuddy_proxy.jsonl")
|
|
109
|
+
logger.setLevel(logging.INFO)
|
|
110
|
+
logger.propagate = False
|
|
111
|
+
logger.handlers.clear()
|
|
112
|
+
|
|
113
|
+
handler = logging.handlers.TimedRotatingFileHandler(
|
|
114
|
+
log_file, when="midnight", interval=1, backupCount=30, encoding="utf-8"
|
|
115
|
+
)
|
|
116
|
+
handler.suffix = "%Y-%m-%d"
|
|
117
|
+
handler.setFormatter(logging.Formatter("%(message)s"))
|
|
118
|
+
logger.addHandler(handler)
|
|
119
|
+
|
|
120
|
+
return logger
|
|
121
|
+
|
|
122
|
+
|
|
104
123
|
def now_s() -> int:
|
|
105
124
|
return int(time.time())
|
|
106
125
|
|
|
107
126
|
|
|
127
|
+
def get_runtime_info() -> dict[str, str]:
|
|
128
|
+
try:
|
|
129
|
+
app_version = importlib.metadata.version("workbuddy2api")
|
|
130
|
+
except importlib.metadata.PackageNotFoundError:
|
|
131
|
+
app_version = "unknown"
|
|
132
|
+
return {
|
|
133
|
+
"app_version": app_version,
|
|
134
|
+
"system_version": platform.platform(),
|
|
135
|
+
"python_version": platform.python_version(),
|
|
136
|
+
"machine": platform.machine(),
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
|
|
108
140
|
# ============================================================================
|
|
109
141
|
# 全局状态管理
|
|
110
142
|
# ============================================================================
|
|
@@ -121,6 +153,7 @@ class ProxyState:
|
|
|
121
153
|
enable_optimize_context: bool = False,
|
|
122
154
|
verbose_llm: bool = False,
|
|
123
155
|
logger: logging.Logger | None = None,
|
|
156
|
+
json_logger: logging.Logger | None = None,
|
|
124
157
|
):
|
|
125
158
|
self.client = client
|
|
126
159
|
self.mock_dir = mock_dir
|
|
@@ -129,6 +162,8 @@ class ProxyState:
|
|
|
129
162
|
self.enable_optimize_context = enable_optimize_context
|
|
130
163
|
self.verbose_llm = verbose_llm
|
|
131
164
|
self.logger = logger
|
|
165
|
+
self.json_logger = json_logger
|
|
166
|
+
self.runtime_info = get_runtime_info()
|
|
132
167
|
self.started_at = time.time()
|
|
133
168
|
|
|
134
169
|
def ensure_auth(self) -> None:
|
|
@@ -136,29 +171,33 @@ class ProxyState:
|
|
|
136
171
|
self.client.ensure_authenticated()
|
|
137
172
|
|
|
138
173
|
def write_log(self, event: str, **kwargs) -> None:
|
|
139
|
-
if self.
|
|
174
|
+
if self.json_logger is None:
|
|
140
175
|
return
|
|
141
176
|
try:
|
|
142
|
-
record = {
|
|
143
|
-
|
|
144
|
-
|
|
177
|
+
record = {
|
|
178
|
+
"timestamp": time.strftime("%Y-%m-%dT%H:%M:%S%z"),
|
|
179
|
+
"event": event,
|
|
180
|
+
**self.runtime_info,
|
|
181
|
+
**kwargs,
|
|
182
|
+
}
|
|
183
|
+
self.json_logger.info(json.dumps(record, ensure_ascii=False))
|
|
145
184
|
except Exception:
|
|
146
185
|
pass
|
|
147
186
|
|
|
148
187
|
def write_body_log(self, event: str, body: bytes, **kwargs) -> None:
|
|
149
|
-
if self.
|
|
188
|
+
if self.json_logger is None:
|
|
150
189
|
return
|
|
151
190
|
try:
|
|
152
191
|
text = body.decode("utf-8", errors="replace")
|
|
153
192
|
record = {
|
|
154
193
|
"timestamp": time.strftime("%Y-%m-%dT%H:%M:%S%z"),
|
|
155
194
|
"event": event,
|
|
195
|
+
**self.runtime_info,
|
|
156
196
|
"body_bytes": len(body),
|
|
157
197
|
"body_text": text,
|
|
158
198
|
**kwargs
|
|
159
199
|
}
|
|
160
|
-
|
|
161
|
-
f.write(json.dumps(record, ensure_ascii=False) + "\n")
|
|
200
|
+
self.json_logger.info(json.dumps(record, ensure_ascii=False))
|
|
162
201
|
except Exception:
|
|
163
202
|
pass
|
|
164
203
|
|
|
@@ -293,7 +332,7 @@ class RemoteConfigCache:
|
|
|
293
332
|
|
|
294
333
|
# 构造请求头(包含认证信息)
|
|
295
334
|
headers = state.client.auth_headers()
|
|
296
|
-
headers["User-Agent"] = "
|
|
335
|
+
headers["User-Agent"] = "Mozilla/5.0 (compatible; Genie-IDE/1.0)"
|
|
297
336
|
headers["Accept"] = "application/json"
|
|
298
337
|
|
|
299
338
|
# 发起请求(超时 5 秒,匹配插件)
|
|
@@ -858,11 +897,18 @@ async def forward_chat(
|
|
|
858
897
|
|
|
859
898
|
url = state.client.endpoint + "/v2/chat/completions"
|
|
860
899
|
headers = {
|
|
900
|
+
"User-Agent": "Mozilla/5.0 (compatible; Genie-IDE/1.0)",
|
|
861
901
|
**state.client.auth_headers(),
|
|
862
902
|
"Content-Type": "application/json",
|
|
863
903
|
"Accept": "text/event-stream",
|
|
864
904
|
}
|
|
865
905
|
|
|
906
|
+
# 🔍 调试:输出实际发送的IDE识别headers
|
|
907
|
+
if state.logger:
|
|
908
|
+
ide_headers = {k: v for k, v in headers.items()
|
|
909
|
+
if k.startswith("X-IDE-") or k == "X-Product-Version" or k == "X-Machine-Id"}
|
|
910
|
+
diagnostic("upstream_ide_headers", **ide_headers)
|
|
911
|
+
|
|
866
912
|
if stream:
|
|
867
913
|
# 流式:直接转发
|
|
868
914
|
return StreamingResponse(
|
|
@@ -1500,9 +1546,18 @@ def main():
|
|
|
1500
1546
|
help="会话文件路径")
|
|
1501
1547
|
parser.add_argument("--mock-dir", type=pathlib.Path,
|
|
1502
1548
|
help="只使用指定目录中的真实响应 fixture,不访问 CodeBuddy 后端")
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1549
|
+
default_log_file = pathlib.Path(
|
|
1550
|
+
os.getenv(
|
|
1551
|
+
"CODEBUDDY_PROXY_LOG_FILE",
|
|
1552
|
+
str(pathlib.Path.home() / ".workbuddy2api" / "codebuddy-proxy.jsonl"),
|
|
1553
|
+
)
|
|
1554
|
+
).expanduser()
|
|
1555
|
+
parser.add_argument(
|
|
1556
|
+
"--log-file",
|
|
1557
|
+
type=pathlib.Path,
|
|
1558
|
+
default=default_log_file,
|
|
1559
|
+
help="记录完整请求/响应的 JSONL 文件(默认 ~/.workbuddy2api/codebuddy-proxy.jsonl)",
|
|
1560
|
+
)
|
|
1506
1561
|
parser.add_argument("--desensitize", action="store_true",
|
|
1507
1562
|
help="启用脱敏处理,对 system 消息中的敏感词插入零宽空格(缓解审核误拦)")
|
|
1508
1563
|
parser.add_argument("--optimize-context", action="store_true",
|
|
@@ -1518,10 +1573,12 @@ def main():
|
|
|
1518
1573
|
parser.add_argument("--config-cache-ttl", type=int, default=int(os.getenv("CODEBUDDY_CONFIG_CACHE_TTL", "300")),
|
|
1519
1574
|
help="远程配置缓存 TTL(秒,默认 300)")
|
|
1520
1575
|
args = parser.parse_args()
|
|
1576
|
+
args.log_file = args.log_file.expanduser()
|
|
1521
1577
|
|
|
1522
1578
|
# 设置日志
|
|
1523
1579
|
log_dir = args.log_file.parent if args.log_file else pathlib.Path("logs")
|
|
1524
1580
|
logger = setup_logging(log_dir)
|
|
1581
|
+
json_logger = setup_json_logging(args.log_file)
|
|
1525
1582
|
|
|
1526
1583
|
# 初始化客户端
|
|
1527
1584
|
client = CodeBuddyClient(args.endpoint, session_file=args.session_file)
|
|
@@ -1538,7 +1595,20 @@ def main():
|
|
|
1538
1595
|
enable_desensitize=args.desensitize,
|
|
1539
1596
|
enable_optimize_context=args.optimize_context,
|
|
1540
1597
|
verbose_llm=args.verbose_llm,
|
|
1541
|
-
logger=logger
|
|
1598
|
+
logger=logger,
|
|
1599
|
+
json_logger=json_logger,
|
|
1600
|
+
)
|
|
1601
|
+
proxy_state.write_log(
|
|
1602
|
+
"startup",
|
|
1603
|
+
host=args.host,
|
|
1604
|
+
port=args.port,
|
|
1605
|
+
)
|
|
1606
|
+
logger.info(
|
|
1607
|
+
"Runtime: app_version=%s system_version=%s python_version=%s machine=%s",
|
|
1608
|
+
proxy_state.runtime_info["app_version"],
|
|
1609
|
+
proxy_state.runtime_info["system_version"],
|
|
1610
|
+
proxy_state.runtime_info["python_version"],
|
|
1611
|
+
proxy_state.runtime_info["machine"],
|
|
1542
1612
|
)
|
|
1543
1613
|
|
|
1544
1614
|
# 初始化远程配置缓存(默认启用动态模型列表)
|
|
@@ -81,8 +81,11 @@ class CodeBuddyClient:
|
|
|
81
81
|
body: Any = None,
|
|
82
82
|
timeout: float = 30,
|
|
83
83
|
) -> Any:
|
|
84
|
-
|
|
85
|
-
request_headers
|
|
84
|
+
# 🔥 所有请求都必须包含这两个基础标识(匹配插件行为)
|
|
85
|
+
request_headers = {
|
|
86
|
+
"User-Agent": "Mozilla/5.0 (compatible; Genie-IDE/1.0)",
|
|
87
|
+
"X-Product-Code": "codebuddy",
|
|
88
|
+
}
|
|
86
89
|
data = None
|
|
87
90
|
if body is not None:
|
|
88
91
|
data = json.dumps(body).encode("utf-8")
|
|
@@ -110,9 +113,20 @@ class CodeBuddyClient:
|
|
|
110
113
|
raise CodeBuddyError(f"{path} 返回的不是 JSON: {raw[:300]!r}") from exc
|
|
111
114
|
|
|
112
115
|
def auth_headers(self, *, access: bool = True, refresh: bool = False) -> dict[str, str]:
|
|
116
|
+
"""构造认证 headers,模拟插件行为"""
|
|
113
117
|
account = self.session.get("account") or {}
|
|
114
118
|
auth = self.session.get("auth") or {}
|
|
115
|
-
headers: dict[str, str] = {
|
|
119
|
+
headers: dict[str, str] = {
|
|
120
|
+
# 🔥 关键标识:所有请求都需要这个 header
|
|
121
|
+
"X-Product-Code": "codebuddy",
|
|
122
|
+
# 🔥 IDE 识别信息(服务端用于识别客户端类型)
|
|
123
|
+
"X-IDE-Type": "vscode",
|
|
124
|
+
"X-IDE-Name": "Visual Studio Code",
|
|
125
|
+
"X-IDE-Version": "1.70.2", # VSCode 最低版本要求
|
|
126
|
+
"X-Product-Version": "4.10.33259736", # 插件版本
|
|
127
|
+
"X-Machine-Id": self._get_machine_id(),
|
|
128
|
+
}
|
|
129
|
+
|
|
116
130
|
if account.get("uid"):
|
|
117
131
|
headers["X-User-Id"] = str(account["uid"])
|
|
118
132
|
if access and auth.get("accessToken"):
|
|
@@ -122,12 +136,41 @@ class CodeBuddyClient:
|
|
|
122
136
|
if account.get("enterpriseId"):
|
|
123
137
|
headers["X-Enterprise-Id"] = str(account["enterpriseId"])
|
|
124
138
|
headers["X-Tenant-Id"] = str(account["enterpriseId"])
|
|
139
|
+
if account.get("departmentInfo"):
|
|
140
|
+
# 🔥 新增:部门信息(如果有)
|
|
141
|
+
headers["X-Department-Info"] = str(account["departmentInfo"])
|
|
125
142
|
if auth.get("domain"):
|
|
126
143
|
# The extension calls this the domain header. The server accepts
|
|
127
144
|
# X-Domain for the plugin protocol.
|
|
128
145
|
headers["X-Domain"] = str(auth["domain"])
|
|
129
146
|
return headers
|
|
130
147
|
|
|
148
|
+
def _get_machine_id(self) -> str:
|
|
149
|
+
"""获取或生成机器ID(模拟VSCode的machineId)"""
|
|
150
|
+
import hashlib
|
|
151
|
+
import platform
|
|
152
|
+
import uuid
|
|
153
|
+
|
|
154
|
+
# 尝试从session读取已保存的machineId
|
|
155
|
+
saved_machine_id = self.session.get("machineId")
|
|
156
|
+
if saved_machine_id:
|
|
157
|
+
return str(saved_machine_id)
|
|
158
|
+
|
|
159
|
+
# 生成一个稳定的machineId(基于主机名和用户)
|
|
160
|
+
try:
|
|
161
|
+
hostname = platform.node()
|
|
162
|
+
username = os.environ.get("USER") or os.environ.get("USERNAME") or "unknown"
|
|
163
|
+
seed = f"{hostname}-{username}"
|
|
164
|
+
machine_id = str(uuid.uuid5(uuid.NAMESPACE_DNS, seed))
|
|
165
|
+
except Exception:
|
|
166
|
+
# 如果失败,生成随机ID
|
|
167
|
+
machine_id = str(uuid.uuid4())
|
|
168
|
+
|
|
169
|
+
# 保存到session
|
|
170
|
+
self.session["machineId"] = machine_id
|
|
171
|
+
self._save_session(self.session)
|
|
172
|
+
return machine_id
|
|
173
|
+
|
|
131
174
|
def login(self, *, open_browser: bool = True, timeout: int = 300) -> None:
|
|
132
175
|
no_auth = {
|
|
133
176
|
"X-No-Authorization": "true",
|
|
@@ -250,6 +293,8 @@ class CodeBuddyClient:
|
|
|
250
293
|
f"{self.endpoint}/v2/chat/completions",
|
|
251
294
|
data=json.dumps(payload).encode("utf-8"),
|
|
252
295
|
headers={
|
|
296
|
+
"User-Agent": "Mozilla/5.0 (compatible; Genie-IDE/1.0)",
|
|
297
|
+
"X-Product-Code": "codebuddy",
|
|
253
298
|
**self.auth_headers(),
|
|
254
299
|
"Content-Type": "application/json",
|
|
255
300
|
"Accept": "text/event-stream",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: workbuddy2api
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.3
|
|
4
4
|
Summary: Local OpenAI/Responses/Anthropic compatible proxy for CodeBuddy
|
|
5
5
|
Requires-Python: >=3.10
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
@@ -30,21 +30,40 @@ Dynamic: license-file
|
|
|
30
30
|
|
|
31
31
|
## 安装
|
|
32
32
|
|
|
33
|
-
推荐使用 [uv](https://docs.astral.sh/uv/)
|
|
33
|
+
推荐使用 [uv](https://docs.astral.sh/uv/) 从 PyPI 运行:
|
|
34
34
|
|
|
35
35
|
```bash
|
|
36
36
|
# 安装 uv
|
|
37
37
|
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
38
38
|
|
|
39
|
-
#
|
|
40
|
-
uv run codebuddy_proxy
|
|
39
|
+
# 运行最新可用版本(uv 会自动创建环境并安装依赖)
|
|
40
|
+
uv run --with workbuddy2api python -m codebuddy_proxy \
|
|
41
|
+
--log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
42
|
+
|
|
43
|
+
# 强制刷新缓存后运行最新版本
|
|
44
|
+
uv run --refresh-package workbuddy2api --with workbuddy2api \
|
|
45
|
+
python -m codebuddy_proxy \
|
|
46
|
+
--log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
41
47
|
```
|
|
42
48
|
|
|
43
|
-
|
|
49
|
+
后续启动无需手动激活虚拟环境,重复执行上述 `uv run` 命令即可。
|
|
50
|
+
|
|
51
|
+
### 本地源码启动
|
|
52
|
+
|
|
53
|
+
在项目根目录执行以下命令,使用当前工作区源码而不是 PyPI 中的已发布版本:
|
|
44
54
|
|
|
45
55
|
```bash
|
|
46
|
-
|
|
47
|
-
|
|
56
|
+
# 同步本地项目依赖
|
|
57
|
+
uv sync
|
|
58
|
+
|
|
59
|
+
# 启动本地源码
|
|
60
|
+
uv run python -m codebuddy_proxy --desensitize
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
首次使用需要登录时:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
uv run python -m codebuddy_proxy --login --desensitize
|
|
48
67
|
```
|
|
49
68
|
|
|
50
69
|
## 快速开始
|
|
@@ -52,11 +71,11 @@ python codebuddy_proxy.py
|
|
|
52
71
|
### 1. 启动 proxy
|
|
53
72
|
|
|
54
73
|
```bash
|
|
55
|
-
#
|
|
56
|
-
uv run codebuddy_proxy
|
|
74
|
+
# 使用最新版本(推荐)
|
|
75
|
+
uv run --with workbuddy2api python -m codebuddy_proxy --desensitize
|
|
57
76
|
|
|
58
|
-
#
|
|
59
|
-
python codebuddy_proxy
|
|
77
|
+
# 首次使用:登录并启动
|
|
78
|
+
uv run --with workbuddy2api python -m codebuddy_proxy --login --desensitize
|
|
60
79
|
```
|
|
61
80
|
|
|
62
81
|
默认监听 `http://127.0.0.1:8787`
|
|
@@ -118,7 +137,7 @@ codex --profile codebuddy "你的任务"
|
|
|
118
137
|
--port PORT 监听端口(默认 8787)
|
|
119
138
|
--endpoint ENDPOINT CodeBuddy 后端地址
|
|
120
139
|
--session-file PATH 会话文件路径(默认 ~/.codebuddy-session.json)
|
|
121
|
-
--log-file PATH JSONL 日志文件(默认
|
|
140
|
+
--log-file PATH JSONL 日志文件(默认 ~/.workbuddy2api/codebuddy-proxy.jsonl)
|
|
122
141
|
--desensitize 启用脱敏处理(推荐)
|
|
123
142
|
--optimize-context 启用消息压缩优化(Codex CLI 推荐)
|
|
124
143
|
--login 启动时执行浏览器登录
|
|
@@ -142,7 +161,8 @@ CODEBUDDY_PROXY_LOG_FILE # 等同 --log-file
|
|
|
142
161
|
### 首次使用(需要登录)
|
|
143
162
|
|
|
144
163
|
```bash
|
|
145
|
-
uv run codebuddy_proxy
|
|
164
|
+
uv run --with workbuddy2api python -m codebuddy_proxy --login \
|
|
165
|
+
--log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
146
166
|
```
|
|
147
167
|
|
|
148
168
|
浏览器打开后登录,成功后 proxy 自动启动。
|
|
@@ -150,29 +170,34 @@ uv run codebuddy_proxy.py --login
|
|
|
150
170
|
### 日常使用(自动读取登录态)
|
|
151
171
|
|
|
152
172
|
```bash
|
|
153
|
-
uv run codebuddy_proxy
|
|
173
|
+
uv run --with workbuddy2api python -m codebuddy_proxy --desensitize \
|
|
174
|
+
--log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
154
175
|
```
|
|
155
176
|
|
|
156
177
|
### Codex CLI 场景(启用压缩优化)
|
|
157
178
|
|
|
158
179
|
```bash
|
|
159
|
-
uv run codebuddy_proxy
|
|
180
|
+
uv run --with workbuddy2api python -m codebuddy_proxy --desensitize --optimize-context \
|
|
181
|
+
--log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
160
182
|
```
|
|
161
183
|
|
|
162
184
|
### 多账号切换
|
|
163
185
|
|
|
164
186
|
```bash
|
|
165
187
|
# 账号 1
|
|
166
|
-
uv run codebuddy_proxy
|
|
188
|
+
uv run --with workbuddy2api python -m codebuddy_proxy --session-file ~/.codebuddy-work.json --login \
|
|
189
|
+
--log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
167
190
|
|
|
168
191
|
# 账号 2
|
|
169
|
-
uv run codebuddy_proxy
|
|
192
|
+
uv run --with workbuddy2api python -m codebuddy_proxy --session-file ~/.codebuddy-personal.json --login \
|
|
193
|
+
--log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
170
194
|
```
|
|
171
195
|
|
|
172
196
|
### 监听所有网卡(局域网共享)
|
|
173
197
|
|
|
174
198
|
```bash
|
|
175
|
-
uv run codebuddy_proxy
|
|
199
|
+
uv run --with workbuddy2api python -m codebuddy_proxy --host 0.0.0.0 --desensitize \
|
|
200
|
+
--log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
176
201
|
```
|
|
177
202
|
|
|
178
203
|
## API 接口
|
|
@@ -371,7 +396,8 @@ upstream chunk → response.output_text.delta
|
|
|
371
396
|
|
|
372
397
|
```bash
|
|
373
398
|
# 必须启用 --desensitize,否则几乎每次都被拦截
|
|
374
|
-
uv run codebuddy_proxy
|
|
399
|
+
uv run --with workbuddy2api python -m codebuddy_proxy --desensitize \
|
|
400
|
+
--log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
375
401
|
|
|
376
402
|
# 在 Claude Code / CC Switch 中配置
|
|
377
403
|
# Base URL: http://127.0.0.1:8787/v1/messages
|
|
@@ -381,7 +407,8 @@ uv run codebuddy_proxy.py --desensitize
|
|
|
381
407
|
|
|
382
408
|
```bash
|
|
383
409
|
# 同时启用脱敏和消息压缩(最佳配置)
|
|
384
|
-
uv run codebuddy_proxy
|
|
410
|
+
uv run --with workbuddy2api python -m codebuddy_proxy --desensitize --optimize-context \
|
|
411
|
+
--log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
385
412
|
|
|
386
413
|
# 在 Codex CLI 配置文件中
|
|
387
414
|
# base_url: http://127.0.0.1:8787/v1/responses
|
|
@@ -391,7 +418,8 @@ uv run codebuddy_proxy.py --desensitize --optimize-context
|
|
|
391
418
|
|
|
392
419
|
```bash
|
|
393
420
|
# 启用脱敏以避免合规术语被误拦
|
|
394
|
-
uv run codebuddy_proxy
|
|
421
|
+
uv run --with workbuddy2api python -m codebuddy_proxy --desensitize \
|
|
422
|
+
--log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
395
423
|
|
|
396
424
|
# 示例请求
|
|
397
425
|
curl http://127.0.0.1:8787/v1/chat/completions \
|
|
@@ -465,10 +493,12 @@ curl http://127.0.0.1:8787/v1/chat/completions \
|
|
|
465
493
|
|
|
466
494
|
```bash
|
|
467
495
|
# 启用消息压缩
|
|
468
|
-
uv run codebuddy_proxy
|
|
496
|
+
uv run --with workbuddy2api python -m codebuddy_proxy --optimize-context \
|
|
497
|
+
--log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
469
498
|
|
|
470
499
|
# 同时启用两个功能(推荐用于 Codex CLI)
|
|
471
|
-
uv run codebuddy_proxy
|
|
500
|
+
uv run --with workbuddy2api python -m codebuddy_proxy --desensitize --optimize-context \
|
|
501
|
+
--log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
472
502
|
```
|
|
473
503
|
|
|
474
504
|
#### 工作原理
|
|
@@ -512,7 +542,7 @@ uv run codebuddy_proxy.py --desensitize --optimize-context
|
|
|
512
542
|
启用功能后,日志会记录压缩统计:
|
|
513
543
|
|
|
514
544
|
```bash
|
|
515
|
-
grep projection_applied
|
|
545
|
+
grep projection_applied "$HOME/.workbuddy2api/codebuddy-proxy.jsonl" | jq .
|
|
516
546
|
```
|
|
517
547
|
|
|
518
548
|
示例输出:
|
|
@@ -543,26 +573,36 @@ grep projection_applied logs/codebuddy-proxy.jsonl | jq .
|
|
|
543
573
|
### 日志
|
|
544
574
|
|
|
545
575
|
日志包含:
|
|
546
|
-
-
|
|
547
|
-
-
|
|
576
|
+
- 文本日志:`$HOME/.workbuddy2api/proxy.log`(按天滚动,保留 30 天)
|
|
577
|
+
- 结构化日志:`$HOME/.workbuddy2api/codebuddy-proxy.jsonl`(按天滚动,保留 30 天,完整请求/响应)
|
|
578
|
+
|
|
579
|
+
JSONL 每条记录包含 `app_version`、`system_version`、`python_version` 和 `machine` 字段;启动时还会记录 `startup` 事件。
|
|
580
|
+
|
|
581
|
+
也可以指定日志文件的绝对路径:
|
|
582
|
+
|
|
583
|
+
```bash
|
|
584
|
+
uv run --with workbuddy2api python -m codebuddy_proxy \
|
|
585
|
+
--desensitize \
|
|
586
|
+
--log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
587
|
+
```
|
|
548
588
|
|
|
549
589
|
查看日志:
|
|
550
590
|
|
|
551
591
|
```bash
|
|
552
592
|
# 实时查看
|
|
553
|
-
tail -f
|
|
593
|
+
tail -f "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
554
594
|
|
|
555
595
|
# 查看流式事件
|
|
556
|
-
tail -100
|
|
596
|
+
tail -100 "$HOME/.workbuddy2api/codebuddy-proxy.jsonl" | jq 'select(.event | startswith("stream"))'
|
|
557
597
|
|
|
558
598
|
# 统计超时
|
|
559
|
-
jq 'select(.event=="stream_timeout")'
|
|
599
|
+
jq 'select(.event=="stream_timeout")' "$HOME/.workbuddy2api/codebuddy-proxy.jsonl" | wc -l
|
|
560
600
|
|
|
561
601
|
# 验证脱敏
|
|
562
|
-
grep desensitize_applied
|
|
602
|
+
grep desensitize_applied "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
563
603
|
|
|
564
604
|
# 验证压缩(查看统计数据)
|
|
565
|
-
grep projection_applied
|
|
605
|
+
grep projection_applied "$HOME/.workbuddy2api/codebuddy-proxy.jsonl" | jq .
|
|
566
606
|
```
|
|
567
607
|
|
|
568
608
|
### 找不到 session 文件
|
|
@@ -570,7 +610,8 @@ grep projection_applied logs/codebuddy-proxy.jsonl | jq .
|
|
|
570
610
|
首次使用需要登录:
|
|
571
611
|
|
|
572
612
|
```bash
|
|
573
|
-
uv run codebuddy_proxy
|
|
613
|
+
uv run --with workbuddy2api python -m codebuddy_proxy --login \
|
|
614
|
+
--log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
574
615
|
```
|
|
575
616
|
|
|
576
617
|
### 401 认证失败
|
|
@@ -578,7 +619,8 @@ uv run codebuddy_proxy.py --login
|
|
|
578
619
|
Token 过期,重新登录:
|
|
579
620
|
|
|
580
621
|
```bash
|
|
581
|
-
uv run codebuddy_proxy
|
|
622
|
+
uv run --with workbuddy2api python -m codebuddy_proxy --login \
|
|
623
|
+
--log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
582
624
|
```
|
|
583
625
|
|
|
584
626
|
### 审核拦截
|
|
@@ -586,20 +628,23 @@ uv run codebuddy_proxy.py --login
|
|
|
586
628
|
启用脱敏:
|
|
587
629
|
|
|
588
630
|
```bash
|
|
589
|
-
uv run codebuddy_proxy
|
|
631
|
+
uv run --with workbuddy2api python -m codebuddy_proxy --desensitize \
|
|
632
|
+
--log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
590
633
|
```
|
|
591
634
|
|
|
592
635
|
如果仍然被拦截,尝试压缩优化(仅 `/v1/responses`):
|
|
593
636
|
|
|
594
637
|
```bash
|
|
595
|
-
uv run codebuddy_proxy
|
|
638
|
+
uv run --with workbuddy2api python -m codebuddy_proxy --desensitize --optimize-context \
|
|
639
|
+
--log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
596
640
|
```
|
|
597
641
|
|
|
598
642
|
### 端口被占用
|
|
599
643
|
|
|
600
644
|
```bash
|
|
601
645
|
lsof -i :8787
|
|
602
|
-
uv run codebuddy_proxy
|
|
646
|
+
uv run --with workbuddy2api python -m codebuddy_proxy --port 8788 \
|
|
647
|
+
--log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
603
648
|
```
|
|
604
649
|
|
|
605
650
|
### SOCKS proxy 错误
|
|
@@ -614,7 +659,8 @@ env | grep -i proxy
|
|
|
614
659
|
|
|
615
660
|
```bash
|
|
616
661
|
unset http_proxy https_proxy all_proxy
|
|
617
|
-
uv run codebuddy_proxy
|
|
662
|
+
uv run --with workbuddy2api python -m codebuddy_proxy \
|
|
663
|
+
--log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
|
|
618
664
|
```
|
|
619
665
|
|
|
620
666
|
## 技术细节
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|