local-openai2anthropic 0.2.4__tar.gz → 0.3.6__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.
- local_openai2anthropic-0.3.6/.claude/CLAUDE.md +163 -0
- local_openai2anthropic-0.3.6/.reports/dead-code-analysis.md +282 -0
- {local_openai2anthropic-0.2.4 → local_openai2anthropic-0.3.6}/PKG-INFO +51 -28
- {local_openai2anthropic-0.2.4 → local_openai2anthropic-0.3.6}/README.md +49 -27
- {local_openai2anthropic-0.2.4 → local_openai2anthropic-0.3.6}/README_zh.md +48 -26
- {local_openai2anthropic-0.2.4 → local_openai2anthropic-0.3.6}/pyproject.toml +2 -1
- {local_openai2anthropic-0.2.4 → local_openai2anthropic-0.3.6}/src/local_openai2anthropic/__init__.py +1 -1
- local_openai2anthropic-0.3.6/src/local_openai2anthropic/config.py +181 -0
- {local_openai2anthropic-0.2.4 → local_openai2anthropic-0.3.6}/src/local_openai2anthropic/converter.py +82 -60
- {local_openai2anthropic-0.2.4 → local_openai2anthropic-0.3.6}/src/local_openai2anthropic/main.py +83 -12
- {local_openai2anthropic-0.2.4 → local_openai2anthropic-0.3.6}/src/local_openai2anthropic/protocol.py +1 -1
- local_openai2anthropic-0.3.6/src/local_openai2anthropic/router.py +424 -0
- local_openai2anthropic-0.3.6/src/local_openai2anthropic/streaming/__init__.py +6 -0
- local_openai2anthropic-0.3.6/src/local_openai2anthropic/streaming/handler.py +444 -0
- local_openai2anthropic-0.3.6/src/local_openai2anthropic/tools/__init__.py +14 -0
- local_openai2anthropic-0.3.6/src/local_openai2anthropic/tools/handler.py +357 -0
- local_openai2anthropic-0.3.6/src/local_openai2anthropic/utils/__init__.py +18 -0
- local_openai2anthropic-0.3.6/src/local_openai2anthropic/utils/tokens.py +96 -0
- local_openai2anthropic-0.3.6/tests/coverage/coverage.json +1 -0
- local_openai2anthropic-0.3.6/tests/coverage/coverage_detailed.json +1 -0
- local_openai2anthropic-0.3.6/tests/coverage/coverage_report.json +1 -0
- local_openai2anthropic-0.3.6/tests/coverage/coverage_report_new.json +1 -0
- local_openai2anthropic-0.3.6/tests/coverage/coverage_summary.json +1 -0
- local_openai2anthropic-0.3.6/tests/test_config.py +364 -0
- local_openai2anthropic-0.3.6/tests/test_converter_edge_cases.py +335 -0
- local_openai2anthropic-0.3.6/tests/test_daemon.py +330 -0
- local_openai2anthropic-0.3.6/tests/test_daemon_advanced.py +283 -0
- local_openai2anthropic-0.3.6/tests/test_daemon_runner.py +221 -0
- local_openai2anthropic-0.3.6/tests/test_e2e_multimodel.py +438 -0
- local_openai2anthropic-0.3.6/tests/test_e2e_websearch.py +397 -0
- {local_openai2anthropic-0.2.4 → local_openai2anthropic-0.3.6}/tests/test_integration.py +0 -1
- local_openai2anthropic-0.3.6/tests/test_logging.py +270 -0
- local_openai2anthropic-0.3.6/tests/test_main.py +372 -0
- local_openai2anthropic-0.3.6/tests/test_openai_types.py +361 -0
- local_openai2anthropic-0.3.6/tests/test_protocol.py +372 -0
- {local_openai2anthropic-0.2.4 → local_openai2anthropic-0.3.6}/tests/test_router.py +7 -9
- local_openai2anthropic-0.3.6/tests/test_router_comprehensive.py +652 -0
- local_openai2anthropic-0.3.6/tests/test_router_edge_cases.py +321 -0
- local_openai2anthropic-0.3.6/tests/test_router_streaming.py +612 -0
- local_openai2anthropic-0.3.6/tests/test_server_tools.py +466 -0
- local_openai2anthropic-0.3.6/tests/test_tavily_client.py +258 -0
- local_openai2anthropic-0.2.4/src/local_openai2anthropic/config.py +0 -67
- local_openai2anthropic-0.2.4/src/local_openai2anthropic/router.py +0 -889
- {local_openai2anthropic-0.2.4 → local_openai2anthropic-0.3.6}/.github/workflows/publish.yml +0 -0
- {local_openai2anthropic-0.2.4 → local_openai2anthropic-0.3.6}/.gitignore +0 -0
- {local_openai2anthropic-0.2.4 → local_openai2anthropic-0.3.6}/LICENSE +0 -0
- {local_openai2anthropic-0.2.4 → local_openai2anthropic-0.3.6}/examples/basic_chat.py +0 -0
- {local_openai2anthropic-0.2.4 → local_openai2anthropic-0.3.6}/examples/streaming.py +0 -0
- {local_openai2anthropic-0.2.4 → local_openai2anthropic-0.3.6}/examples/thinking_mode.py +0 -0
- {local_openai2anthropic-0.2.4 → local_openai2anthropic-0.3.6}/examples/tool_calling.py +0 -0
- {local_openai2anthropic-0.2.4 → local_openai2anthropic-0.3.6}/examples/vision.py +0 -0
- {local_openai2anthropic-0.2.4 → local_openai2anthropic-0.3.6}/examples/web_search.py +0 -0
- {local_openai2anthropic-0.2.4 → local_openai2anthropic-0.3.6}/src/local_openai2anthropic/__main__.py +0 -0
- {local_openai2anthropic-0.2.4 → local_openai2anthropic-0.3.6}/src/local_openai2anthropic/daemon.py +0 -0
- {local_openai2anthropic-0.2.4 → local_openai2anthropic-0.3.6}/src/local_openai2anthropic/daemon_runner.py +0 -0
- {local_openai2anthropic-0.2.4 → local_openai2anthropic-0.3.6}/src/local_openai2anthropic/openai_types.py +0 -0
- {local_openai2anthropic-0.2.4 → local_openai2anthropic-0.3.6}/src/local_openai2anthropic/server_tools/__init__.py +0 -0
- {local_openai2anthropic-0.2.4 → local_openai2anthropic-0.3.6}/src/local_openai2anthropic/server_tools/base.py +0 -0
- {local_openai2anthropic-0.2.4 → local_openai2anthropic-0.3.6}/src/local_openai2anthropic/server_tools/web_search.py +0 -0
- {local_openai2anthropic-0.2.4 → local_openai2anthropic-0.3.6}/src/local_openai2anthropic/tavily_client.py +0 -0
- {local_openai2anthropic-0.2.4 → local_openai2anthropic-0.3.6}/tests/__init__.py +0 -0
- {local_openai2anthropic-0.2.4 → local_openai2anthropic-0.3.6}/tests/test_converter.py +0 -0
- {local_openai2anthropic-0.2.4 → local_openai2anthropic-0.3.6}/tests/test_upstream.sh +0 -0
- {local_openai2anthropic-0.2.4 → local_openai2anthropic-0.3.6}/uv.lock +0 -0
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
# Claude 开发指南
|
|
2
|
+
|
|
3
|
+
## Configuration File
|
|
4
|
+
|
|
5
|
+
### Config File Location
|
|
6
|
+
|
|
7
|
+
- **Linux/macOS**: `~/.oa2a/config.toml`
|
|
8
|
+
- **Windows**: `%USERPROFILE%\.oa2a\config.toml`
|
|
9
|
+
|
|
10
|
+
### First Run
|
|
11
|
+
|
|
12
|
+
A default config file will be created automatically on first startup. Edit this file to add your API keys.
|
|
13
|
+
|
|
14
|
+
### Configuration Example
|
|
15
|
+
|
|
16
|
+
```toml
|
|
17
|
+
# OA2A Configuration File
|
|
18
|
+
# Place this file at ~/.oa2a/config.toml
|
|
19
|
+
|
|
20
|
+
# OpenAI API Configuration
|
|
21
|
+
openai_api_key = "your-openai-api-key"
|
|
22
|
+
openai_base_url = "https://api.openai.com/v1"
|
|
23
|
+
openai_org_id = ""
|
|
24
|
+
openai_project_id = ""
|
|
25
|
+
|
|
26
|
+
# Server Configuration
|
|
27
|
+
host = "0.0.0.0"
|
|
28
|
+
port = 8080
|
|
29
|
+
request_timeout = 300.0
|
|
30
|
+
|
|
31
|
+
# API Key for authenticating requests to this server (optional)
|
|
32
|
+
api_key = ""
|
|
33
|
+
|
|
34
|
+
# CORS settings
|
|
35
|
+
cors_origins = ["*"]
|
|
36
|
+
cors_credentials = true
|
|
37
|
+
cors_methods = ["*"]
|
|
38
|
+
cors_headers = ["*"]
|
|
39
|
+
|
|
40
|
+
# Logging
|
|
41
|
+
log_level = "DEBUG"
|
|
42
|
+
log_dir = "" # Empty uses platform-specific default
|
|
43
|
+
|
|
44
|
+
# Tavily Web Search Configuration
|
|
45
|
+
tavily_api_key = ""
|
|
46
|
+
tavily_timeout = 30.0
|
|
47
|
+
tavily_max_results = 5
|
|
48
|
+
websearch_max_uses = 5
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## 版本号更新清单
|
|
52
|
+
|
|
53
|
+
当修改项目版本号时,需要同步更新以下所有位置:
|
|
54
|
+
|
|
55
|
+
### 1. pyproject.toml
|
|
56
|
+
- **位置**: 第3行
|
|
57
|
+
- **格式**: `version = "x.y.z"`
|
|
58
|
+
- **示例**: `version = "0.3.5"`
|
|
59
|
+
|
|
60
|
+
### 2. src/local_openai2anthropic/__init__.py
|
|
61
|
+
- **位置**: 第6行
|
|
62
|
+
- **格式**: `__version__ = "x.y.z"`
|
|
63
|
+
- **示例**: `__version__ = "0.3.5"`
|
|
64
|
+
|
|
65
|
+
### 3. src/local_openai2anthropic/main.py (FastAPI 应用版本)
|
|
66
|
+
- **位置**: 第104行
|
|
67
|
+
- **格式**: `version="x.y.z"`
|
|
68
|
+
- **示例**: `version="0.3.5"`
|
|
69
|
+
|
|
70
|
+
### 4. src/local_openai2anthropic/main.py (命令行 --version)
|
|
71
|
+
- **位置**: 第254行
|
|
72
|
+
- **格式**: `version="%(prog)s x.y.z"`
|
|
73
|
+
- **示例**: `version="%(prog)s 0.3.5"`
|
|
74
|
+
|
|
75
|
+
### 5. tests/test_main.py (测试断言)
|
|
76
|
+
- **位置**: 第26行
|
|
77
|
+
- **格式**: `assert app.version == "x.y.z"`
|
|
78
|
+
- **示例**: `assert app.version == "0.3.5"`
|
|
79
|
+
|
|
80
|
+
### 6. Git Tag
|
|
81
|
+
- **格式**: `vx.y.z`
|
|
82
|
+
- **示例**: `v0.3.5`
|
|
83
|
+
- **命令**:
|
|
84
|
+
```bash
|
|
85
|
+
git tag v0.3.5
|
|
86
|
+
git push origin v0.3.5
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## 版本号格式
|
|
90
|
+
|
|
91
|
+
使用语义化版本控制 (Semantic Versioning):
|
|
92
|
+
- **MAJOR**: 不兼容的 API 修改
|
|
93
|
+
- **MINOR**: 向下兼容的功能新增
|
|
94
|
+
- **PATCH**: 向下兼容的问题修复
|
|
95
|
+
|
|
96
|
+
## 发布流程
|
|
97
|
+
|
|
98
|
+
1. 更新上述所有文件中的版本号
|
|
99
|
+
2. 运行测试确保通过: `pytest`
|
|
100
|
+
3. 提交更改: `git commit -m "chore(release): bump version to x.y.z"`
|
|
101
|
+
4. 创建标签: `git tag vx.y.z`
|
|
102
|
+
5. 推送代码和标签: `git push && git push origin vx.y.z`
|
|
103
|
+
6. GitHub Actions 将自动发布到 PyPI
|
|
104
|
+
|
|
105
|
+
## 代码提交规范
|
|
106
|
+
|
|
107
|
+
### 测试覆盖率要求
|
|
108
|
+
|
|
109
|
+
在提交任何新代码之前,必须满足以下测试要求:
|
|
110
|
+
|
|
111
|
+
#### 1. 新代码单元测试
|
|
112
|
+
- **必须**为所有未提交的新代码编写单元测试
|
|
113
|
+
- 新代码的测试覆盖率**必须 > 90%**
|
|
114
|
+
- 测试文件命名规范: `test_<module_name>.py`
|
|
115
|
+
- 测试函数命名规范: `test_<function_name>_<scenario>`
|
|
116
|
+
|
|
117
|
+
#### 2. 总体覆盖率检查
|
|
118
|
+
- 运行 `/everything-claude-code:test-coverage` 检查总体覆盖率
|
|
119
|
+
- **总体覆盖率必须 ≥ 80%**
|
|
120
|
+
- 如果总体覆盖率低于 80%,需要补充测试或优化现有代码
|
|
121
|
+
|
|
122
|
+
#### 3. 代码审查
|
|
123
|
+
|
|
124
|
+
在提交代码前,必须进行代码审查:
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
# 运行代码审查(检查安全漏洞、代码质量、最佳实践)
|
|
128
|
+
/code-review:code-review
|
|
129
|
+
|
|
130
|
+
# 根据审查结果修复问题
|
|
131
|
+
# - CRITICAL/HIGH 级别问题必须修复
|
|
132
|
+
# - MEDIUM/LOW 级别问题根据情况处理
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
代码审查将检查:
|
|
136
|
+
- **安全问题**: 硬编码凭证、SQL注入、XSS、路径遍历等
|
|
137
|
+
- **代码质量**: 函数长度、嵌套深度、错误处理、console.log等
|
|
138
|
+
- **最佳实践**: 不可变模式、emoji使用、测试覆盖、可访问性等
|
|
139
|
+
|
|
140
|
+
#### 4. 提交流程
|
|
141
|
+
```bash
|
|
142
|
+
# 1. 编写新代码
|
|
143
|
+
# 2. 编写对应的单元测试
|
|
144
|
+
# 3. 运行测试并检查覆盖率
|
|
145
|
+
pytest --cov=src/local_openai2anthropic --cov-report=term-missing
|
|
146
|
+
|
|
147
|
+
# 4. 运行 Claude Code 覆盖率检查
|
|
148
|
+
/everything-claude-code:test-coverage
|
|
149
|
+
|
|
150
|
+
# 5. 运行代码审查
|
|
151
|
+
/code-review:code-review
|
|
152
|
+
|
|
153
|
+
# 6. 确认新代码覆盖率 > 90% 且总体覆盖率 ≥ 80%,且无 CRITICAL/HIGH 问题
|
|
154
|
+
# 7. 提交代码
|
|
155
|
+
git add .
|
|
156
|
+
git commit -m "feat: your commit message"
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
#### 4. 测试质量标准
|
|
160
|
+
- 测试用例应覆盖正常路径、边界条件和异常情况
|
|
161
|
+
- 使用 `pytest` 作为测试框架
|
|
162
|
+
- 异步代码使用 `pytest-asyncio`
|
|
163
|
+
- 适当的测试夹具 (fixtures) 和参数化测试
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
# Dead Code Analysis Report
|
|
2
|
+
|
|
3
|
+
**Project:** local-openai2anthropic
|
|
4
|
+
**Analysis Date:** 2026-02-03
|
|
5
|
+
**Tools Used:** vulture, pylint, ruff
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Executive Summary
|
|
10
|
+
|
|
11
|
+
This report identifies potentially unused code in the codebase. The analysis found **47 issues** across the source code, categorized by severity level. No code has been deleted - this is for review purposes only.
|
|
12
|
+
|
|
13
|
+
### Summary by Severity
|
|
14
|
+
|
|
15
|
+
| Severity | Count | Description |
|
|
16
|
+
|----------|-------|-------------|
|
|
17
|
+
| SAFE | 23 | Unused imports, variables, and f-strings - safe to remove |
|
|
18
|
+
| CAUTION | 15 | Unused functions/methods - verify before removal |
|
|
19
|
+
| DANGER | 9 | Model fields and properties - may be used externally |
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Detailed Findings
|
|
24
|
+
|
|
25
|
+
### SEVERITY: SAFE (High Confidence for Removal)
|
|
26
|
+
|
|
27
|
+
These items are safe to remove with minimal risk.
|
|
28
|
+
|
|
29
|
+
#### 1. Unused Imports
|
|
30
|
+
|
|
31
|
+
| File | Line | Item | Tool | Notes |
|
|
32
|
+
|------|------|------|------|-------|
|
|
33
|
+
| `src/local_openai2anthropic/converter.py` | 20 | `ChatCompletionChunk` from `openai.types.chat` | vulture (90%), ruff, pylint | Imported but never referenced |
|
|
34
|
+
| `src/local_openai2anthropic/converter.py` | 26 | `ServerToolRegistry` from `local_openai2anthropic.server_tools` | vulture (90%), ruff, pylint | Imported but never referenced |
|
|
35
|
+
| `src/local_openai2anthropic/protocol.py` | 9 | `Field` from `pydantic` | vulture (90%), ruff, pylint | Imported but never used in file |
|
|
36
|
+
| `tests/test_daemon_runner.py` | 8 | `datetime` | vulture (90%) | Unused import in test file |
|
|
37
|
+
| `tests/test_router_comprehensive.py` | 7 | `Mock` from `unittest.mock` | vulture (90%) | Unused import |
|
|
38
|
+
| `tests/test_router_comprehensive.py` | 9 | `Request` from `fastapi` | vulture (90%) | Unused import |
|
|
39
|
+
| `tests/test_router_comprehensive.py` | 10 | `StreamingResponse` from `fastapi.responses` | vulture (90%) | Unused import |
|
|
40
|
+
| `tests/test_router_comprehensive.py` | 12 | `_handle_with_server_tools` from `local_openai2anthropic.router` | vulture (90%) | Unused import |
|
|
41
|
+
| `tests/test_router_streaming.py` | 7 | `Mock` from `unittest.mock` | vulture (90%) | Unused import |
|
|
42
|
+
| `tests/test_router_streaming.py` | 9 | `StreamingResponse` from `fastapi.responses` | vulture (90%) | Unused import |
|
|
43
|
+
| `tests/test_router_streaming.py` | 11 | `_handle_with_server_tools` from `local_openai2anthropic.router` | vulture (90%) | Unused import |
|
|
44
|
+
|
|
45
|
+
#### 2. Unused Local Variables
|
|
46
|
+
|
|
47
|
+
| File | Line | Variable | Tool | Notes |
|
|
48
|
+
|------|------|----------|------|-------|
|
|
49
|
+
| `src/local_openai2anthropic/converter.py` | 297 | `is_error` | ruff (F841) | Assigned but never used in tool_result handling |
|
|
50
|
+
| `src/local_openai2anthropic/daemon.py` | 274 | `e` (exception) | ruff (F841) | Exception variable not used in except block |
|
|
51
|
+
| `src/local_openai2anthropic/main.py` | 240 | `status_parser` | vulture (60%), ruff | Assigned but status command parser not used |
|
|
52
|
+
| `src/local_openai2anthropic/router.py` | 483 | `openai_stop_reason` | vulture (60%), ruff | Variable assigned but never used |
|
|
53
|
+
| `src/local_openai2anthropic/router.py` | 1182 | `model` | ruff (F841) | Extracted from request but never used |
|
|
54
|
+
|
|
55
|
+
#### 3. F-strings Without Placeholders
|
|
56
|
+
|
|
57
|
+
| File | Line | Content | Tool | Notes |
|
|
58
|
+
|------|------|---------|------|-------|
|
|
59
|
+
| `src/local_openai2anthropic/daemon.py` | 146 | `"Use 'oa2a logs' to view output"` | ruff (F541) | No placeholders in f-string |
|
|
60
|
+
| `src/local_openai2anthropic/daemon.py` | 152 | `"Another process may be listening on this port"` | ruff (F541) | No placeholders in f-string |
|
|
61
|
+
| `src/local_openai2anthropic/daemon.py` | 263 | `"Server did not stop gracefully, use -f to force kill"` | ruff (F541) | No placeholders in f-string |
|
|
62
|
+
| `src/local_openai2anthropic/daemon_runner.py` | 84 | `"Configuration loaded:"` | ruff (F541) | No placeholders in f-string |
|
|
63
|
+
|
|
64
|
+
#### 4. Unused Arguments
|
|
65
|
+
|
|
66
|
+
| File | Line | Function/Method | Argument | Tool | Notes |
|
|
67
|
+
|------|------|-----------------|----------|------|-------|
|
|
68
|
+
| `src/local_openai2anthropic/daemon_runner.py` | 45 | signal handler | `frame` | vulture (100%), pylint | Signal handler frame argument not used |
|
|
69
|
+
| `src/local_openai2anthropic/main.py` | 95 | `http_exception_handler` | `request` | pylint | FastAPI exception handler receives request but doesn't use it |
|
|
70
|
+
| `src/local_openai2anthropic/main.py` | 116 | `general_exception_handler` | `request` | pylint | FastAPI exception handler receives request but doesn't use it |
|
|
71
|
+
| `src/local_openai2anthropic/router.py` | 860 | (inline function) | `handler` | pylint | Exception handler argument not used |
|
|
72
|
+
| `src/local_openai2anthropic/router.py` | 1138 | `count_tokens` | `settings` | pylint | Settings dependency injected but not used |
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
### SEVERITY: CAUTION (Verify Before Removal)
|
|
77
|
+
|
|
78
|
+
These items appear unused but may be called dynamically or through external APIs.
|
|
79
|
+
|
|
80
|
+
#### 1. Unused Functions
|
|
81
|
+
|
|
82
|
+
| File | Line | Function | Tool | Risk Assessment |
|
|
83
|
+
|------|------|----------|------|-----------------|
|
|
84
|
+
| `src/local_openai2anthropic/converter.py` | 348 | `_build_usage_with_cache` | vulture (60%) | **LOW RISK** - Private function, appears truly unused. Could be removed or used for future cache token support. |
|
|
85
|
+
| `src/local_openai2anthropic/main.py` | 55 | `auth_middleware` | vulture (60%) | **MEDIUM RISK** - Middleware that may be registered dynamically. Verify if used in app setup. |
|
|
86
|
+
| `src/local_openai2anthropic/main.py` | 94 | `http_exception_handler` | vulture (60%) | **LOW RISK** - Exception handler, may be registered via decorator. Check FastAPI app setup. |
|
|
87
|
+
| `src/local_openai2anthropic/main.py` | 115 | `general_exception_handler` | vulture (60%) | **LOW RISK** - Exception handler, may be registered via decorator. Check FastAPI app setup. |
|
|
88
|
+
| `src/local_openai2anthropic/router.py` | 898 | `create_message` | vulture (60%) | **MEDIUM RISK** - API endpoint handler. May be registered as route. Verify router setup. |
|
|
89
|
+
| `src/local_openai2anthropic/router.py` | 1106 | `list_models` | vulture (60%) | **MEDIUM RISK** - API endpoint handler. May be registered as route. Verify router setup. |
|
|
90
|
+
| `src/local_openai2anthropic/router.py` | 1135 | `count_tokens` | vulture (60%) | **MEDIUM RISK** - API endpoint handler. May be registered as route. Verify router setup. |
|
|
91
|
+
| `src/local_openai2anthropic/router.py` | 1241 | `health_check` | vulture (60%) | **MEDIUM RISK** - API endpoint handler. May be registered as route. Verify router setup. |
|
|
92
|
+
|
|
93
|
+
#### 2. Unused Methods
|
|
94
|
+
|
|
95
|
+
| File | Line | Class | Method | Tool | Risk Assessment |
|
|
96
|
+
|------|------|-------|--------|------|-----------------|
|
|
97
|
+
| `src/local_openai2anthropic/server_tools/base.py` | 167 | `ServerToolRegistry` | `all_tools` | vulture (60%) | **LOW RISK** - Method that returns all registered tools. May be useful for debugging/admin. |
|
|
98
|
+
|
|
99
|
+
#### 3. Unused Test Functions/Fixtures
|
|
100
|
+
|
|
101
|
+
| File | Line | Function | Tool | Notes |
|
|
102
|
+
|------|------|----------|------|-------|
|
|
103
|
+
| `tests/test_router_comprehensive.py` | 31 | `async_iter` | vulture (60%) | Helper function, may be used in tests |
|
|
104
|
+
| `tests/test_router_streaming.py` | 25 | `async_iter` | vulture (60%) | Helper function, may be used in tests |
|
|
105
|
+
| `tests/test_router_streaming.py` | 614 | `async_iter` | vulture (60%) | Duplicate helper function |
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
### SEVERITY: DANGER (Do Not Remove Without Careful Review)
|
|
110
|
+
|
|
111
|
+
These items are model fields, properties, or public API components that may be used externally even if not referenced internally.
|
|
112
|
+
|
|
113
|
+
#### 1. Model Configuration and Properties
|
|
114
|
+
|
|
115
|
+
| File | Line | Item | Type | Tool | Risk Assessment |
|
|
116
|
+
|------|------|------|------|------|-----------------|
|
|
117
|
+
| `src/local_openai2anthropic/config.py` | 15 | `model_config` | Class variable | vulture (60%) | **HIGH RISK** - Pydantic Settings configuration. Required by pydantic-settings. |
|
|
118
|
+
| `src/local_openai2anthropic/config.py` | 52 | `openai_auth_headers` | Property | vulture (60%) | **HIGH RISK** - Public property that may be used by external code. Verify usage before removal. |
|
|
119
|
+
|
|
120
|
+
#### 2. TypedDict Fields (May be Required for API Compatibility)
|
|
121
|
+
|
|
122
|
+
| File | Line | Field | Parent Class | Tool | Risk Assessment |
|
|
123
|
+
|------|------|-------|--------------|------|-----------------|
|
|
124
|
+
| `src/local_openai2anthropic/openai_types.py` | 20 | `description` | `ChatCompletionToolFunction` | vulture (60%) | **HIGH RISK** - TypedDict field for OpenAI API compatibility. |
|
|
125
|
+
| `src/local_openai2anthropic/openai_types.py` | 21 | `parameters` | `ChatCompletionToolFunction` | vulture (60%) | **HIGH RISK** - TypedDict field for OpenAI API compatibility. |
|
|
126
|
+
| `src/local_openai2anthropic/openai_types.py` | 41 | `stop` | `CompletionCreateParams` | vulture (60%) | **HIGH RISK** - TypedDict field for OpenAI API compatibility. |
|
|
127
|
+
| `src/local_openai2anthropic/openai_types.py` | 44 | `stream_options` | `CompletionCreateParams` | vulture (60%) | **HIGH RISK** - TypedDict field for OpenAI API compatibility. |
|
|
128
|
+
| `src/local_openai2anthropic/openai_types.py` | 46 | `chat_template_kwargs` | `CompletionCreateParams` | vulture (60%) | **HIGH RISK** - TypedDict field for vLLM/SGLang compatibility. |
|
|
129
|
+
|
|
130
|
+
#### 3. Pydantic Model Fields (Default Values)
|
|
131
|
+
|
|
132
|
+
| File | Line | Field | Parent Class | Tool | Risk Assessment |
|
|
133
|
+
|------|------|-------|--------------|------|-----------------|
|
|
134
|
+
| `src/local_openai2anthropic/openai_types.py` | 80 | `index` | `Choice` | vulture (60%) | **MEDIUM RISK** - Model field with default value. May be used in serialization. |
|
|
135
|
+
| `src/local_openai2anthropic/openai_types.py` | 95 | `index` | `ChatCompletionDeltaToolCall` | vulture (60%) | **MEDIUM RISK** - Model field with default value. |
|
|
136
|
+
| `src/local_openai2anthropic/openai_types.py` | 114 | `index` | `StreamingChoice` | vulture (60%) | **MEDIUM RISK** - Model field with default value. |
|
|
137
|
+
| `src/local_openai2anthropic/openai_types.py` | 135 | `created` | `ChatCompletion` | vulture (60%) | **MEDIUM RISK** - Model field. Required for OpenAI API compatibility. |
|
|
138
|
+
| `src/local_openai2anthropic/openai_types.py` | 146 | `created` | `ChatCompletionChunk` | vulture (60%) | **MEDIUM RISK** - Model field. Required for OpenAI API compatibility. |
|
|
139
|
+
|
|
140
|
+
#### 4. Unused Classes
|
|
141
|
+
|
|
142
|
+
| File | Line | Class | Tool | Risk Assessment |
|
|
143
|
+
|------|------|-------|------|-----------------|
|
|
144
|
+
| `src/local_openai2anthropic/openai_types.py` | 141 | `ChatCompletionChunk` | vulture (60%) | **HIGH RISK** - Public Pydantic model. May be imported by external code. |
|
|
145
|
+
|
|
146
|
+
#### 5. Protocol Model Fields (Web Search Tool Types)
|
|
147
|
+
|
|
148
|
+
| File | Line | Field | Parent Class | Tool | Risk Assessment |
|
|
149
|
+
|------|------|-------|--------------|------|-----------------|
|
|
150
|
+
| `src/local_openai2anthropic/protocol.py` | 77 | `city` | `ApproximateLocation` | vulture (60%) | **MEDIUM RISK** - Optional field for web search location. |
|
|
151
|
+
| `src/local_openai2anthropic/protocol.py` | 78 | `region` | `ApproximateLocation` | vulture (60%) | **MEDIUM RISK** - Optional field for web search location. |
|
|
152
|
+
| `src/local_openai2anthropic/protocol.py` | 79 | `country` | `ApproximateLocation` | vulture (60%) | **MEDIUM RISK** - Optional field with default. |
|
|
153
|
+
| `src/local_openai2anthropic/protocol.py` | 80 | `timezone` | `ApproximateLocation` | vulture (60%) | **MEDIUM RISK** - Optional field for web search location. |
|
|
154
|
+
| `src/local_openai2anthropic/protocol.py` | 89 | `allowed_domains` | `WebSearchToolDefinition` | vulture (60%) | **MEDIUM RISK** - Optional field for domain filtering. |
|
|
155
|
+
| `src/local_openai2anthropic/protocol.py` | 90 | `blocked_domains` | `WebSearchToolDefinition` | vulture (60%) | **MEDIUM RISK** - Optional field for domain filtering. |
|
|
156
|
+
| `src/local_openai2anthropic/protocol.py` | 91 | `user_location` | `WebSearchToolDefinition` | vulture (60%) | **MEDIUM RISK** - Optional field for location context. |
|
|
157
|
+
| `src/local_openai2anthropic/protocol.py` | 148 | `web_search_requests` | `ServerToolUseUsage` | vulture (60%) | **MEDIUM RISK** - Usage tracking field. |
|
|
158
|
+
| `src/local_openai2anthropic/protocol.py` | 158 | `server_tool_use` | `UsageWithServerToolUse` | vulture (60%) | **MEDIUM RISK** - Usage tracking field. |
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## Test File Analysis
|
|
163
|
+
|
|
164
|
+
The test files contain many mock-related unused attributes. These are typically false positives because:
|
|
165
|
+
|
|
166
|
+
1. **Mock return_value assignments** - Used to configure mock behavior even if not directly referenced
|
|
167
|
+
2. **Mock side_effect assignments** - Configure mock behavior
|
|
168
|
+
3. **Test fixtures** - May be used indirectly by pytest
|
|
169
|
+
|
|
170
|
+
### Test File Recommendations
|
|
171
|
+
|
|
172
|
+
| File | Issue Count | Recommendation |
|
|
173
|
+
|------|-------------|----------------|
|
|
174
|
+
| `test_daemon.py` | 4 | Review mock configurations - likely false positives |
|
|
175
|
+
| `test_daemon_advanced.py` | 5 | Review mock configurations - likely false positives |
|
|
176
|
+
| `test_daemon_runner.py` | 8 | Remove unused `datetime` import; review mocks |
|
|
177
|
+
| `test_main.py` | 14 | Review mock configurations - likely false positives |
|
|
178
|
+
| `test_router_comprehensive.py` | 7 | Remove unused imports; review helper functions |
|
|
179
|
+
| `test_router_edge_cases.py` | 2 | Review mock configurations |
|
|
180
|
+
| `test_router_streaming.py` | 6 | Remove unused imports; review helper functions |
|
|
181
|
+
| `test_server_tools.py` | 13 | Review test fixtures - `cls` in `@classmethod` is required |
|
|
182
|
+
| `test_tavily_client.py` | 14 | Review mock configurations - likely false positives |
|
|
183
|
+
|
|
184
|
+
**Note:** The `cls` variable in `@classmethod` decorators is a false positive - it's required by Python even if not explicitly used.
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
## Recommendations
|
|
189
|
+
|
|
190
|
+
### Immediate Actions (SAFE)
|
|
191
|
+
|
|
192
|
+
1. **Remove unused imports:**
|
|
193
|
+
```python
|
|
194
|
+
# In converter.py - Remove lines 18-22 and 26
|
|
195
|
+
from openai.types.chat import ChatCompletionChunk # REMOVE
|
|
196
|
+
from local_openai2anthropic.server_tools import ServerToolRegistry # REMOVE
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
2. **Remove unused variable assignments:**
|
|
200
|
+
```python
|
|
201
|
+
# In converter.py line 297
|
|
202
|
+
is_error = getattr(block, "is_error", False) # REMOVE or use
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
3. **Fix f-strings without placeholders:**
|
|
206
|
+
```python
|
|
207
|
+
# Change f"..." to "..." where no placeholders exist
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
4. **Clean up test file imports** as listed above
|
|
211
|
+
|
|
212
|
+
### Cautionary Actions (CAUTION)
|
|
213
|
+
|
|
214
|
+
1. **Verify API endpoint functions** in `router.py`:
|
|
215
|
+
- Check if `create_message`, `list_models`, `count_tokens`, `health_check` are registered as routes
|
|
216
|
+
- If not registered, they can be removed
|
|
217
|
+
|
|
218
|
+
2. **Review exception handlers** in `main.py`:
|
|
219
|
+
- Verify if they're registered with FastAPI's exception handlers
|
|
220
|
+
- If not registered, they can be removed
|
|
221
|
+
|
|
222
|
+
### Do Not Remove (DANGER)
|
|
223
|
+
|
|
224
|
+
1. **Pydantic model fields** - Required for API compatibility
|
|
225
|
+
2. **TypedDict fields** - Define API contract
|
|
226
|
+
3. **Config properties** - May be used externally
|
|
227
|
+
4. **Web search tool type fields** - Part of feature implementation
|
|
228
|
+
|
|
229
|
+
---
|
|
230
|
+
|
|
231
|
+
## Verification Commands
|
|
232
|
+
|
|
233
|
+
Before removing any code, verify with these commands:
|
|
234
|
+
|
|
235
|
+
```bash
|
|
236
|
+
# Check if a function is referenced anywhere
|
|
237
|
+
grep -r "function_name" --include="*.py" .
|
|
238
|
+
|
|
239
|
+
# Check for dynamic imports
|
|
240
|
+
grep -r "importlib\|__import__\|import_module" --include="*.py" .
|
|
241
|
+
|
|
242
|
+
# Check for string-based references (common in web frameworks)
|
|
243
|
+
grep -r "\"create_message\"\|'create_message'" --include="*.py" .
|
|
244
|
+
|
|
245
|
+
# Run tests after changes
|
|
246
|
+
pytest tests/ -v
|
|
247
|
+
|
|
248
|
+
# Check for import errors
|
|
249
|
+
python -c "from local_openai2anthropic import *"
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
---
|
|
253
|
+
|
|
254
|
+
## Appendix: Tool Configuration
|
|
255
|
+
|
|
256
|
+
### Vulture
|
|
257
|
+
```bash
|
|
258
|
+
vulture src/ tests/ --min-confidence 60
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### Pylint
|
|
262
|
+
```bash
|
|
263
|
+
pylint src/ --disable=all --enable=W0611,W0613,W0614,W1300,W1301,W1302,W1303,W1304,W1305,W1306,W1307,W1401,W1404,W1405,W1505
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
### Ruff
|
|
267
|
+
```bash
|
|
268
|
+
ruff check src/ tests/ --select F401,F541,F841
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
---
|
|
272
|
+
|
|
273
|
+
## Changelog
|
|
274
|
+
|
|
275
|
+
| Date | Version | Changes |
|
|
276
|
+
|------|---------|---------|
|
|
277
|
+
| 2026-02-03 | 1.0 | Initial analysis report |
|
|
278
|
+
|
|
279
|
+
---
|
|
280
|
+
|
|
281
|
+
**Report Generated By:** Claude Code Dead Code Analysis Agent
|
|
282
|
+
**Disclaimer:** This report is generated by automated tools and requires human review before any code deletion. Always verify findings with grep searches and run the full test suite before removing code.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: local-openai2anthropic
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.6
|
|
4
4
|
Summary: A lightweight proxy server that converts Anthropic Messages API to OpenAI API
|
|
5
5
|
Project-URL: Homepage, https://github.com/dongfangzan/local-openai2anthropic
|
|
6
6
|
Project-URL: Repository, https://github.com/dongfangzan/local-openai2anthropic
|
|
@@ -24,6 +24,7 @@ Requires-Dist: httpx>=0.25.0
|
|
|
24
24
|
Requires-Dist: openai>=1.30.0
|
|
25
25
|
Requires-Dist: pydantic-settings>=2.0.0
|
|
26
26
|
Requires-Dist: pydantic>=2.0.0
|
|
27
|
+
Requires-Dist: tomli>=2.0.0; python_version < '3.11'
|
|
27
28
|
Requires-Dist: uvicorn[standard]>=0.23.0
|
|
28
29
|
Provides-Extra: dev
|
|
29
30
|
Requires-Dist: black>=23.0.0; extra == 'dev'
|
|
@@ -55,6 +56,7 @@ This proxy translates Claude SDK calls to OpenAI API format in real-time, enabli
|
|
|
55
56
|
- **Offline development** without cloud API costs
|
|
56
57
|
- **Privacy-first AI** - data never leaves your machine
|
|
57
58
|
- **Seamless model switching** between cloud and local
|
|
59
|
+
- **Web Search tool** - built-in Tavily web search for local models
|
|
58
60
|
|
|
59
61
|
---
|
|
60
62
|
|
|
@@ -79,7 +81,11 @@ Other OpenAI-compatible backends may work but are not fully tested.
|
|
|
79
81
|
pip install local-openai2anthropic
|
|
80
82
|
```
|
|
81
83
|
|
|
82
|
-
### 2.
|
|
84
|
+
### 2. Configure Your LLM Backend (Optional)
|
|
85
|
+
|
|
86
|
+
**Option A: Start a local LLM server**
|
|
87
|
+
|
|
88
|
+
If you don't have an LLM server running, you can start one locally:
|
|
83
89
|
|
|
84
90
|
Example with vLLM:
|
|
85
91
|
```bash
|
|
@@ -93,6 +99,16 @@ sglang launch --model-path meta-llama/Llama-2-7b-chat-hf --port 8000
|
|
|
93
99
|
# SGLang starts at http://localhost:8000/v1
|
|
94
100
|
```
|
|
95
101
|
|
|
102
|
+
**Option B: Use an existing OpenAI-compatible API**
|
|
103
|
+
|
|
104
|
+
If you already have a deployed OpenAI-compatible API (local or remote), you can use it directly. Just note the base URL for the next step.
|
|
105
|
+
|
|
106
|
+
Examples:
|
|
107
|
+
- Local vLLM/SGLang: `http://localhost:8000/v1`
|
|
108
|
+
- Remote API: `https://api.example.com/v1`
|
|
109
|
+
|
|
110
|
+
> **Note:** If you're using [Ollama](https://ollama.com), it natively supports the Anthropic API format, so you don't need this proxy. Just point your Claude SDK directly to `http://localhost:11434/v1`.
|
|
111
|
+
|
|
96
112
|
### 3. Start the Proxy
|
|
97
113
|
|
|
98
114
|
**Option A: Run in background (recommended)**
|
|
@@ -155,22 +171,31 @@ You can configure [Claude Code](https://github.com/anthropics/claude-code) to us
|
|
|
155
171
|
|
|
156
172
|
### Configuration Steps
|
|
157
173
|
|
|
158
|
-
1. **
|
|
159
|
-
|
|
160
|
-
```
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
174
|
+
1. **Edit Claude Code config file** at `~/.claude/settings.json`:
|
|
175
|
+
|
|
176
|
+
```json
|
|
177
|
+
{
|
|
178
|
+
"env": {
|
|
179
|
+
"ANTHROPIC_BASE_URL": "http://localhost:8080",
|
|
180
|
+
"ANTHROPIC_API_KEY": "dummy-key",
|
|
181
|
+
"ANTHROPIC_MODEL": "meta-llama/Llama-2-7b-chat-hf",
|
|
182
|
+
"ANTHROPIC_DEFAULT_SONNET_MODEL": "meta-llama/Llama-2-7b-chat-hf",
|
|
183
|
+
"ANTHROPIC_DEFAULT_OPUS_MODEL": "meta-llama/Llama-2-7b-chat-hf",
|
|
184
|
+
"ANTHROPIC_DEFAULT_HAIKU_MODEL": "meta-llama/Llama-2-7b-chat-hf",
|
|
185
|
+
"ANTHROPIC_REASONING_MODEL": "meta-llama/Llama-2-7b-chat-hf"
|
|
186
|
+
}
|
|
187
|
+
}
|
|
171
188
|
```
|
|
172
189
|
|
|
173
|
-
|
|
190
|
+
| Variable | Description |
|
|
191
|
+
|----------|-------------|
|
|
192
|
+
| `ANTHROPIC_MODEL` | General model setting |
|
|
193
|
+
| `ANTHROPIC_DEFAULT_SONNET_MODEL` | Default model for Sonnet mode (Claude Code default) |
|
|
194
|
+
| `ANTHROPIC_DEFAULT_OPUS_MODEL` | Default model for Opus mode |
|
|
195
|
+
| `ANTHROPIC_DEFAULT_HAIKU_MODEL` | Default model for Haiku mode |
|
|
196
|
+
| `ANTHROPIC_REASONING_MODEL` | Default model for reasoning tasks |
|
|
197
|
+
|
|
198
|
+
2. **Or set environment variables** before running Claude Code:
|
|
174
199
|
|
|
175
200
|
```bash
|
|
176
201
|
export ANTHROPIC_BASE_URL=http://localhost:8080
|
|
@@ -179,38 +204,36 @@ export ANTHROPIC_API_KEY=dummy-key
|
|
|
179
204
|
claude
|
|
180
205
|
```
|
|
181
206
|
|
|
182
|
-
3. **Or use the `--api-key` and `--base-url` flags**:
|
|
183
|
-
|
|
184
|
-
```bash
|
|
185
|
-
claude --api-key dummy-key --base-url http://localhost:8080
|
|
186
|
-
```
|
|
187
|
-
|
|
188
207
|
### Complete Workflow Example
|
|
189
208
|
|
|
209
|
+
Make sure `~/.claude/settings.json` is configured as described above.
|
|
210
|
+
|
|
190
211
|
Terminal 1 - Start your local LLM:
|
|
191
212
|
```bash
|
|
192
213
|
vllm serve meta-llama/Llama-2-7b-chat-hf
|
|
193
214
|
```
|
|
194
215
|
|
|
195
|
-
Terminal 2 - Start the proxy:
|
|
216
|
+
Terminal 2 - Start the proxy (background mode):
|
|
196
217
|
```bash
|
|
197
218
|
export OA2A_OPENAI_BASE_URL=http://localhost:8000/v1
|
|
198
219
|
export OA2A_OPENAI_API_KEY=dummy
|
|
199
220
|
export OA2A_TAVILY_API_KEY="tvly-your-tavily-api-key" # Optional: enable web search
|
|
200
221
|
|
|
201
|
-
oa2a
|
|
222
|
+
oa2a start
|
|
202
223
|
```
|
|
203
224
|
|
|
204
|
-
Terminal 3 - Launch Claude Code
|
|
225
|
+
Terminal 3 - Launch Claude Code:
|
|
205
226
|
```bash
|
|
206
|
-
export ANTHROPIC_BASE_URL=http://localhost:8080
|
|
207
|
-
export ANTHROPIC_API_KEY=dummy-key
|
|
208
|
-
|
|
209
227
|
claude
|
|
210
228
|
```
|
|
211
229
|
|
|
212
230
|
Now Claude Code will use your local LLM instead of the cloud API.
|
|
213
231
|
|
|
232
|
+
To stop the proxy:
|
|
233
|
+
```bash
|
|
234
|
+
oa2a stop
|
|
235
|
+
```
|
|
236
|
+
|
|
214
237
|
---
|
|
215
238
|
|
|
216
239
|
## Features
|