local-openai2anthropic 0.3.3__tar.gz → 0.3.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 (61) hide show
  1. local_openai2anthropic-0.3.5/.reports/dead-code-analysis.md +282 -0
  2. {local_openai2anthropic-0.3.3 → local_openai2anthropic-0.3.5}/PKG-INFO +1 -1
  3. {local_openai2anthropic-0.3.3 → local_openai2anthropic-0.3.5}/pyproject.toml +1 -1
  4. {local_openai2anthropic-0.3.3 → local_openai2anthropic-0.3.5}/src/local_openai2anthropic/__init__.py +1 -1
  5. {local_openai2anthropic-0.3.3 → local_openai2anthropic-0.3.5}/src/local_openai2anthropic/config.py +1 -0
  6. {local_openai2anthropic-0.3.3 → local_openai2anthropic-0.3.5}/src/local_openai2anthropic/converter.py +8 -4
  7. {local_openai2anthropic-0.3.3 → local_openai2anthropic-0.3.5}/src/local_openai2anthropic/main.py +75 -6
  8. {local_openai2anthropic-0.3.3 → local_openai2anthropic-0.3.5}/src/local_openai2anthropic/protocol.py +1 -1
  9. local_openai2anthropic-0.3.5/src/local_openai2anthropic/router.py +424 -0
  10. local_openai2anthropic-0.3.5/src/local_openai2anthropic/streaming/__init__.py +6 -0
  11. local_openai2anthropic-0.3.5/src/local_openai2anthropic/streaming/handler.py +444 -0
  12. local_openai2anthropic-0.3.5/src/local_openai2anthropic/tools/__init__.py +14 -0
  13. local_openai2anthropic-0.3.5/src/local_openai2anthropic/tools/handler.py +357 -0
  14. local_openai2anthropic-0.3.5/src/local_openai2anthropic/utils/__init__.py +18 -0
  15. local_openai2anthropic-0.3.5/src/local_openai2anthropic/utils/tokens.py +96 -0
  16. local_openai2anthropic-0.3.5/tests/coverage/coverage.json +1 -0
  17. local_openai2anthropic-0.3.5/tests/coverage/coverage_detailed.json +1 -0
  18. local_openai2anthropic-0.3.5/tests/coverage/coverage_report.json +1 -0
  19. local_openai2anthropic-0.3.5/tests/coverage/coverage_report_new.json +1 -0
  20. local_openai2anthropic-0.3.5/tests/coverage/coverage_summary.json +1 -0
  21. local_openai2anthropic-0.3.5/tests/test_config.py +177 -0
  22. local_openai2anthropic-0.3.5/tests/test_converter_edge_cases.py +335 -0
  23. local_openai2anthropic-0.3.5/tests/test_daemon.py +330 -0
  24. local_openai2anthropic-0.3.5/tests/test_daemon_advanced.py +283 -0
  25. local_openai2anthropic-0.3.5/tests/test_daemon_runner.py +221 -0
  26. local_openai2anthropic-0.3.5/tests/test_e2e_multimodel.py +438 -0
  27. {local_openai2anthropic-0.3.3 → local_openai2anthropic-0.3.5}/tests/test_integration.py +0 -1
  28. local_openai2anthropic-0.3.5/tests/test_logging.py +270 -0
  29. local_openai2anthropic-0.3.5/tests/test_main.py +372 -0
  30. local_openai2anthropic-0.3.5/tests/test_openai_types.py +361 -0
  31. local_openai2anthropic-0.3.5/tests/test_protocol.py +372 -0
  32. {local_openai2anthropic-0.3.3 → local_openai2anthropic-0.3.5}/tests/test_router.py +7 -9
  33. local_openai2anthropic-0.3.5/tests/test_router_comprehensive.py +652 -0
  34. local_openai2anthropic-0.3.5/tests/test_router_edge_cases.py +321 -0
  35. local_openai2anthropic-0.3.5/tests/test_router_streaming.py +612 -0
  36. local_openai2anthropic-0.3.5/tests/test_server_tools.py +466 -0
  37. local_openai2anthropic-0.3.5/tests/test_tavily_client.py +258 -0
  38. local_openai2anthropic-0.3.3/src/local_openai2anthropic/router.py +0 -1229
  39. {local_openai2anthropic-0.3.3 → local_openai2anthropic-0.3.5}/.github/workflows/publish.yml +0 -0
  40. {local_openai2anthropic-0.3.3 → local_openai2anthropic-0.3.5}/.gitignore +0 -0
  41. {local_openai2anthropic-0.3.3 → local_openai2anthropic-0.3.5}/LICENSE +0 -0
  42. {local_openai2anthropic-0.3.3 → local_openai2anthropic-0.3.5}/README.md +0 -0
  43. {local_openai2anthropic-0.3.3 → local_openai2anthropic-0.3.5}/README_zh.md +0 -0
  44. {local_openai2anthropic-0.3.3 → local_openai2anthropic-0.3.5}/examples/basic_chat.py +0 -0
  45. {local_openai2anthropic-0.3.3 → local_openai2anthropic-0.3.5}/examples/streaming.py +0 -0
  46. {local_openai2anthropic-0.3.3 → local_openai2anthropic-0.3.5}/examples/thinking_mode.py +0 -0
  47. {local_openai2anthropic-0.3.3 → local_openai2anthropic-0.3.5}/examples/tool_calling.py +0 -0
  48. {local_openai2anthropic-0.3.3 → local_openai2anthropic-0.3.5}/examples/vision.py +0 -0
  49. {local_openai2anthropic-0.3.3 → local_openai2anthropic-0.3.5}/examples/web_search.py +0 -0
  50. {local_openai2anthropic-0.3.3 → local_openai2anthropic-0.3.5}/src/local_openai2anthropic/__main__.py +0 -0
  51. {local_openai2anthropic-0.3.3 → local_openai2anthropic-0.3.5}/src/local_openai2anthropic/daemon.py +0 -0
  52. {local_openai2anthropic-0.3.3 → local_openai2anthropic-0.3.5}/src/local_openai2anthropic/daemon_runner.py +0 -0
  53. {local_openai2anthropic-0.3.3 → local_openai2anthropic-0.3.5}/src/local_openai2anthropic/openai_types.py +0 -0
  54. {local_openai2anthropic-0.3.3 → local_openai2anthropic-0.3.5}/src/local_openai2anthropic/server_tools/__init__.py +0 -0
  55. {local_openai2anthropic-0.3.3 → local_openai2anthropic-0.3.5}/src/local_openai2anthropic/server_tools/base.py +0 -0
  56. {local_openai2anthropic-0.3.3 → local_openai2anthropic-0.3.5}/src/local_openai2anthropic/server_tools/web_search.py +0 -0
  57. {local_openai2anthropic-0.3.3 → local_openai2anthropic-0.3.5}/src/local_openai2anthropic/tavily_client.py +0 -0
  58. {local_openai2anthropic-0.3.3 → local_openai2anthropic-0.3.5}/tests/__init__.py +0 -0
  59. {local_openai2anthropic-0.3.3 → local_openai2anthropic-0.3.5}/tests/test_converter.py +0 -0
  60. {local_openai2anthropic-0.3.3 → local_openai2anthropic-0.3.5}/tests/test_upstream.sh +0 -0
  61. {local_openai2anthropic-0.3.3 → local_openai2anthropic-0.3.5}/uv.lock +0 -0
@@ -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.3
3
+ Version: 0.3.5
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
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "local-openai2anthropic"
3
- version = "0.3.3"
3
+ version = "0.3.5"
4
4
  description = "A lightweight proxy server that converts Anthropic Messages API to OpenAI API"
5
5
  readme = "README.md"
6
6
  license = { text = "Apache-2.0" }
@@ -3,7 +3,7 @@
3
3
  local-openai2anthropic: A proxy server that converts Anthropic Messages API to OpenAI API.
4
4
  """
5
5
 
6
- __version__ = "0.2.5"
6
+ __version__ = "0.3.5"
7
7
 
8
8
  from local_openai2anthropic.protocol import (
9
9
  AnthropicError,
@@ -42,6 +42,7 @@ class Settings(BaseSettings):
42
42
 
43
43
  # Logging
44
44
  log_level: str = "DEBUG"
45
+ log_dir: str = "" # Empty means use platform-specific default
45
46
 
46
47
  # Tavily Web Search Configuration
47
48
  tavily_api_key: Optional[str] = None
@@ -17,13 +17,11 @@ from anthropic.types import (
17
17
  from anthropic.types.message_create_params import MessageCreateParams
18
18
  from openai.types.chat import (
19
19
  ChatCompletion,
20
- ChatCompletionChunk,
21
20
  ChatCompletionToolParam,
22
21
  )
23
22
  from openai.types.chat.completion_create_params import CompletionCreateParams
24
23
 
25
24
  from local_openai2anthropic.protocol import UsageWithCache
26
- from local_openai2anthropic.server_tools import ServerToolRegistry
27
25
 
28
26
  logger = logging.getLogger(__name__)
29
27
 
@@ -54,6 +52,7 @@ def convert_anthropic_to_openai(
54
52
  tools = anthropic_params.get("tools")
55
53
  top_k = anthropic_params.get("top_k")
56
54
  top_p = anthropic_params.get("top_p", 0.95)
55
+ repetition_penalty = anthropic_params.get("repetition_penalty", 1.1)
57
56
  thinking = anthropic_params.get("thinking")
58
57
  # metadata is accepted but not forwarded to OpenAI
59
58
 
@@ -102,6 +101,7 @@ def convert_anthropic_to_openai(
102
101
  "messages": openai_messages,
103
102
  "max_tokens": max_tokens,
104
103
  "stream": stream,
104
+ "repetition_penalty": repetition_penalty,
105
105
  }
106
106
 
107
107
  # Always include usage in stream for accurate token counting
@@ -288,11 +288,11 @@ def _convert_anthropic_message_to_openai(
288
288
  if isinstance(block, dict):
289
289
  tool_use_id = block.get("tool_use_id", "")
290
290
  result_content = block.get("content", "")
291
- is_error = block.get("is_error", False)
291
+ # Note: is_error is not directly supported in OpenAI API
292
292
  else:
293
293
  tool_use_id = block.tool_use_id
294
294
  result_content = block.content
295
- is_error = getattr(block, "is_error", False)
295
+ # Note: is_error is not directly supported in OpenAI API
296
296
 
297
297
  # Handle content that might be a list or string
298
298
  if isinstance(result_content, list):
@@ -404,6 +404,10 @@ def convert_openai_to_anthropic(
404
404
  # Convert tool calls
405
405
  if message.tool_calls:
406
406
  for tc in message.tool_calls:
407
+ # Handle case where function might be None
408
+ if not tc.function:
409
+ continue
410
+
407
411
  tool_input: dict[str, Any] = {}
408
412
  try:
409
413
  tool_input = json.loads(tc.function.arguments)
@@ -5,7 +5,10 @@ Main entry point for the local-openai2anthropic proxy server.
5
5
 
6
6
  import argparse
7
7
  import logging
8
+ import os
8
9
  import sys
10
+ from logging.handlers import TimedRotatingFileHandler
11
+ from pathlib import Path
9
12
 
10
13
  import uvicorn
11
14
  from fastapi import FastAPI, HTTPException, Request
@@ -17,22 +20,88 @@ from local_openai2anthropic.protocol import AnthropicError, AnthropicErrorRespon
17
20
  from local_openai2anthropic.router import router
18
21
 
19
22
 
23
+ def get_default_log_dir() -> str:
24
+ """Get default log directory based on platform.
25
+
26
+ Returns:
27
+ Path to log directory
28
+ """
29
+ if sys.platform == 'win32':
30
+ # Windows: use %LOCALAPPDATA%\local-openai2anthropic\logs
31
+ base_dir = os.environ.get('LOCALAPPDATA', os.path.expanduser('~\\AppData\\Local'))
32
+ return os.path.join(base_dir, 'local-openai2anthropic', 'logs')
33
+ else:
34
+ # macOS/Linux: use ~/.local/share/local-openai2anthropic/logs
35
+ return os.path.expanduser("~/.local/share/local-openai2anthropic/logs")
36
+
37
+
38
+ def setup_logging(log_level: str, log_dir: str | None = None) -> None:
39
+ """Setup logging with daily rotation, keeping only today's logs.
40
+
41
+ Args:
42
+ log_level: Logging level (DEBUG, INFO, WARNING, ERROR)
43
+ log_dir: Directory for log files (platform-specific default)
44
+ """
45
+ # Default log directory based on platform
46
+ if log_dir is None:
47
+ log_dir = get_default_log_dir()
48
+
49
+ # Expand user directory if specified
50
+ log_dir = os.path.expanduser(log_dir)
51
+
52
+ # Create log directory if it doesn't exist
53
+ Path(log_dir).mkdir(parents=True, exist_ok=True)
54
+
55
+ log_file = os.path.join(log_dir, "server.log")
56
+
57
+ # Create formatter
58
+ formatter = logging.Formatter(
59
+ "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
60
+ )
61
+
62
+ # Setup root logger
63
+ root_logger = logging.getLogger()
64
+ root_logger.setLevel(getattr(logging, log_level.upper()))
65
+
66
+ # Clear existing handlers
67
+ root_logger.handlers = []
68
+
69
+ # Console handler
70
+ console_handler = logging.StreamHandler(sys.stdout)
71
+ console_handler.setFormatter(formatter)
72
+ root_logger.addHandler(console_handler)
73
+
74
+ # File handler with daily rotation
75
+ # backupCount=0 means no backup files are kept (only today's log)
76
+ # when='midnight' rotates at midnight
77
+ file_handler = TimedRotatingFileHandler(
78
+ log_file,
79
+ when='midnight',
80
+ interval=1,
81
+ backupCount=0, # Keep only today's log
82
+ encoding='utf-8'
83
+ )
84
+ file_handler.setFormatter(formatter)
85
+ root_logger.addHandler(file_handler)
86
+
87
+ logging.info(f"Logging configured. Log file: {log_file}")
88
+
89
+
20
90
  def create_app(settings: Settings | None = None) -> FastAPI:
21
91
  """Create and configure the FastAPI application."""
22
92
  if settings is None:
23
93
  settings = get_settings()
24
94
 
25
- # Configure logging
26
- logging.basicConfig(
27
- level=getattr(logging, settings.log_level.upper()),
28
- format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
29
- )
95
+ # Configure logging with daily rotation
96
+ # Use platform-specific default if log_dir is not set
97
+ log_dir = settings.log_dir if settings.log_dir else None
98
+ setup_logging(settings.log_level, log_dir)
30
99
 
31
100
  # Create FastAPI app
32
101
  app = FastAPI(
33
102
  title="local-openai2anthropic",
34
103
  description="A proxy server that converts Anthropic Messages API to OpenAI API",
35
- version="0.2.5",
104
+ version="0.3.5",
36
105
  docs_url="/docs",
37
106
  redoc_url="/redoc",
38
107
  )
@@ -6,7 +6,7 @@ Uses Anthropic SDK types for request/response models.
6
6
 
7
7
  from typing import Any, Literal, Optional
8
8
 
9
- from pydantic import BaseModel, Field
9
+ from pydantic import BaseModel
10
10
 
11
11
  # Re-export all Anthropic types for convenience
12
12
  from anthropic.types import (