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