ccproxy-api 0.2.0a4__py3-none-any.whl → 0.2.3__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/plugins/oauth_claude/storage.py +103 -8
- {ccproxy_api-0.2.0a4.dist-info → ccproxy_api-0.2.3.dist-info}/METADATA +4 -3
- {ccproxy_api-0.2.0a4.dist-info → ccproxy_api-0.2.3.dist-info}/RECORD +11 -10
- {ccproxy_api-0.2.0a4.dist-info → ccproxy_api-0.2.3.dist-info}/WHEEL +0 -0
- {ccproxy_api-0.2.0a4.dist-info → ccproxy_api-0.2.3.dist-info}/entry_points.txt +0 -0
- {ccproxy_api-0.2.0a4.dist-info → ccproxy_api-0.2.3.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.3'
|
|
32
|
+
__version_tuple__ = version_tuple = (0, 2, 3)
|
|
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:
|
|
@@ -15,6 +15,77 @@ from .models import ClaudeCredentials, ClaudeProfileInfo
|
|
|
15
15
|
logger = get_plugin_logger()
|
|
16
16
|
|
|
17
17
|
|
|
18
|
+
# Keychain service name used by Claude Code
|
|
19
|
+
KEYCHAIN_SERVICE = "Claude Code"
|
|
20
|
+
KEYCHAIN_ACCOUNT = "credentials"
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def _is_keyring_available() -> bool:
|
|
24
|
+
"""Check if keyring library is available."""
|
|
25
|
+
try:
|
|
26
|
+
import keyring # noqa: F401
|
|
27
|
+
|
|
28
|
+
return True
|
|
29
|
+
except ImportError:
|
|
30
|
+
return False
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
async def _read_from_keychain() -> dict[str, Any] | None:
|
|
34
|
+
"""Read Claude credentials from system keychain.
|
|
35
|
+
|
|
36
|
+
Claude Code stores OAuth credentials in the system keychain and intentionally
|
|
37
|
+
deletes the plain text ~/.claude/.credentials.json file for security.
|
|
38
|
+
See: https://github.com/anthropics/claude-code/issues/1414
|
|
39
|
+
|
|
40
|
+
Uses the keyring library which supports:
|
|
41
|
+
- macOS Keychain
|
|
42
|
+
- Windows Credential Manager
|
|
43
|
+
- Linux Secret Service (GNOME Keyring, KDE Wallet)
|
|
44
|
+
|
|
45
|
+
Returns:
|
|
46
|
+
Parsed credentials dict or None if not found or keyring unavailable
|
|
47
|
+
"""
|
|
48
|
+
if not _is_keyring_available():
|
|
49
|
+
logger.debug(
|
|
50
|
+
"keyring_not_available",
|
|
51
|
+
hint="Install keyring package for system keychain support",
|
|
52
|
+
category="auth",
|
|
53
|
+
)
|
|
54
|
+
return None
|
|
55
|
+
|
|
56
|
+
def read_keychain() -> dict[str, Any] | None:
|
|
57
|
+
try:
|
|
58
|
+
import keyring
|
|
59
|
+
|
|
60
|
+
password = keyring.get_password(KEYCHAIN_SERVICE, KEYCHAIN_ACCOUNT)
|
|
61
|
+
if password:
|
|
62
|
+
parsed = json.loads(password)
|
|
63
|
+
if isinstance(parsed, dict):
|
|
64
|
+
return parsed
|
|
65
|
+
logger.debug(
|
|
66
|
+
"keychain_invalid_format",
|
|
67
|
+
expected="dict",
|
|
68
|
+
got=type(parsed).__name__,
|
|
69
|
+
category="auth",
|
|
70
|
+
)
|
|
71
|
+
except json.JSONDecodeError as e:
|
|
72
|
+
logger.debug(
|
|
73
|
+
"keychain_json_decode_error",
|
|
74
|
+
error=str(e),
|
|
75
|
+
category="auth",
|
|
76
|
+
)
|
|
77
|
+
except Exception as e:
|
|
78
|
+
logger.debug(
|
|
79
|
+
"keychain_read_error",
|
|
80
|
+
error=str(e),
|
|
81
|
+
error_type=type(e).__name__,
|
|
82
|
+
category="auth",
|
|
83
|
+
)
|
|
84
|
+
return None
|
|
85
|
+
|
|
86
|
+
return await asyncio.to_thread(read_keychain)
|
|
87
|
+
|
|
88
|
+
|
|
18
89
|
class ClaudeOAuthStorage(BaseJsonStorage[ClaudeCredentials]):
|
|
19
90
|
"""Claude OAuth-specific token storage implementation."""
|
|
20
91
|
|
|
@@ -61,24 +132,48 @@ class ClaudeOAuthStorage(BaseJsonStorage[ClaudeCredentials]):
|
|
|
61
132
|
return False
|
|
62
133
|
|
|
63
134
|
async def load(self) -> ClaudeCredentials | None:
|
|
64
|
-
"""Load Claude credentials.
|
|
135
|
+
"""Load Claude credentials from file or system keychain.
|
|
136
|
+
|
|
137
|
+
Claude Code stores credentials in the system keychain and intentionally
|
|
138
|
+
deletes the plain text file for security. This method tries file first,
|
|
139
|
+
then falls back to the system keychain (macOS Keychain, Windows Credential
|
|
140
|
+
Manager, or Linux Secret Service).
|
|
65
141
|
|
|
66
142
|
Returns:
|
|
67
143
|
Stored credentials or None
|
|
68
144
|
"""
|
|
69
145
|
try:
|
|
70
|
-
#
|
|
146
|
+
# Try file first (works on all platforms, manual setups)
|
|
71
147
|
data = await self._read_json()
|
|
72
|
-
if
|
|
73
|
-
|
|
148
|
+
if data:
|
|
149
|
+
credentials = ClaudeCredentials.model_validate(data)
|
|
150
|
+
logger.debug(
|
|
151
|
+
"claude_oauth_credentials_loaded",
|
|
152
|
+
has_oauth=bool(credentials.claude_ai_oauth),
|
|
153
|
+
source="file",
|
|
154
|
+
category="auth",
|
|
155
|
+
)
|
|
156
|
+
return credentials
|
|
157
|
+
|
|
158
|
+
# Fallback to system keychain (where Claude Code stores credentials)
|
|
159
|
+
keychain_data = await _read_from_keychain()
|
|
160
|
+
if keychain_data:
|
|
161
|
+
credentials = ClaudeCredentials.model_validate(keychain_data)
|
|
162
|
+
logger.debug(
|
|
163
|
+
"claude_oauth_credentials_loaded",
|
|
164
|
+
has_oauth=bool(credentials.claude_ai_oauth),
|
|
165
|
+
source="keychain",
|
|
166
|
+
category="auth",
|
|
167
|
+
)
|
|
168
|
+
return credentials
|
|
74
169
|
|
|
75
|
-
credentials = ClaudeCredentials.model_validate(data)
|
|
76
170
|
logger.debug(
|
|
77
|
-
"
|
|
78
|
-
|
|
171
|
+
"claude_oauth_credentials_not_found",
|
|
172
|
+
checked_file=str(self.file_path),
|
|
173
|
+
checked_keychain=_is_keyring_available(),
|
|
79
174
|
category="auth",
|
|
80
175
|
)
|
|
81
|
-
return
|
|
176
|
+
return None
|
|
82
177
|
except Exception as e:
|
|
83
178
|
logger.error(
|
|
84
179
|
"claude_oauth_credentials_load_error",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ccproxy-api
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.3
|
|
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
|
|
@@ -20,6 +20,7 @@ Requires-Dist: typing-extensions>=4.0.0
|
|
|
20
20
|
Requires-Dist: uvicorn>=0.34.0
|
|
21
21
|
Provides-Extra: plugins-claude
|
|
22
22
|
Requires-Dist: claude-agent-sdk>=0.1.0; extra == 'plugins-claude'
|
|
23
|
+
Requires-Dist: keyring>=25.0.0; extra == 'plugins-claude'
|
|
23
24
|
Requires-Dist: qrcode>=8.2; extra == 'plugins-claude'
|
|
24
25
|
Provides-Extra: plugins-codex
|
|
25
26
|
Requires-Dist: pyjwt>=2.10.1; extra == 'plugins-codex'
|
|
@@ -196,14 +197,14 @@ To install the latest stable release without cloning the repository, use `uvx`
|
|
|
196
197
|
to grab the published wheel and launch the CLI:
|
|
197
198
|
|
|
198
199
|
```bash
|
|
199
|
-
uvx --with "ccproxy-api[all]
|
|
200
|
+
uvx --with "ccproxy-api[all]" ccproxy serve --port 8000
|
|
200
201
|
```
|
|
201
202
|
|
|
202
203
|
If you prefer `pipx`, install the package (optionally with extras) and use the
|
|
203
204
|
local shim:
|
|
204
205
|
|
|
205
206
|
```bash
|
|
206
|
-
pipx install "ccproxy-api[all]
|
|
207
|
+
pipx install "ccproxy-api[all]"
|
|
207
208
|
ccproxy serve # default on localhost:8000
|
|
208
209
|
```
|
|
209
210
|
|
|
@@ -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=kBRz0P2plw1eVdIpt70W6m1LMbEIhLY3RyOfVGdubaI,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
|
|
@@ -300,7 +301,7 @@ ccproxy/plugins/oauth_claude/manager.py,sha256=0aOTVwPy3nDLhZsX5vcpWRG4kGqkdklOy
|
|
|
300
301
|
ccproxy/plugins/oauth_claude/models.py,sha256=90BQzi0MVL9sK7NtTYZjwSWR5DGmEPsU2F8zF60Jbgw,9227
|
|
301
302
|
ccproxy/plugins/oauth_claude/plugin.py,sha256=_EybVmwvigoJfuzAMETkknO3kQ-fp59earI7i1yWA-s,4918
|
|
302
303
|
ccproxy/plugins/oauth_claude/provider.py,sha256=lV0RUmBthE8rmnPUNqdtcYuZL_RED95bURBhOOcyDqQ,19500
|
|
303
|
-
ccproxy/plugins/oauth_claude/storage.py,sha256=
|
|
304
|
+
ccproxy/plugins/oauth_claude/storage.py,sha256=JsSSmeGkaQHhtdczhQdQSuTEGv4N6gmXX2YIJVzO68A,9844
|
|
304
305
|
ccproxy/plugins/oauth_codex/README.md,sha256=XgbCxp_JHadpYcq6JW-hC8YvBo9310CLqVbKdprY5Vc,1451
|
|
305
306
|
ccproxy/plugins/oauth_codex/__init__.py,sha256=pA4sU7Ngj0xY2Ppr_G6K_H4boihe-TL7ppvvusoBKEg,345
|
|
306
307
|
ccproxy/plugins/oauth_codex/client.py,sha256=Ry0uFDsdXXFUGdI5ol5i-zDgjEZtaToKdaUAlhmgyu4,7357
|
|
@@ -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.3.dist-info/METADATA,sha256=X9RSa7zriZwyjtyM4Qm-Br6D62c0u1aOeW7DfDfJl-Q,8338
|
|
415
|
+
ccproxy_api-0.2.3.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
416
|
+
ccproxy_api-0.2.3.dist-info/entry_points.txt,sha256=bibqQtPpKZJhOY_j5TFvcYzHuR-w7tNovV2i7UcPlU4,1147
|
|
417
|
+
ccproxy_api-0.2.3.dist-info/licenses/LICENSE,sha256=httxSCpTrEOkipisMeGXSrZhTB-4MRIorQU0hS1B6eQ,1066
|
|
418
|
+
ccproxy_api-0.2.3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|