ccproxy-api 0.1.0__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/__init__.py +4 -0
- ccproxy/__main__.py +7 -0
- ccproxy/_version.py +21 -0
- ccproxy/adapters/__init__.py +11 -0
- ccproxy/adapters/base.py +80 -0
- ccproxy/adapters/openai/__init__.py +43 -0
- ccproxy/adapters/openai/adapter.py +915 -0
- ccproxy/adapters/openai/models.py +412 -0
- ccproxy/adapters/openai/streaming.py +449 -0
- ccproxy/api/__init__.py +28 -0
- ccproxy/api/app.py +225 -0
- ccproxy/api/dependencies.py +140 -0
- ccproxy/api/middleware/__init__.py +11 -0
- ccproxy/api/middleware/auth.py +0 -0
- ccproxy/api/middleware/cors.py +55 -0
- ccproxy/api/middleware/errors.py +703 -0
- ccproxy/api/middleware/headers.py +51 -0
- ccproxy/api/middleware/logging.py +175 -0
- ccproxy/api/middleware/request_id.py +69 -0
- ccproxy/api/middleware/server_header.py +62 -0
- ccproxy/api/responses.py +84 -0
- ccproxy/api/routes/__init__.py +16 -0
- ccproxy/api/routes/claude.py +181 -0
- ccproxy/api/routes/health.py +489 -0
- ccproxy/api/routes/metrics.py +1033 -0
- ccproxy/api/routes/proxy.py +238 -0
- ccproxy/auth/__init__.py +75 -0
- ccproxy/auth/bearer.py +68 -0
- ccproxy/auth/credentials_adapter.py +93 -0
- ccproxy/auth/dependencies.py +229 -0
- ccproxy/auth/exceptions.py +79 -0
- ccproxy/auth/manager.py +102 -0
- ccproxy/auth/models.py +118 -0
- ccproxy/auth/oauth/__init__.py +26 -0
- ccproxy/auth/oauth/models.py +49 -0
- ccproxy/auth/oauth/routes.py +396 -0
- ccproxy/auth/oauth/storage.py +0 -0
- ccproxy/auth/storage/__init__.py +12 -0
- ccproxy/auth/storage/base.py +57 -0
- ccproxy/auth/storage/json_file.py +159 -0
- ccproxy/auth/storage/keyring.py +192 -0
- ccproxy/claude_sdk/__init__.py +20 -0
- ccproxy/claude_sdk/client.py +169 -0
- ccproxy/claude_sdk/converter.py +331 -0
- ccproxy/claude_sdk/options.py +120 -0
- ccproxy/cli/__init__.py +14 -0
- ccproxy/cli/commands/__init__.py +8 -0
- ccproxy/cli/commands/auth.py +553 -0
- ccproxy/cli/commands/config/__init__.py +14 -0
- ccproxy/cli/commands/config/commands.py +766 -0
- ccproxy/cli/commands/config/schema_commands.py +119 -0
- ccproxy/cli/commands/serve.py +630 -0
- ccproxy/cli/docker/__init__.py +34 -0
- ccproxy/cli/docker/adapter_factory.py +157 -0
- ccproxy/cli/docker/params.py +278 -0
- ccproxy/cli/helpers.py +144 -0
- ccproxy/cli/main.py +193 -0
- ccproxy/cli/options/__init__.py +14 -0
- ccproxy/cli/options/claude_options.py +216 -0
- ccproxy/cli/options/core_options.py +40 -0
- ccproxy/cli/options/security_options.py +48 -0
- ccproxy/cli/options/server_options.py +117 -0
- ccproxy/config/__init__.py +40 -0
- ccproxy/config/auth.py +154 -0
- ccproxy/config/claude.py +124 -0
- ccproxy/config/cors.py +79 -0
- ccproxy/config/discovery.py +87 -0
- ccproxy/config/docker_settings.py +265 -0
- ccproxy/config/loader.py +108 -0
- ccproxy/config/observability.py +158 -0
- ccproxy/config/pricing.py +88 -0
- ccproxy/config/reverse_proxy.py +31 -0
- ccproxy/config/scheduler.py +89 -0
- ccproxy/config/security.py +14 -0
- ccproxy/config/server.py +81 -0
- ccproxy/config/settings.py +534 -0
- ccproxy/config/validators.py +231 -0
- ccproxy/core/__init__.py +274 -0
- ccproxy/core/async_utils.py +675 -0
- ccproxy/core/constants.py +97 -0
- ccproxy/core/errors.py +256 -0
- ccproxy/core/http.py +328 -0
- ccproxy/core/http_transformers.py +428 -0
- ccproxy/core/interfaces.py +247 -0
- ccproxy/core/logging.py +189 -0
- ccproxy/core/middleware.py +114 -0
- ccproxy/core/proxy.py +143 -0
- ccproxy/core/system.py +38 -0
- ccproxy/core/transformers.py +259 -0
- ccproxy/core/types.py +129 -0
- ccproxy/core/validators.py +288 -0
- ccproxy/docker/__init__.py +67 -0
- ccproxy/docker/adapter.py +588 -0
- ccproxy/docker/docker_path.py +207 -0
- ccproxy/docker/middleware.py +103 -0
- ccproxy/docker/models.py +228 -0
- ccproxy/docker/protocol.py +192 -0
- ccproxy/docker/stream_process.py +264 -0
- ccproxy/docker/validators.py +173 -0
- ccproxy/models/__init__.py +123 -0
- ccproxy/models/errors.py +42 -0
- ccproxy/models/messages.py +243 -0
- ccproxy/models/requests.py +85 -0
- ccproxy/models/responses.py +227 -0
- ccproxy/models/types.py +102 -0
- ccproxy/observability/__init__.py +51 -0
- ccproxy/observability/access_logger.py +400 -0
- ccproxy/observability/context.py +447 -0
- ccproxy/observability/metrics.py +539 -0
- ccproxy/observability/pushgateway.py +366 -0
- ccproxy/observability/sse_events.py +303 -0
- ccproxy/observability/stats_printer.py +755 -0
- ccproxy/observability/storage/__init__.py +1 -0
- ccproxy/observability/storage/duckdb_simple.py +665 -0
- ccproxy/observability/storage/models.py +55 -0
- ccproxy/pricing/__init__.py +19 -0
- ccproxy/pricing/cache.py +212 -0
- ccproxy/pricing/loader.py +267 -0
- ccproxy/pricing/models.py +106 -0
- ccproxy/pricing/updater.py +309 -0
- ccproxy/scheduler/__init__.py +39 -0
- ccproxy/scheduler/core.py +335 -0
- ccproxy/scheduler/exceptions.py +34 -0
- ccproxy/scheduler/manager.py +186 -0
- ccproxy/scheduler/registry.py +150 -0
- ccproxy/scheduler/tasks.py +484 -0
- ccproxy/services/__init__.py +10 -0
- ccproxy/services/claude_sdk_service.py +614 -0
- ccproxy/services/credentials/__init__.py +55 -0
- ccproxy/services/credentials/config.py +105 -0
- ccproxy/services/credentials/manager.py +562 -0
- ccproxy/services/credentials/oauth_client.py +482 -0
- ccproxy/services/proxy_service.py +1536 -0
- ccproxy/static/.keep +0 -0
- ccproxy/testing/__init__.py +34 -0
- ccproxy/testing/config.py +148 -0
- ccproxy/testing/content_generation.py +197 -0
- ccproxy/testing/mock_responses.py +262 -0
- ccproxy/testing/response_handlers.py +161 -0
- ccproxy/testing/scenarios.py +241 -0
- ccproxy/utils/__init__.py +6 -0
- ccproxy/utils/cost_calculator.py +210 -0
- ccproxy/utils/streaming_metrics.py +199 -0
- ccproxy_api-0.1.0.dist-info/METADATA +253 -0
- ccproxy_api-0.1.0.dist-info/RECORD +148 -0
- ccproxy_api-0.1.0.dist-info/WHEEL +4 -0
- ccproxy_api-0.1.0.dist-info/entry_points.txt +2 -0
- ccproxy_api-0.1.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
"""Shared dependencies for CCProxy API Server."""
|
|
2
|
+
|
|
3
|
+
from typing import Annotated
|
|
4
|
+
|
|
5
|
+
from fastapi import Depends, Request
|
|
6
|
+
from structlog import get_logger
|
|
7
|
+
|
|
8
|
+
from ccproxy.auth.dependencies import AuthManagerDep, get_auth_manager
|
|
9
|
+
from ccproxy.config.settings import Settings, get_settings
|
|
10
|
+
from ccproxy.core.http import BaseProxyClient
|
|
11
|
+
from ccproxy.observability import PrometheusMetrics, get_metrics
|
|
12
|
+
from ccproxy.observability.storage.duckdb_simple import SimpleDuckDBStorage
|
|
13
|
+
from ccproxy.services.claude_sdk_service import ClaudeSDKService
|
|
14
|
+
from ccproxy.services.credentials.manager import CredentialsManager
|
|
15
|
+
from ccproxy.services.proxy_service import ProxyService
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
logger = get_logger(__name__)
|
|
19
|
+
|
|
20
|
+
# Type aliases for dependency injection
|
|
21
|
+
SettingsDep = Annotated[Settings, Depends(get_settings)]
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def get_claude_service(
|
|
25
|
+
auth_manager: AuthManagerDep,
|
|
26
|
+
) -> ClaudeSDKService:
|
|
27
|
+
"""Get Claude SDK service instance.
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
auth_manager: Authentication manager dependency
|
|
31
|
+
|
|
32
|
+
Returns:
|
|
33
|
+
Claude SDK service instance
|
|
34
|
+
"""
|
|
35
|
+
logger.debug("Creating Claude SDK service instance")
|
|
36
|
+
# Get global metrics instance
|
|
37
|
+
metrics = get_metrics()
|
|
38
|
+
|
|
39
|
+
return ClaudeSDKService(
|
|
40
|
+
auth_manager=auth_manager,
|
|
41
|
+
metrics=metrics,
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def get_credentials_manager(
|
|
46
|
+
settings: SettingsDep,
|
|
47
|
+
) -> CredentialsManager:
|
|
48
|
+
"""Get credentials manager instance.
|
|
49
|
+
|
|
50
|
+
Args:
|
|
51
|
+
settings: Application settings dependency
|
|
52
|
+
|
|
53
|
+
Returns:
|
|
54
|
+
Credentials manager instance
|
|
55
|
+
"""
|
|
56
|
+
logger.debug("Creating credentials manager instance")
|
|
57
|
+
return CredentialsManager(config=settings.auth)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def get_proxy_service(
|
|
61
|
+
settings: SettingsDep,
|
|
62
|
+
credentials_manager: Annotated[
|
|
63
|
+
CredentialsManager, Depends(get_credentials_manager)
|
|
64
|
+
],
|
|
65
|
+
) -> ProxyService:
|
|
66
|
+
"""Get proxy service instance.
|
|
67
|
+
|
|
68
|
+
Args:
|
|
69
|
+
settings: Application settings dependency
|
|
70
|
+
credentials_manager: Credentials manager dependency
|
|
71
|
+
|
|
72
|
+
Returns:
|
|
73
|
+
Proxy service instance
|
|
74
|
+
"""
|
|
75
|
+
logger.debug("Creating proxy service instance")
|
|
76
|
+
# Create HTTP client for proxy
|
|
77
|
+
from ccproxy.core.http import HTTPXClient
|
|
78
|
+
|
|
79
|
+
http_client = HTTPXClient()
|
|
80
|
+
proxy_client = BaseProxyClient(http_client)
|
|
81
|
+
|
|
82
|
+
# Get global metrics instance
|
|
83
|
+
metrics = get_metrics()
|
|
84
|
+
|
|
85
|
+
return ProxyService(
|
|
86
|
+
proxy_client=proxy_client,
|
|
87
|
+
credentials_manager=credentials_manager,
|
|
88
|
+
settings=settings,
|
|
89
|
+
proxy_mode="full",
|
|
90
|
+
target_base_url=settings.reverse_proxy.target_url,
|
|
91
|
+
metrics=metrics,
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def get_observability_metrics() -> PrometheusMetrics:
|
|
96
|
+
"""Get observability metrics instance.
|
|
97
|
+
|
|
98
|
+
Returns:
|
|
99
|
+
PrometheusMetrics instance
|
|
100
|
+
"""
|
|
101
|
+
logger.debug("Getting observability metrics instance")
|
|
102
|
+
return get_metrics()
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
async def get_log_storage(request: Request) -> SimpleDuckDBStorage | None:
|
|
106
|
+
"""Get log storage from app state.
|
|
107
|
+
|
|
108
|
+
Args:
|
|
109
|
+
request: FastAPI request object
|
|
110
|
+
|
|
111
|
+
Returns:
|
|
112
|
+
SimpleDuckDBStorage instance if available, None otherwise
|
|
113
|
+
"""
|
|
114
|
+
return getattr(request.app.state, "log_storage", None)
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
async def get_duckdb_storage(request: Request) -> SimpleDuckDBStorage | None:
|
|
118
|
+
"""Get DuckDB storage from app state (backward compatibility).
|
|
119
|
+
|
|
120
|
+
Args:
|
|
121
|
+
request: FastAPI request object
|
|
122
|
+
|
|
123
|
+
Returns:
|
|
124
|
+
SimpleDuckDBStorage instance if available, None otherwise
|
|
125
|
+
"""
|
|
126
|
+
# Try new name first, then fall back to old name for backward compatibility
|
|
127
|
+
storage = getattr(request.app.state, "log_storage", None)
|
|
128
|
+
if storage is None:
|
|
129
|
+
storage = getattr(request.app.state, "duckdb_storage", None)
|
|
130
|
+
return storage
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
# Type aliases for service dependencies
|
|
134
|
+
ClaudeServiceDep = Annotated[ClaudeSDKService, Depends(get_claude_service)]
|
|
135
|
+
ProxyServiceDep = Annotated[ProxyService, Depends(get_proxy_service)]
|
|
136
|
+
ObservabilityMetricsDep = Annotated[
|
|
137
|
+
PrometheusMetrics, Depends(get_observability_metrics)
|
|
138
|
+
]
|
|
139
|
+
LogStorageDep = Annotated[SimpleDuckDBStorage | None, Depends(get_log_storage)]
|
|
140
|
+
DuckDBStorageDep = Annotated[SimpleDuckDBStorage | None, Depends(get_duckdb_storage)]
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"""API middleware for CCProxy API Server."""
|
|
2
|
+
|
|
3
|
+
from ccproxy.api.middleware.cors import get_cors_config, setup_cors_middleware
|
|
4
|
+
from ccproxy.api.middleware.errors import setup_error_handlers
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
__all__ = [
|
|
8
|
+
"setup_cors_middleware",
|
|
9
|
+
"get_cors_config",
|
|
10
|
+
"setup_error_handlers",
|
|
11
|
+
]
|
|
File without changes
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"""CORS middleware for CCProxy API Server."""
|
|
2
|
+
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
from fastapi import FastAPI
|
|
6
|
+
from fastapi.middleware.cors import CORSMiddleware
|
|
7
|
+
from structlog import get_logger
|
|
8
|
+
|
|
9
|
+
from ccproxy.config.settings import Settings
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
logger = get_logger(__name__)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def setup_cors_middleware(app: FastAPI, settings: Settings) -> None:
|
|
16
|
+
"""Setup CORS middleware for the FastAPI application.
|
|
17
|
+
|
|
18
|
+
Args:
|
|
19
|
+
app: FastAPI application instance
|
|
20
|
+
settings: Application settings containing CORS configuration
|
|
21
|
+
"""
|
|
22
|
+
logger.debug("cors_middleware_setup_start")
|
|
23
|
+
|
|
24
|
+
app.add_middleware(
|
|
25
|
+
CORSMiddleware,
|
|
26
|
+
allow_origins=settings.cors.origins,
|
|
27
|
+
allow_credentials=settings.cors.credentials,
|
|
28
|
+
allow_methods=settings.cors.methods,
|
|
29
|
+
allow_headers=settings.cors.headers,
|
|
30
|
+
allow_origin_regex=settings.cors.origin_regex,
|
|
31
|
+
expose_headers=settings.cors.expose_headers,
|
|
32
|
+
max_age=settings.cors.max_age,
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
logger.debug("cors_middleware_configured", origins=settings.cors.origins)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def get_cors_config(settings: Settings) -> dict[str, Any]:
|
|
39
|
+
"""Get CORS configuration dictionary.
|
|
40
|
+
|
|
41
|
+
Args:
|
|
42
|
+
settings: Application settings containing CORS configuration
|
|
43
|
+
|
|
44
|
+
Returns:
|
|
45
|
+
Dictionary containing CORS configuration
|
|
46
|
+
"""
|
|
47
|
+
return {
|
|
48
|
+
"allow_origins": settings.cors.origins,
|
|
49
|
+
"allow_credentials": settings.cors.credentials,
|
|
50
|
+
"allow_methods": settings.cors.methods,
|
|
51
|
+
"allow_headers": settings.cors.headers,
|
|
52
|
+
"allow_origin_regex": settings.cors.origin_regex,
|
|
53
|
+
"expose_headers": settings.cors.expose_headers,
|
|
54
|
+
"max_age": settings.cors.max_age,
|
|
55
|
+
}
|