ccproxy-api 0.2.0__py3-none-any.whl → 0.2.2__py3-none-any.whl
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.
- ccproxy/core/_version.py +2 -2
- ccproxy/llms/formatters/anthropic_to_openai/_helpers.py +44 -0
- ccproxy/llms/formatters/anthropic_to_openai/responses.py +19 -2
- ccproxy/llms/formatters/anthropic_to_openai/streams.py +9 -17
- ccproxy/plugins/claude_api/adapter.py +5 -0
- {ccproxy_api-0.2.0.dist-info → ccproxy_api-0.2.2.dist-info}/METADATA +1 -1
- {ccproxy_api-0.2.0.dist-info → ccproxy_api-0.2.2.dist-info}/RECORD +10 -9
- {ccproxy_api-0.2.0.dist-info → ccproxy_api-0.2.2.dist-info}/WHEEL +0 -0
- {ccproxy_api-0.2.0.dist-info → ccproxy_api-0.2.2.dist-info}/entry_points.txt +0 -0
- {ccproxy_api-0.2.0.dist-info → ccproxy_api-0.2.2.dist-info}/licenses/LICENSE +0 -0
ccproxy/core/_version.py
CHANGED
|
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
|
|
|
28
28
|
commit_id: COMMIT_ID
|
|
29
29
|
__commit_id__: COMMIT_ID
|
|
30
30
|
|
|
31
|
-
__version__ = version = '0.2.
|
|
32
|
-
__version_tuple__ = version_tuple = (0, 2,
|
|
31
|
+
__version__ = version = '0.2.2'
|
|
32
|
+
__version_tuple__ = version_tuple = (0, 2, 2)
|
|
33
33
|
|
|
34
34
|
__commit_id__ = commit_id = None
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"""Shared helpers for Anthropic to OpenAI formatting."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
from ccproxy.llms.models import openai as openai_models
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def serialize_tool_arguments(tool_input: Any) -> str:
|
|
12
|
+
if isinstance(tool_input, str):
|
|
13
|
+
return tool_input
|
|
14
|
+
try:
|
|
15
|
+
return json.dumps(tool_input, ensure_ascii=False)
|
|
16
|
+
except Exception:
|
|
17
|
+
return json.dumps({"arguments": str(tool_input)})
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def build_openai_tool_call(
|
|
21
|
+
*,
|
|
22
|
+
tool_id: str | None,
|
|
23
|
+
tool_name: str | None,
|
|
24
|
+
tool_input: Any,
|
|
25
|
+
arguments: Any = None,
|
|
26
|
+
fallback_index: int = 0,
|
|
27
|
+
) -> openai_models.ToolCall:
|
|
28
|
+
args_str = (
|
|
29
|
+
arguments
|
|
30
|
+
if isinstance(arguments, str) and arguments
|
|
31
|
+
else serialize_tool_arguments(tool_input)
|
|
32
|
+
)
|
|
33
|
+
call_id = (
|
|
34
|
+
tool_id if isinstance(tool_id, str) and tool_id else f"call_{fallback_index}"
|
|
35
|
+
)
|
|
36
|
+
name = tool_name if isinstance(tool_name, str) and tool_name else "function"
|
|
37
|
+
|
|
38
|
+
return openai_models.ToolCall(
|
|
39
|
+
id=str(call_id),
|
|
40
|
+
function=openai_models.FunctionCall(
|
|
41
|
+
name=str(name),
|
|
42
|
+
arguments=str(args_str),
|
|
43
|
+
),
|
|
44
|
+
)
|
|
@@ -14,6 +14,8 @@ from ccproxy.llms.formatters.constants import ANTHROPIC_TO_OPENAI_FINISH_REASON
|
|
|
14
14
|
from ccproxy.llms.models import anthropic as anthropic_models
|
|
15
15
|
from ccproxy.llms.models import openai as openai_models
|
|
16
16
|
|
|
17
|
+
from ._helpers import build_openai_tool_call
|
|
18
|
+
|
|
17
19
|
|
|
18
20
|
logger = ccproxy.core.logging.get_logger(__name__)
|
|
19
21
|
|
|
@@ -101,6 +103,8 @@ def convert__anthropic_message_to_openai_chat__response(
|
|
|
101
103
|
"""Convert Anthropic MessageResponse to an OpenAI ChatCompletionResponse."""
|
|
102
104
|
content_blocks = response.content
|
|
103
105
|
parts: list[str] = []
|
|
106
|
+
tool_calls: list[openai_models.ToolCall] = []
|
|
107
|
+
|
|
104
108
|
for block in content_blocks:
|
|
105
109
|
btype = getattr(block, "type", None)
|
|
106
110
|
if btype == "text":
|
|
@@ -117,8 +121,17 @@ def convert__anthropic_message_to_openai_chat__response(
|
|
|
117
121
|
else ""
|
|
118
122
|
)
|
|
119
123
|
parts.append(f"<thinking{sig_attr}>{thinking}</thinking>")
|
|
124
|
+
elif btype == "tool_use":
|
|
125
|
+
tool_calls.append(
|
|
126
|
+
build_openai_tool_call(
|
|
127
|
+
tool_id=getattr(block, "id", None),
|
|
128
|
+
tool_name=getattr(block, "name", None),
|
|
129
|
+
tool_input=getattr(block, "input", {}) or {},
|
|
130
|
+
fallback_index=len(tool_calls),
|
|
131
|
+
)
|
|
132
|
+
)
|
|
120
133
|
|
|
121
|
-
content_text = "".join(parts)
|
|
134
|
+
content_text = "".join(parts) if parts else None
|
|
122
135
|
|
|
123
136
|
stop_reason = response.stop_reason
|
|
124
137
|
finish_reason = ANTHROPIC_TO_OPENAI_FINISH_REASON.get(
|
|
@@ -127,12 +140,16 @@ def convert__anthropic_message_to_openai_chat__response(
|
|
|
127
140
|
|
|
128
141
|
usage_model = convert__anthropic_usage_to_openai_completion__usage(response.usage)
|
|
129
142
|
|
|
143
|
+
message_dict: dict[str, Any] = {"role": "assistant", "content": content_text}
|
|
144
|
+
if tool_calls:
|
|
145
|
+
message_dict["tool_calls"] = [call.model_dump() for call in tool_calls]
|
|
146
|
+
|
|
130
147
|
payload = {
|
|
131
148
|
"id": response.id,
|
|
132
149
|
"choices": [
|
|
133
150
|
{
|
|
134
151
|
"index": 0,
|
|
135
|
-
"message":
|
|
152
|
+
"message": message_dict,
|
|
136
153
|
"finish_reason": finish_reason,
|
|
137
154
|
}
|
|
138
155
|
],
|
|
@@ -27,10 +27,9 @@ from ccproxy.llms.models import anthropic as anthropic_models
|
|
|
27
27
|
from ccproxy.llms.models import openai as openai_models
|
|
28
28
|
from ccproxy.llms.streaming.accumulators import ClaudeAccumulator
|
|
29
29
|
|
|
30
|
+
from ._helpers import build_openai_tool_call
|
|
30
31
|
from .requests import _build_responses_payload_from_anthropic_request
|
|
31
|
-
from .responses import
|
|
32
|
-
convert__anthropic_usage_to_openai_responses__usage,
|
|
33
|
-
)
|
|
32
|
+
from .responses import convert__anthropic_usage_to_openai_responses__usage
|
|
34
33
|
|
|
35
34
|
|
|
36
35
|
logger = ccproxy.core.logging.get_logger(__name__)
|
|
@@ -100,22 +99,15 @@ def _build_openai_tool_call(
|
|
|
100
99
|
function_payload = (
|
|
101
100
|
tool_call.get("function", {}) if isinstance(tool_call, dict) else {}
|
|
102
101
|
)
|
|
103
|
-
|
|
102
|
+
tool_name = function_payload.get("name") or tool_call.get("name")
|
|
104
103
|
arguments = function_payload.get("arguments")
|
|
105
|
-
if not isinstance(arguments, str) or not arguments:
|
|
106
|
-
try:
|
|
107
|
-
arguments = json.dumps(tool_call.get("input", {}), ensure_ascii=False)
|
|
108
|
-
except Exception:
|
|
109
|
-
arguments = json.dumps(tool_call.get("input", {}))
|
|
110
|
-
|
|
111
|
-
tool_id = tool_call.get("id") or f"call_{block_index}"
|
|
112
104
|
|
|
113
|
-
return
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
105
|
+
return build_openai_tool_call(
|
|
106
|
+
tool_id=tool_call.get("id"),
|
|
107
|
+
tool_name=tool_name,
|
|
108
|
+
tool_input=tool_call.get("input", {}),
|
|
109
|
+
arguments=arguments,
|
|
110
|
+
fallback_index=block_index,
|
|
119
111
|
)
|
|
120
112
|
|
|
121
113
|
return None
|
|
@@ -85,6 +85,11 @@ class ClaudeAPIAdapter(BaseHTTPAdapter):
|
|
|
85
85
|
# Always set Authorization from OAuth-managed access token
|
|
86
86
|
filtered_headers["authorization"] = f"Bearer {token_value}"
|
|
87
87
|
|
|
88
|
+
# PATCH: Add Computer Use beta headers for Anthropic API
|
|
89
|
+
# These are required for browser automation tools to work
|
|
90
|
+
filtered_headers["anthropic-version"] = "2023-06-01"
|
|
91
|
+
filtered_headers["anthropic-beta"] = "computer-use-2025-01-24"
|
|
92
|
+
|
|
88
93
|
# Add CLI headers if available, but never allow overriding auth
|
|
89
94
|
cli_headers = self._collect_cli_headers()
|
|
90
95
|
if cli_headers:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ccproxy-api
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: API server that provides an Anthropic and OpenAI compatible interface over Claude Code, allowing to use your Claude OAuth account or over the API.
|
|
5
5
|
License-File: LICENSE
|
|
6
6
|
Requires-Python: >=3.11
|
|
@@ -67,7 +67,7 @@ ccproxy/config/settings.py,sha256=uva0RV4KfIvv7VApDr7w3oARft7OoBCWf7ZSM4oM2VM,19
|
|
|
67
67
|
ccproxy/config/toml_generator.py,sha256=_txCYDHI8lXWl-mwOK8P1_TsX1TNiLgkG4iryxOruZc,10034
|
|
68
68
|
ccproxy/config/utils.py,sha256=tuvOPUsMGgznz94MRwuSWw6sZi_AGkB_ri7VWKMVg8Y,11877
|
|
69
69
|
ccproxy/core/__init__.py,sha256=hQgrBogZjdt8ZQlQyZtbL91I3gX9YUTWrenqTPRfwbM,236
|
|
70
|
-
ccproxy/core/_version.py,sha256=
|
|
70
|
+
ccproxy/core/_version.py,sha256=o3ZTescp-19Z9cvBGq9dQnbppljgzdUYUf98Nov0spY,704
|
|
71
71
|
ccproxy/core/async_task_manager.py,sha256=zf_mbbDwomh8q0E-oMNSPzFecHwLRi-ZPbhqsb6IPgM,16888
|
|
72
72
|
ccproxy/core/async_utils.py,sha256=OFCJT8xbgZJO757iDPMAKY5c1Ildyk0PbwuktVF19UI,21676
|
|
73
73
|
ccproxy/core/constants.py,sha256=FSLlbdNqCmZgZC4VAgvmovwXJh4C9WaUf_YBqDbYXXM,1837
|
|
@@ -121,10 +121,11 @@ ccproxy/llms/formatters/context.py,sha256=ULZl3sIcGbYKqzqo-W4HNpYoWD03vPVU-akahg
|
|
|
121
121
|
ccproxy/llms/formatters/mapping.py,sha256=Tskj43bbDQAZWjqKEfnoivStwAycPXDGn1vXjuqTaic,1014
|
|
122
122
|
ccproxy/llms/formatters/utils.py,sha256=7TKOraamcc_TXAxYkTv_HUFXr-fkHnqyBWb7WU9eZn4,10224
|
|
123
123
|
ccproxy/llms/formatters/anthropic_to_openai/__init__.py,sha256=BR4ZAbaPRPd3q7Urb22ylyUgWaVi7UQ2zJzzGBam_Lw,1992
|
|
124
|
+
ccproxy/llms/formatters/anthropic_to_openai/_helpers.py,sha256=mX2HTsmcofkZ-ocBUUr62q0IxHpG2n5oS_cryAY6yvs,1166
|
|
124
125
|
ccproxy/llms/formatters/anthropic_to_openai/errors.py,sha256=PCGB7PKr6x1jElIKxqDye0o1mI0_MUdTNMtk_djWbLA,2066
|
|
125
126
|
ccproxy/llms/formatters/anthropic_to_openai/requests.py,sha256=e7BanFju5owBD64gtd835YIv1T18XYshp-DP-7I4y1o,14660
|
|
126
|
-
ccproxy/llms/formatters/anthropic_to_openai/responses.py,sha256=
|
|
127
|
-
ccproxy/llms/formatters/anthropic_to_openai/streams.py,sha256=
|
|
127
|
+
ccproxy/llms/formatters/anthropic_to_openai/responses.py,sha256=uDq5NAvfinPDC75pY54j8BJzltb5r1kAeytToz0InFM,5834
|
|
128
|
+
ccproxy/llms/formatters/anthropic_to_openai/streams.py,sha256=CGW74eS-TZ9_0pM9ff2MfdI9yUhfmqXlwP7jS96obZQ,65722
|
|
128
129
|
ccproxy/llms/formatters/common/__init__.py,sha256=Lnsz81M4P91Cex7t0_oM_hD1Tak7oHAWuykQkWg4b38,1524
|
|
129
130
|
ccproxy/llms/formatters/common/identifiers.py,sha256=rzTynHqcvmPKhog64YAtxLDcQH27u38kZH8aCI3HIOA,1400
|
|
130
131
|
ccproxy/llms/formatters/common/streams.py,sha256=kP_QQViwki1dH9IIMtigQLOtTY8wM2KZoQMFMl8vE_Y,8042
|
|
@@ -170,7 +171,7 @@ ccproxy/plugins/analytics/routes.py,sha256=RZLbaRkvo1vFvOasnzlqKyyTIm01dLYTg-T4a
|
|
|
170
171
|
ccproxy/plugins/analytics/service.py,sha256=9aqS0sNZVsKsbrhYi62jdkkDgeoifcC3ARM3d4dweJ0,11699
|
|
171
172
|
ccproxy/plugins/claude_api/README.md,sha256=kXpPt1NMbKdQiG0D4UmJKreLytWJKr0FwS9pSrxEgTE,1072
|
|
172
173
|
ccproxy/plugins/claude_api/__init__.py,sha256=2n3Kw6EGmvEyoSgQzT2DRwLe5Zb1XET7kvvt0mwG3Mg,304
|
|
173
|
-
ccproxy/plugins/claude_api/adapter.py,sha256=
|
|
174
|
+
ccproxy/plugins/claude_api/adapter.py,sha256=T1y9lAxJEj5yqiyo210IlZeRfSmuqyi4Gt1Jx6q5Bew,31121
|
|
174
175
|
ccproxy/plugins/claude_api/config.py,sha256=R-8w5yOYcN42tx4cR3eyzyz99Ldt4B1aTDj_vEy9NdQ,1681
|
|
175
176
|
ccproxy/plugins/claude_api/detection_service.py,sha256=mJeYvSskPS8mN-RTvwEVkPqN-91LZVfD7BsfYw7mDR8,15975
|
|
176
177
|
ccproxy/plugins/claude_api/health.py,sha256=s1Vb3JuHWaWslLKOyFJXq6PrDAkzjEhhHXAR2cVXgQ8,5990
|
|
@@ -410,8 +411,8 @@ ccproxy/utils/id_generator.py,sha256=k6R_W40lJSPi_it4M99EVg9eRD138oC4bv_8Ua3X8ms
|
|
|
410
411
|
ccproxy/utils/model_mapper.py,sha256=hnIWc528x8oBuk1y1HuyGHbnwe6dsSxZ2UgA1OYrcJs,3731
|
|
411
412
|
ccproxy/utils/startup_helpers.py,sha256=u1okOVbm2OeSqrNrbhWco_sXBR0usNo7Wv8zvhBLPhc,7492
|
|
412
413
|
ccproxy/utils/version_checker.py,sha256=cGRgjD0PUB3MDZDSAdKPQwYIyqnlzFWue0ROyfGngNE,13452
|
|
413
|
-
ccproxy_api-0.2.
|
|
414
|
-
ccproxy_api-0.2.
|
|
415
|
-
ccproxy_api-0.2.
|
|
416
|
-
ccproxy_api-0.2.
|
|
417
|
-
ccproxy_api-0.2.
|
|
414
|
+
ccproxy_api-0.2.2.dist-info/METADATA,sha256=5rWBdjovufqSnrAZSnIIy1HwiwWgP2a9R3xf7yV5WCE,8280
|
|
415
|
+
ccproxy_api-0.2.2.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
416
|
+
ccproxy_api-0.2.2.dist-info/entry_points.txt,sha256=bibqQtPpKZJhOY_j5TFvcYzHuR-w7tNovV2i7UcPlU4,1147
|
|
417
|
+
ccproxy_api-0.2.2.dist-info/licenses/LICENSE,sha256=httxSCpTrEOkipisMeGXSrZhTB-4MRIorQU0hS1B6eQ,1066
|
|
418
|
+
ccproxy_api-0.2.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|