workbuddy2api 2.0.3__tar.gz → 2.0.5__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 (25) hide show
  1. workbuddy2api-2.0.5/PKG-INFO +838 -0
  2. workbuddy2api-2.0.5/README.md +823 -0
  3. {workbuddy2api-2.0.3 → workbuddy2api-2.0.5}/pyproject.toml +31 -28
  4. {workbuddy2api-2.0.3 → workbuddy2api-2.0.5}/src/codebuddy_proxy/__main__.py +1813 -1560
  5. {workbuddy2api-2.0.3 → workbuddy2api-2.0.5}/src/codebuddy_proxy/anthropic_adapter.py +5 -2
  6. workbuddy2api-2.0.5/src/codebuddy_proxy/backend_profile.py +198 -0
  7. {workbuddy2api-2.0.3 → workbuddy2api-2.0.5}/src/codebuddy_proxy/codebuddy_client_demo.py +463 -287
  8. {workbuddy2api-2.0.3 → workbuddy2api-2.0.5}/src/codebuddy_proxy/desensitize.py +34 -0
  9. {workbuddy2api-2.0.3 → workbuddy2api-2.0.5}/src/codebuddy_proxy/dsml_parser.py +983 -888
  10. workbuddy2api-2.0.5/src/codebuddy_proxy/models_config.domestic.json +464 -0
  11. workbuddy2api-2.0.5/src/codebuddy_proxy/models_config.global.json +150 -0
  12. workbuddy2api-2.0.5/src/workbuddy2api.egg-info/PKG-INFO +838 -0
  13. {workbuddy2api-2.0.3 → workbuddy2api-2.0.5}/src/workbuddy2api.egg-info/SOURCES.txt +3 -0
  14. workbuddy2api-2.0.3/PKG-INFO +0 -680
  15. workbuddy2api-2.0.3/README.md +0 -665
  16. workbuddy2api-2.0.3/src/workbuddy2api.egg-info/PKG-INFO +0 -680
  17. {workbuddy2api-2.0.3 → workbuddy2api-2.0.5}/LICENSE +0 -0
  18. {workbuddy2api-2.0.3 → workbuddy2api-2.0.5}/setup.cfg +0 -0
  19. {workbuddy2api-2.0.3 → workbuddy2api-2.0.5}/src/codebuddy_proxy/projection_metadata.py +0 -0
  20. {workbuddy2api-2.0.3 → workbuddy2api-2.0.5}/src/codebuddy_proxy/responses_adapter.py +0 -0
  21. {workbuddy2api-2.0.3 → workbuddy2api-2.0.5}/src/codebuddy_proxy/responses_projection.py +0 -0
  22. {workbuddy2api-2.0.3 → workbuddy2api-2.0.5}/src/workbuddy2api.egg-info/dependency_links.txt +0 -0
  23. {workbuddy2api-2.0.3 → workbuddy2api-2.0.5}/src/workbuddy2api.egg-info/entry_points.txt +0 -0
  24. {workbuddy2api-2.0.3 → workbuddy2api-2.0.5}/src/workbuddy2api.egg-info/requires.txt +0 -0
  25. {workbuddy2api-2.0.3 → workbuddy2api-2.0.5}/src/workbuddy2api.egg-info/top_level.txt +0 -0
@@ -0,0 +1,838 @@
1
+ Metadata-Version: 2.4
2
+ Name: workbuddy2api
3
+ Version: 2.0.5
4
+ Summary: Local OpenAI/Responses/Anthropic compatible proxy for CodeBuddy
5
+ Requires-Python: >=3.10
6
+ Description-Content-Type: text/markdown
7
+ License-File: LICENSE
8
+ Requires-Dist: fastapi>=0.104.0
9
+ Requires-Dist: uvicorn>=0.24.0
10
+ Requires-Dist: httpx[socks]>=0.25.0
11
+ Requires-Dist: requests>=2.31.0
12
+ Provides-Extra: dev
13
+ Requires-Dist: pytest>=7.4.0; extra == "dev"
14
+ Dynamic: license-file
15
+
16
+ # CodeBuddy API Proxy
17
+
18
+ > A lightweight API proxy service that converts CodeBuddy's underlying interface into standard OpenAI, Anthropic, and Responses protocol formats.
19
+
20
+ > **中文版文档见 [README_zh.md](README_zh.md).**
21
+
22
+ ## ✨ Core Features
23
+
24
+ - **Protocol conversion** - Supports three standard formats: OpenAI Chat Completions, Anthropic Messages API, and Responses
25
+ - **Desensitization** - Built-in smart desensitization module that automatically filters sensitive information (accounts, passwords, keys, brand terms, paths, etc.) to mitigate review-based false blocks
26
+ - **Message compression** - Intelligently compresses historical messages to dramatically reduce token usage (ideal for long-context scenarios such as Codex CLI)
27
+ - **Tool call support** - Full support for function calling and tool use, with automatic filtering of invalid tool definitions
28
+ - **DSML parsing** - Automatically detects and converts DeepSeek Markup Language (DSML) tool calls
29
+ - **Streaming responses** - SSE streaming output, returning generated content in real time, with built-in 60-second timeout protection
30
+ - **Domestic and international backends** - Uses domestic CodeBuddy by default and switches to the international CodeBuddy service with `--global`, with isolated sessions and model catalogs
31
+ - **Multi-account management** - Supports isolation of multiple login states for easy switching between work/personal accounts
32
+
33
+ ---
34
+
35
+ ## Installation
36
+
37
+ Recommended to run from PyPI using [uv](https://docs.astral.sh/uv/):
38
+
39
+ ```bash
40
+ # Install uv
41
+ curl -LsSf https://astral.sh/uv/install.sh | sh
42
+
43
+ # Run the latest available version (uv automatically creates the environment and installs dependencies)
44
+ uv run --with workbuddy2api python -m codebuddy_proxy \
45
+ --log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
46
+
47
+ # Force refresh the cache and run the latest version
48
+ uv run --refresh-package workbuddy2api --with workbuddy2api \
49
+ python -m codebuddy_proxy \
50
+ --log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
51
+ ```
52
+
53
+ No need to manually activate the virtual environment on subsequent starts; just repeat the `uv run` command above.
54
+
55
+ ### Running from local source
56
+
57
+ Run the following commands from the project root to use the workspace source code instead of the published PyPI version:
58
+
59
+ ```bash
60
+ # Sync local project dependencies
61
+ uv sync
62
+
63
+ # Start the local source
64
+ uv run python -m codebuddy_proxy --desensitize
65
+ ```
66
+
67
+ On first use, when login is required:
68
+
69
+ ```bash
70
+ uv run python -m codebuddy_proxy --login --desensitize
71
+ ```
72
+
73
+ ## Quick Start
74
+
75
+ ### 1. Start the proxy
76
+
77
+ ```bash
78
+ # Use the latest version (recommended)
79
+ uv run --with workbuddy2api python -m codebuddy_proxy --desensitize
80
+
81
+ # First use: log in and start
82
+ uv run --with workbuddy2api python -m codebuddy_proxy --login --desensitize
83
+
84
+ # International service: first login and start
85
+ uv run --with workbuddy2api python -m codebuddy_proxy --global --login --desensitize
86
+
87
+ # International service: later starts
88
+ uv run --with workbuddy2api python -m codebuddy_proxy --global --desensitize
89
+ ```
90
+
91
+ Listens on `http://127.0.0.1:8787` by default.
92
+
93
+ ### Domestic and international CodeBuddy backends
94
+
95
+ The proxy supports both CodeBuddy regions. Domestic mode remains the default,
96
+ so existing startup commands continue to work unchanged.
97
+
98
+ | Mode | Startup option | Upstream endpoint | Default session file |
99
+ | --- | --- | --- | --- |
100
+ | Domestic (default) | none | `https://copilot.tencent.com` | `~/.codebuddy-session.json` |
101
+ | International | `--global` | `https://www.codebuddy.ai` | `~/.codebuddy-global-session.json` |
102
+
103
+ First login and daily startup for the international service:
104
+
105
+ ```bash
106
+ # First login
107
+ uv run --with workbuddy2api python -m codebuddy_proxy \
108
+ --global --login --desensitize
109
+
110
+ # Later starts reuse the international session
111
+ uv run --with workbuddy2api python -m codebuddy_proxy \
112
+ --global --desensitize
113
+ ```
114
+
115
+ If the package is installed as a command, the equivalent short form is
116
+ `workbuddy2api --global --login`. When running from source, use
117
+ `uv run python -m codebuddy_proxy --global --login`.
118
+
119
+ `--global` changes only the upstream service. Codex CLI, Claude Code/CC Switch,
120
+ OpenCode, and other clients continue to use the same local proxy URLs. The
121
+ selected profile also controls the model catalog returned by `/v1/models`.
122
+
123
+ Domestic and international sessions are intentionally isolated. An explicit
124
+ `--session-file` takes precedence, but its saved backend and endpoint must match
125
+ the current startup options. The proxy refuses mismatched credentials and does
126
+ not modify the original file.
127
+
128
+ For a custom international endpoint, always use a dedicated session file:
129
+
130
+ ```bash
131
+ uv run --with workbuddy2api python -m codebuddy_proxy \
132
+ --global \
133
+ --endpoint https://staging-codebuddy.tencent.com \
134
+ --session-file "$HOME/.codebuddy-global-staging-session.json" \
135
+ --login
136
+ ```
137
+
138
+ Endpoint precedence is: explicit `--endpoint` > the `--global` profile default
139
+ > `CODEBUDDY_ENDPOINT` in non-global mode > the domestic default endpoint.
140
+ Therefore `--global` without `--endpoint` cannot be redirected to the domestic
141
+ host by `CODEBUDDY_ENDPOINT`.
142
+
143
+ Runtime model catalogs are loaded from the packaged profile resources
144
+ `src/codebuddy_proxy/models_config.domestic.json` and
145
+ `src/codebuddy_proxy/models_config.global.json`. The root
146
+ `models_config.json` is retained only as a development-compatibility copy of
147
+ the domestic catalog and is not a runtime data source.
148
+
149
+ ### 2. Verify
150
+
151
+ ```bash
152
+ curl http://127.0.0.1:8787/health
153
+ curl http://127.0.0.1:8787/v1/models
154
+ ```
155
+
156
+ The health response reports the active `backend` (`domestic` or `global`) and
157
+ `upstream_endpoint`, which makes it easy to confirm the selected region before
158
+ connecting a client.
159
+
160
+ ### 3. Connect clients
161
+
162
+ #### Codex CLI
163
+
164
+ Edit `~/.codex/config.toml`:
165
+
166
+ ```toml
167
+ [model_providers.codebuddy]
168
+ name = "CodeBuddy (via local proxy)"
169
+ base_url = "http://127.0.0.1:8787/v1"
170
+ wire_api = "responses"
171
+
172
+ [profiles.codebuddy]
173
+ model = "glm-5.2"
174
+ model_provider = "codebuddy"
175
+ ```
176
+
177
+ Usage:
178
+
179
+ ```bash
180
+ codex --profile codebuddy "your task"
181
+ ```
182
+
183
+ #### Claude Code + CC Switch
184
+
185
+ Add the following to your CC Switch configuration:
186
+
187
+ ```json
188
+ {
189
+ "DeepSeek-V4": {
190
+ "base_url": "http://127.0.0.1:8787/v1/messages",
191
+ "api_key": "",
192
+ "model": "deepseek-v4-pro"
193
+ }
194
+ }
195
+ ```
196
+
197
+ #### OpenCode
198
+
199
+ Edit `opencode.json` in the project root:
200
+
201
+ ```json
202
+ {
203
+ "$schema": "https://opencode.ai/config.json",
204
+ "model": "codebuddy/glm-5.2",
205
+ "providers": {
206
+ "codebuddy": {
207
+ "name": "CodeBuddy (via local proxy)",
208
+ "package": "@opencode-ai/ai/providers/openai-compatible",
209
+ "settings": {
210
+ "baseURL": "http://127.0.0.1:8787/v1",
211
+ "apiKey": "noop"
212
+ },
213
+ "models": {
214
+ "glm-5.2": { "modelID": "glm-5.2", "name": "GLM-5.2" },
215
+ "deepseek-v4-pro": { "modelID": "deepseek-v4-pro", "name": "DeepSeek V4 Pro" },
216
+ "kimi-k2.7": { "modelID": "kimi-k2.7", "name": "Kimi K2.7" }
217
+ }
218
+ }
219
+ }
220
+ }
221
+ ```
222
+
223
+ After launching opencode, use the `/models` command to select a model under the `codebuddy` provider (e.g. `codebuddy/glm-5.2`).
224
+
225
+ > Note: `baseURL` points to the local proxy; `apiKey` can be any placeholder value (the local proxy does not validate keys). The `models` keys are the model IDs used inside OpenCode (for selection), while `modelID` is the actual model name sent to the proxy. Use `apiKey` for the key field (not `env_key` from some older templates), to avoid binding the wrong provider semantics.
226
+
227
+ #### Grok CLI
228
+
229
+ Edit `~/.grok/config.toml` and add a `[model.<name>]` entry per model that points at the local proxy. Grok uses the OpenAI Chat Completions backend (`/v1/chat/completions`) by default, which this proxy supports:
230
+
231
+ ```toml
232
+ [models]
233
+ default = "hy3" # optional: set your default model
234
+
235
+ [model.hy3]
236
+ model = "hy3" # model id sent to the proxy
237
+ base_url = "http://127.0.0.1:8787/v1"
238
+ name = "HY3 Main" # shown in the model picker
239
+ api_key = "noop" # any placeholder value works
240
+
241
+ [model.dv4f]
242
+ model = "deepseek-v4-flash"
243
+ base_url = "http://127.0.0.1:8787/v1"
244
+ name = "DeepSeek V4 Flash"
245
+ api_key = "noop"
246
+ ```
247
+
248
+ Then switch to the proxy model in the TUI with `/model hy3` (or `Ctrl+M` model picker), or run headless with `grok -m hy3 "your task"`.
249
+
250
+ > Note: `base_url` points to the local proxy; `api_key` can be any placeholder value (the local proxy does not validate keys). You can also set `api_backend = "responses"` to use the `/v1/responses` endpoint, or `"messages"` for the Anthropic `/v1/messages` endpoint, depending on your needs.
251
+
252
+ #### Oh My Pi (OMP)
253
+
254
+ [Oh My Pi](https://github.com/can1357/oh-my-pi) is a terminal coding agent (formerly known as `pi`). It reads custom providers from `~/.omp/agent/models.yml`, so the local proxy is configured as a keyless OpenAI-compatible endpoint.
255
+
256
+ Add a `codebuddy` provider (the exact models follow the IDs returned by `/v1/models`, e.g. `hy3`, `glm-5.2`, `deepseek-v4-flash`, `kimi-k2.7`):
257
+
258
+ ```yaml
259
+ # ~/.omp/agent/models.yml
260
+ providers:
261
+ codebuddy:
262
+ baseUrl: http://127.0.0.1:8787/v1
263
+ api: openai-completions
264
+ auth: none
265
+ models:
266
+ - id: hy3
267
+ name: Hy3 (CodeBuddy)
268
+ reasoning: true
269
+ contextWindow: 192000
270
+ maxTokens: 64000
271
+ - id: glm-5.2
272
+ name: GLM-5.2 (CodeBuddy)
273
+ reasoning: true
274
+ contextWindow: 1000000
275
+ maxTokens: 48000
276
+ - id: deepseek-v4-flash
277
+ name: DeepSeek V4 Flash (CodeBuddy)
278
+ reasoning: true
279
+ contextWindow: 1000000
280
+ maxTokens: 50000
281
+ - id: kimi-k2.7
282
+ name: Kimi K2.7 (CodeBuddy)
283
+ reasoning: true
284
+ contextWindow: 256000
285
+ maxTokens: 32000
286
+ ```
287
+
288
+ Notes:
289
+
290
+ - `auth: none` marks the provider keyless, so the proxy's own session file handles authentication. No `apiKey` is needed (the proxy does not validate keys anyway).
291
+ - `api: openai-completions` routes requests through `/v1/chat/completions`, which this proxy supports. If your OMP build or model needs the Responses wire format instead, use `api: openai-responses` (routes through `/v1/responses`).
292
+ - The proxy already strips OpenAI extension fields (`strict`, `additionalProperties`) from tool schemas before forwarding to CodeBuddy, so you generally do **not** need `disableStrictTools: true` — add it only if a CodeBuddy backend revision starts rejecting tool requests.
293
+
294
+ Select the model inside OMP with `/model codebuddy/hy3` (or set it as the default in your OMP profile), or run headless with `omp --model codebuddy/hy3 "your task"`. Model selection is by exact `provider/modelId`.
295
+
296
+ #### Other OpenAI-compatible clients
297
+
298
+ - Base URL: `http://127.0.0.1:8787/v1`
299
+ - API Key: leave blank (or use the value you set with `--api-key` at startup)
300
+ - Model name: `glm-5.2` / `deepseek-v4-pro` / `kimi-k2.7` / `auto`, etc.
301
+
302
+ ## Command-line arguments
303
+
304
+ ```bash
305
+ --host HOST Bind address (default 127.0.0.1)
306
+ --port PORT Bind port (default 8787)
307
+ --global Use the international CodeBuddy backend (default domestic)
308
+ --endpoint ENDPOINT CodeBuddy backend address (overrides the profile default)
309
+ --session-file PATH Session file path (isolated by profile by default)
310
+ --log-file PATH JSONL log file (default ~/.workbuddy2api/codebuddy-proxy.jsonl)
311
+ --desensitize Enable desensitization (recommended)
312
+ --optimize-context Enable message compression (recommended for Codex CLI)
313
+ --login Perform browser login at startup
314
+ --no-browser Do not open the browser on login
315
+ --verbose-llm Log full LLM request/response content
316
+ (default: summary only, saves 98% space)
317
+ --mock-dir DIR Use mock data (for testing)
318
+ ```
319
+
320
+ ### Environment variables
321
+
322
+ ```bash
323
+ CODEBUDDY_PROXY_HOST # Same as --host
324
+ CODEBUDDY_PROXY_PORT # Same as --port
325
+ CODEBUDDY_ENDPOINT # Endpoint fallback in non-global mode
326
+ CODEBUDDY_PROXY_LOG_FILE # Same as --log-file
327
+ ```
328
+
329
+ ## Common scenarios
330
+
331
+ ### First use (login required)
332
+
333
+ ```bash
334
+ uv run --with workbuddy2api python -m codebuddy_proxy --login \
335
+ --log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
336
+ ```
337
+
338
+ After the browser opens and you log in, the proxy starts automatically.
339
+
340
+ First login for the international backend:
341
+
342
+ ```bash
343
+ uv run --with workbuddy2api python -m codebuddy_proxy --global --login \
344
+ --log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
345
+ ```
346
+
347
+ ### Daily use (automatically reads the login state)
348
+
349
+ ```bash
350
+ uv run --with workbuddy2api python -m codebuddy_proxy --desensitize \
351
+ --log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
352
+ ```
353
+
354
+ For the international backend, keep `--global` on every startup:
355
+
356
+ ```bash
357
+ uv run --with workbuddy2api python -m codebuddy_proxy --global --desensitize \
358
+ --log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
359
+ ```
360
+
361
+ ### Codex CLI scenario (with compression enabled)
362
+
363
+ ```bash
364
+ uv run --with workbuddy2api python -m codebuddy_proxy --desensitize --optimize-context \
365
+ --log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
366
+ ```
367
+
368
+ ### Multi-account switching
369
+
370
+ ```bash
371
+ # Account 1
372
+ uv run --with workbuddy2api python -m codebuddy_proxy --session-file ~/.codebuddy-work.json --login \
373
+ --log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
374
+
375
+ # Account 2
376
+ uv run --with workbuddy2api python -m codebuddy_proxy --session-file ~/.codebuddy-personal.json --login \
377
+ --log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
378
+ ```
379
+
380
+ ### Listening on all interfaces (LAN sharing)
381
+
382
+ ```bash
383
+ uv run --with workbuddy2api python -m codebuddy_proxy --host 0.0.0.0 --desensitize \
384
+ --log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
385
+ ```
386
+
387
+ ## API endpoints
388
+
389
+ All endpoints do not require an extra token in the request by default; the proxy authenticates using the local session.
390
+
391
+ | Method | Path | Purpose |
392
+ | --- | --- | --- |
393
+ | GET | `/health` | Query local service and auth status |
394
+ | GET | `/v1/models` | Query the CodeBuddy model list |
395
+ | POST | `/v1/chat/completions` | OpenAI Chat Completions, supports tools and streaming |
396
+ | POST | `/v1/responses` | Responses API, compatible with Codex CLI |
397
+ | POST | `/v1/messages` | Anthropic Messages API, compatible with Claude Code / CC Switch |
398
+
399
+ ### `/health` - health check
400
+
401
+ ```bash
402
+ curl http://127.0.0.1:8787/health
403
+ ```
404
+
405
+ Example response:
406
+
407
+ ```json
408
+ {
409
+ "status": "ok",
410
+ "uptime_seconds": 123,
411
+ "authenticated": true,
412
+ "token_valid": true,
413
+ "backend": "global",
414
+ "upstream_endpoint": "https://www.codebuddy.ai"
415
+ }
416
+ ```
417
+
418
+ ### `/v1/models` - model list
419
+
420
+ ```bash
421
+ curl http://127.0.0.1:8787/v1/models
422
+ ```
423
+
424
+ Returns the active backend's model catalog in OpenAI format. `data[].id` is the
425
+ `model` value used in subsequent requests; domestic and international mode may
426
+ expose different model IDs.
427
+
428
+ ### `/v1/chat/completions` - OpenAI Chat
429
+
430
+ **Non-streaming request:**
431
+
432
+ ```bash
433
+ curl http://127.0.0.1:8787/v1/chat/completions \
434
+ -H 'Content-Type: application/json' \
435
+ -d '{
436
+ "model": "deepseek-v4-flash",
437
+ "messages": [{"role": "user", "content": "Write a quicksort"}]
438
+ }'
439
+ ```
440
+
441
+ **Streaming request:**
442
+
443
+ ```bash
444
+ curl -N http://127.0.0.1:8787/v1/chat/completions \
445
+ -H 'Content-Type: application/json' \
446
+ -d '{
447
+ "model": "glm-5.2",
448
+ "stream": true,
449
+ "messages": [{"role": "user", "content": "hi"}]
450
+ }'
451
+ ```
452
+
453
+ Supports the full set of OpenAI features, including `tools`, `tool_choice`, and `stream_options`.
454
+
455
+ ### `/v1/responses` - Responses API
456
+
457
+ Used for Codex CLI compatibility:
458
+
459
+ ```bash
460
+ curl http://127.0.0.1:8787/v1/responses \
461
+ -H 'Content-Type: application/json' \
462
+ -d '{
463
+ "model": "default",
464
+ "input": "Write a quicksort"
465
+ }'
466
+ ```
467
+
468
+ Supports `instructions` (system prompt), message-form `input`, `tools`, `tool_choice`, and `stream`.
469
+
470
+ **💡 Tip:** Using `--optimize-context` dramatically reduces token usage for Codex CLI.
471
+
472
+ ### `/v1/messages` - Anthropic Messages
473
+
474
+ Used for Claude Code / CC Switch compatibility:
475
+
476
+ ```bash
477
+ curl http://127.0.0.1:8787/v1/messages \
478
+ -H 'Content-Type: application/json' \
479
+ -d '{
480
+ "model": "deepseek-v4-pro",
481
+ "max_tokens": 4096,
482
+ "messages": [{"role": "user", "content": "hi"}]
483
+ }'
484
+ ```
485
+
486
+ Setting `"stream": true` returns an Anthropic SSE event stream.
487
+
488
+ ## Advanced features
489
+
490
+ ### Desensitization (`--desensitize`)
491
+
492
+ Inserts zero-width spaces (U+200B) into sensitive words in system messages, breaking the backend's keyword matching and mitigating compliance templates being falsely blocked by review.
493
+
494
+ #### When to use it
495
+
496
+ **Scenarios where enabling is strongly recommended:**
497
+
498
+ 1. **Integrating with Claude Code / CC Switch**
499
+ - Claude Code's system prompt contains many Anthropic brand terms and security compliance statements
500
+ - The Tencent backend may treat competing brand terms ("Claude", "Anthropic") as sensitive content
501
+ - Without desensitization, almost every request gets blocked by review
502
+
503
+ 2. **Integrating with agentic tools such as Codex CLI / Oh My Posh**
504
+ - These tools' system prompts contain a large number of security terms (DoS, exploit, credential testing, etc.)
505
+ - Even compliant "refuse harmful requests" statements can be falsely blocked by keyword matching
506
+
507
+ 3. **Using custom system prompts that contain security terms**
508
+ - Compliance conversations related to security research and penetration testing
509
+ - Generating technical documentation that needs to discuss vulnerabilities and attack defenses
510
+
511
+ **Typical error message:**
512
+ ```json
513
+ {
514
+ "error": {
515
+ "message": "内容违规",
516
+ "type": "content_policy_violation"
517
+ }
518
+ }
519
+ ```
520
+ Or the backend returns an empty response / connection drops.
521
+
522
+ **Scenarios where you don't need it:**
523
+ - ✅ Normal conversation (no security terms)
524
+ - ✅ Using the official CodeBuddy client (handling is built in)
525
+ - ✅ Pure code generation (no brand terms / security statements)
526
+
527
+ #### Typical use cases
528
+
529
+ **Case 1: Integrating with Claude Code**
530
+
531
+ ```bash
532
+ # --desensitize is required, otherwise almost every request is blocked
533
+ uv run --with workbuddy2api python -m codebuddy_proxy --desensitize \
534
+ --log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
535
+
536
+ # Configure in Claude Code / CC Switch
537
+ # Base URL: http://127.0.0.1:8787/v1/messages
538
+ ```
539
+
540
+ **Case 2: Integrating with Codex CLI**
541
+
542
+ ```bash
543
+ # Enable both desensitization and message compression (best configuration)
544
+ uv run --with workbuddy2api python -m codebuddy_proxy --desensitize --optimize-context \
545
+ --log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
546
+
547
+ # In the Codex CLI config file
548
+ # base_url: http://127.0.0.1:8787/v1/responses
549
+ ```
550
+
551
+ **Case 3: Security research conversation**
552
+
553
+ ```bash
554
+ # Enable desensitization to avoid compliance terms being falsely blocked
555
+ uv run --with workbuddy2api python -m codebuddy_proxy --desensitize \
556
+ --log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
557
+
558
+ # Example request
559
+ curl http://127.0.0.1:8787/v1/chat/completions \
560
+ -H 'Content-Type: application/json' \
561
+ -d '{
562
+ "model": "deepseek-v4-pro",
563
+ "messages": [
564
+ {
565
+ "role": "system",
566
+ "content": "You are a security expert. Refuse requests for exploit development."
567
+ },
568
+ {
569
+ "role": "user",
570
+ "content": "Explain defenses against SQL injection"
571
+ }
572
+ ]
573
+ }'
574
+ ```
575
+
576
+ #### How it works
577
+
578
+ ```python
579
+ # Original
580
+ "Refuse requests for DoS attacks and exploit development."
581
+
582
+ # Desensitized (zero-width space U+200B inserted)
583
+ "Refuse requests for Do​S a​ttacks and e​xploit development."
584
+ # Human/model: looks exactly the same
585
+ # Backend review: keyword matching fails
586
+ ```
587
+
588
+ #### Scope of processing
589
+
590
+ - ✅ `system` role messages (default)
591
+ - ✅ `developer` role messages
592
+ - ✅ Harness user messages injected by Codex CLI / Claude Code
593
+ - ✅ `description` field of `tools`
594
+ - ❌ `user`/`assistant` messages (kept as-is, so normal conversation is unaffected)
595
+
596
+ #### Sensitive word list
597
+
598
+ Roughly 80 security/compliance terms:
599
+ - Attack types: DoS, DDoS, exploit, SQL injection, XSS, malware...
600
+ - Security terms: vulnerability, penetration testing, privilege escalation...
601
+ - Brand terms: Claude Code, Anthropic (to avoid competing brands triggering review)
602
+
603
+ The full list is in `SENSITIVE_TERMS` in `desensitize.py`.
604
+
605
+ #### Notes
606
+
607
+ - ✅ Only processes compliance statements; does not bypass review of harmful input
608
+ - ✅ Only modifies system messages; real user input is kept as-is
609
+ - ⚠️ Zero-width spaces are transparent to humans/models but affect exact string matching
610
+ - ⚠️ Performance cost: <1ms (regex replacement)
611
+
612
+ ---
613
+
614
+ ### Message compression (`--optimize-context`)
615
+
616
+ Only applies to the `/v1/responses` endpoint, compressing long histories, large schemas, and oversized tool outputs into a "minimal semantic closure", dramatically reducing token usage (possibly 60-90%).
617
+
618
+ #### When to use it
619
+
620
+ - ✅ Using agentic tools such as Codex CLI / Claude Code (long histories)
621
+ - ✅ High token usage (>100k/day)
622
+ - ✅ Frequently hitting "context" errors
623
+ - ✅ Sending the full history on every request
624
+ - ❌ Not for short conversations / simple requests
625
+
626
+ #### Usage
627
+
628
+ ```bash
629
+ # Enable message compression
630
+ uv run --with workbuddy2api python -m codebuddy_proxy --optimize-context \
631
+ --log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
632
+
633
+ # Enable both features (recommended for Codex CLI)
634
+ uv run --with workbuddy2api python -m codebuddy_proxy --desensitize --optimize-context \
635
+ --log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
636
+ ```
637
+
638
+ #### How it works
639
+
640
+ ##### Conservative mode (non-agentic requests)
641
+
642
+ Only length trimming:
643
+ - System → truncated to 1200 characters
644
+ - User → 3200 characters
645
+ - Assistant → keep a head/tail summary (1800)
646
+ - Tool output → compressed to 1600 characters
647
+
648
+ ##### Aggressive mode (agentic CLI requests)
649
+
650
+ Automatically detects agentic requests (tools containing `exec_command`, `apply_patch`, etc., or messages containing harness markers) and reconstructs them into a minimal semantic closure:
651
+
652
+ 1. **Drop harness messages** — remove all Codex/Claude Code injected system/user messages
653
+ 2. **Keep recent context** — keep ≤8 messages / ≤7000 chars from the tail
654
+ 3. **Summarize history** — compress earlier history into rule summaries (one line each)
655
+ 4. **Schema convergence** — keep only structural fields, drop descriptions (the biggest space consumers)
656
+ 5. **Compress tool output/arguments** — keep key parts, omit the rest
657
+
658
+ #### Example effect
659
+
660
+ ```
661
+ Original request:
662
+ - Messages: 50, 120,000 characters
663
+ - Tools: 15, 45,000 characters
664
+ - Total: ~165,000 characters (~40k tokens)
665
+
666
+ After compression:
667
+ - Messages: 12, 18,000 characters
668
+ - Tools: 15, 8,000 characters
669
+ - Total: ~26,000 characters (~6k tokens)
670
+
671
+ Savings: ~85% tokens
672
+ ```
673
+
674
+ #### Log verification
675
+
676
+ Once enabled, the log records compression statistics:
677
+
678
+ ```bash
679
+ grep projection_applied "$HOME/.workbuddy2api/codebuddy-proxy.jsonl" | jq .
680
+ ```
681
+
682
+ Example output:
683
+
684
+ ```json
685
+ {
686
+ "event": "projection_applied",
687
+ "protocol": "responses",
688
+ "mode": "aggressive",
689
+ "original_messages": 50,
690
+ "projected_messages": 12,
691
+ "original_message_chars": 120000,
692
+ "projected_message_chars": 18000,
693
+ "dropped_harness_messages": 8
694
+ }
695
+ ```
696
+
697
+ #### Notes
698
+
699
+ - ✅ Only used for `/v1/responses`; does not affect the chat/messages endpoints
700
+ - ✅ Preserves the semantic closure; the model can still reason
701
+ - ⚠️ History is summarized; precise details require re-running tools to retrieve
702
+ - ⚠️ Schema is trimmed; auxiliary info such as descriptions is lost
703
+ - ⚠️ Performance cost: <10ms (traversal + compression)
704
+
705
+ ---
706
+
707
+ ### Logging
708
+
709
+ Logs include:
710
+ - Text log: `$HOME/.workbuddy2api/proxy.log` (rotated daily, retained 30 days)
711
+ - Structured log: `$HOME/.workbuddy2api/codebuddy-proxy.jsonl` (rotated daily, retained 30 days, full request/response)
712
+
713
+ Each JSONL record contains `app_version`, `system_version`, `python_version`, and `machine` fields; a `startup` event is also recorded at launch.
714
+
715
+ You can also specify an absolute path for the log file:
716
+
717
+ ```bash
718
+ uv run --with workbuddy2api python -m codebuddy_proxy \
719
+ --desensitize \
720
+ --log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
721
+ ```
722
+
723
+ Viewing logs:
724
+
725
+ ```bash
726
+ # Follow in real time
727
+ tail -f "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
728
+
729
+ # View streaming events
730
+ tail -100 "$HOME/.workbuddy2api/codebuddy-proxy.jsonl" | jq 'select(.event | startswith("stream"))'
731
+
732
+ # Count timeouts
733
+ jq 'select(.event=="stream_timeout")' "$HOME/.workbuddy2api/codebuddy-proxy.jsonl" | wc -l
734
+
735
+ # Verify desensitization
736
+ grep desensitize_applied "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
737
+
738
+ # Verify compression (view statistics)
739
+ grep projection_applied "$HOME/.workbuddy2api/codebuddy-proxy.jsonl" | jq .
740
+ ```
741
+
742
+ ## Troubleshooting
743
+
744
+ ### Session file not found
745
+
746
+ First use requires login:
747
+
748
+ ```bash
749
+ uv run --with workbuddy2api python -m codebuddy_proxy --login \
750
+ --log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
751
+ ```
752
+
753
+ For the international backend, add `--global` to the same command. It creates
754
+ and later reuses `~/.codebuddy-global-session.json`.
755
+
756
+ ### Session backend or endpoint mismatch
757
+
758
+ Do not reuse a domestic session for the international backend, or a production
759
+ session for a custom endpoint. Log in with the same backend options you plan to
760
+ use later:
761
+
762
+ ```bash
763
+ # International default endpoint
764
+ uv run --with workbuddy2api python -m codebuddy_proxy --global --login
765
+
766
+ # Custom international endpoint with an isolated session
767
+ uv run --with workbuddy2api python -m codebuddy_proxy \
768
+ --global --endpoint https://staging-codebuddy.tencent.com \
769
+ --session-file "$HOME/.codebuddy-global-staging-session.json" --login
770
+ ```
771
+
772
+ The proxy intentionally rejects mismatched session metadata instead of sending
773
+ the saved token to another host.
774
+
775
+ ### 401 authentication failure
776
+
777
+ Token expired; log in again:
778
+
779
+ ```bash
780
+ uv run --with workbuddy2api python -m codebuddy_proxy --login \
781
+ --log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
782
+ ```
783
+
784
+ ### Review blocking
785
+
786
+ Enable desensitization:
787
+
788
+ ```bash
789
+ uv run --with workbuddy2api python -m codebuddy_proxy --desensitize \
790
+ --log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
791
+ ```
792
+
793
+ If still blocked, try compression (`/v1/responses` only):
794
+
795
+ ```bash
796
+ uv run --with workbuddy2api python -m codebuddy_proxy --desensitize --optimize-context \
797
+ --log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
798
+ ```
799
+
800
+ ### Port already in use
801
+
802
+ ```bash
803
+ lsof -i :8787
804
+ uv run --with workbuddy2api python -m codebuddy_proxy --port 8788 \
805
+ --log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
806
+ ```
807
+
808
+ ### SOCKS proxy errors
809
+
810
+ The `httpx[socks]` dependency is installed automatically. If problems persist, check the environment variables:
811
+
812
+ ```bash
813
+ env | grep -i proxy
814
+ ```
815
+
816
+ Temporarily disable the proxy:
817
+
818
+ ```bash
819
+ unset http_proxy https_proxy all_proxy
820
+ uv run --with workbuddy2api python -m codebuddy_proxy \
821
+ --log-file "$HOME/.workbuddy2api/codebuddy-proxy.jsonl"
822
+ ```
823
+
824
+ ## Technical details
825
+
826
+ - **Architecture**: FastAPI + httpx (async)
827
+ - **Concurrency**: supports 1000+ concurrent requests
828
+ - **Timeouts**: connect 10 seconds, read 30 seconds
829
+ - **Streaming**: full streaming logs (started / progress / completed / timeout)
830
+
831
+ ## Disclaimer
832
+
833
+ **This project is for learning and research purposes only. Please comply with CodeBuddy's Terms of Service.**
834
+
835
+ - This project provides no warranty of any kind
836
+ - Any consequences arising from the use of this project are the sole responsibility of the user
837
+ - Do not use this project for any purpose that violates CodeBuddy's Terms of Service
838
+ - Do not use this project for commercial purposes