ccproxy-api 0.1.6__py3-none-any.whl → 0.2.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/api/__init__.py +1 -15
- ccproxy/api/app.py +439 -212
- ccproxy/api/bootstrap.py +30 -0
- ccproxy/api/decorators.py +85 -0
- ccproxy/api/dependencies.py +145 -176
- ccproxy/api/format_validation.py +54 -0
- ccproxy/api/middleware/cors.py +6 -3
- ccproxy/api/middleware/errors.py +402 -530
- ccproxy/api/middleware/hooks.py +563 -0
- ccproxy/api/middleware/normalize_headers.py +59 -0
- ccproxy/api/middleware/request_id.py +35 -16
- ccproxy/api/middleware/streaming_hooks.py +292 -0
- ccproxy/api/routes/__init__.py +5 -14
- ccproxy/api/routes/health.py +39 -672
- ccproxy/api/routes/plugins.py +277 -0
- ccproxy/auth/__init__.py +2 -19
- ccproxy/auth/bearer.py +25 -15
- ccproxy/auth/dependencies.py +123 -157
- ccproxy/auth/exceptions.py +0 -12
- ccproxy/auth/manager.py +35 -49
- ccproxy/auth/managers/__init__.py +10 -0
- ccproxy/auth/managers/base.py +523 -0
- ccproxy/auth/managers/base_enhanced.py +63 -0
- ccproxy/auth/managers/token_snapshot.py +77 -0
- ccproxy/auth/models/base.py +65 -0
- ccproxy/auth/models/credentials.py +40 -0
- ccproxy/auth/oauth/__init__.py +4 -18
- ccproxy/auth/oauth/base.py +533 -0
- ccproxy/auth/oauth/cli_errors.py +37 -0
- ccproxy/auth/oauth/flows.py +430 -0
- ccproxy/auth/oauth/protocol.py +366 -0
- ccproxy/auth/oauth/registry.py +408 -0
- ccproxy/auth/oauth/router.py +396 -0
- ccproxy/auth/oauth/routes.py +186 -113
- ccproxy/auth/oauth/session.py +151 -0
- ccproxy/auth/oauth/templates.py +342 -0
- ccproxy/auth/storage/__init__.py +2 -5
- ccproxy/auth/storage/base.py +279 -5
- ccproxy/auth/storage/generic.py +134 -0
- ccproxy/cli/__init__.py +1 -2
- ccproxy/cli/_settings_help.py +351 -0
- ccproxy/cli/commands/auth.py +1519 -793
- ccproxy/cli/commands/config/commands.py +209 -276
- ccproxy/cli/commands/plugins.py +669 -0
- ccproxy/cli/commands/serve.py +75 -810
- ccproxy/cli/commands/status.py +254 -0
- ccproxy/cli/decorators.py +83 -0
- ccproxy/cli/helpers.py +22 -60
- ccproxy/cli/main.py +359 -10
- ccproxy/cli/options/claude_options.py +0 -25
- ccproxy/config/__init__.py +7 -11
- ccproxy/config/core.py +227 -0
- ccproxy/config/env_generator.py +232 -0
- ccproxy/config/runtime.py +67 -0
- ccproxy/config/security.py +36 -3
- ccproxy/config/settings.py +382 -441
- ccproxy/config/toml_generator.py +299 -0
- ccproxy/config/utils.py +452 -0
- ccproxy/core/__init__.py +7 -271
- ccproxy/{_version.py → core/_version.py} +16 -3
- ccproxy/core/async_task_manager.py +516 -0
- ccproxy/core/async_utils.py +47 -14
- ccproxy/core/auth/__init__.py +6 -0
- ccproxy/core/constants.py +16 -50
- ccproxy/core/errors.py +53 -0
- ccproxy/core/id_utils.py +20 -0
- ccproxy/core/interfaces.py +16 -123
- ccproxy/core/logging.py +473 -18
- ccproxy/core/plugins/__init__.py +77 -0
- ccproxy/core/plugins/cli_discovery.py +211 -0
- ccproxy/core/plugins/declaration.py +455 -0
- ccproxy/core/plugins/discovery.py +604 -0
- ccproxy/core/plugins/factories.py +967 -0
- ccproxy/core/plugins/hooks/__init__.py +30 -0
- ccproxy/core/plugins/hooks/base.py +58 -0
- ccproxy/core/plugins/hooks/events.py +46 -0
- ccproxy/core/plugins/hooks/implementations/__init__.py +16 -0
- ccproxy/core/plugins/hooks/implementations/formatters/__init__.py +11 -0
- ccproxy/core/plugins/hooks/implementations/formatters/json.py +552 -0
- ccproxy/core/plugins/hooks/implementations/formatters/raw.py +370 -0
- ccproxy/core/plugins/hooks/implementations/http_tracer.py +431 -0
- ccproxy/core/plugins/hooks/layers.py +44 -0
- ccproxy/core/plugins/hooks/manager.py +186 -0
- ccproxy/core/plugins/hooks/registry.py +139 -0
- ccproxy/core/plugins/hooks/thread_manager.py +203 -0
- ccproxy/core/plugins/hooks/types.py +22 -0
- ccproxy/core/plugins/interfaces.py +416 -0
- ccproxy/core/plugins/loader.py +166 -0
- ccproxy/core/plugins/middleware.py +233 -0
- ccproxy/core/plugins/models.py +59 -0
- ccproxy/core/plugins/protocol.py +180 -0
- ccproxy/core/plugins/runtime.py +519 -0
- ccproxy/{observability/context.py → core/request_context.py} +137 -94
- ccproxy/core/status_report.py +211 -0
- ccproxy/core/transformers.py +13 -8
- ccproxy/data/claude_headers_fallback.json +558 -0
- ccproxy/data/codex_headers_fallback.json +121 -0
- ccproxy/http/__init__.py +30 -0
- ccproxy/http/base.py +95 -0
- ccproxy/http/client.py +323 -0
- ccproxy/http/hooks.py +642 -0
- ccproxy/http/pool.py +279 -0
- ccproxy/llms/formatters/__init__.py +7 -0
- ccproxy/llms/formatters/anthropic_to_openai/__init__.py +55 -0
- ccproxy/llms/formatters/anthropic_to_openai/errors.py +65 -0
- ccproxy/llms/formatters/anthropic_to_openai/requests.py +356 -0
- ccproxy/llms/formatters/anthropic_to_openai/responses.py +153 -0
- ccproxy/llms/formatters/anthropic_to_openai/streams.py +1546 -0
- ccproxy/llms/formatters/base.py +140 -0
- ccproxy/llms/formatters/base_model.py +33 -0
- ccproxy/llms/formatters/common/__init__.py +51 -0
- ccproxy/llms/formatters/common/identifiers.py +48 -0
- ccproxy/llms/formatters/common/streams.py +254 -0
- ccproxy/llms/formatters/common/thinking.py +74 -0
- ccproxy/llms/formatters/common/usage.py +135 -0
- ccproxy/llms/formatters/constants.py +55 -0
- ccproxy/llms/formatters/context.py +116 -0
- ccproxy/llms/formatters/mapping.py +33 -0
- ccproxy/llms/formatters/openai_to_anthropic/__init__.py +55 -0
- ccproxy/llms/formatters/openai_to_anthropic/_helpers.py +141 -0
- ccproxy/llms/formatters/openai_to_anthropic/errors.py +53 -0
- ccproxy/llms/formatters/openai_to_anthropic/requests.py +674 -0
- ccproxy/llms/formatters/openai_to_anthropic/responses.py +285 -0
- ccproxy/llms/formatters/openai_to_anthropic/streams.py +530 -0
- ccproxy/llms/formatters/openai_to_openai/__init__.py +53 -0
- ccproxy/llms/formatters/openai_to_openai/_helpers.py +325 -0
- ccproxy/llms/formatters/openai_to_openai/errors.py +6 -0
- ccproxy/llms/formatters/openai_to_openai/requests.py +388 -0
- ccproxy/llms/formatters/openai_to_openai/responses.py +594 -0
- ccproxy/llms/formatters/openai_to_openai/streams.py +1832 -0
- ccproxy/llms/formatters/utils.py +306 -0
- ccproxy/llms/models/__init__.py +9 -0
- ccproxy/llms/models/anthropic.py +619 -0
- ccproxy/llms/models/openai.py +844 -0
- ccproxy/llms/streaming/__init__.py +26 -0
- ccproxy/llms/streaming/accumulators.py +1074 -0
- ccproxy/llms/streaming/formatters.py +251 -0
- ccproxy/{adapters/openai/streaming.py → llms/streaming/processors.py} +193 -240
- ccproxy/models/__init__.py +8 -159
- ccproxy/models/detection.py +92 -193
- ccproxy/models/provider.py +75 -0
- ccproxy/plugins/access_log/README.md +32 -0
- ccproxy/plugins/access_log/__init__.py +20 -0
- ccproxy/plugins/access_log/config.py +33 -0
- ccproxy/plugins/access_log/formatter.py +126 -0
- ccproxy/plugins/access_log/hook.py +763 -0
- ccproxy/plugins/access_log/logger.py +254 -0
- ccproxy/plugins/access_log/plugin.py +137 -0
- ccproxy/plugins/access_log/writer.py +109 -0
- ccproxy/plugins/analytics/README.md +24 -0
- ccproxy/plugins/analytics/__init__.py +1 -0
- ccproxy/plugins/analytics/config.py +5 -0
- ccproxy/plugins/analytics/ingest.py +85 -0
- ccproxy/plugins/analytics/models.py +97 -0
- ccproxy/plugins/analytics/plugin.py +121 -0
- ccproxy/plugins/analytics/routes.py +163 -0
- ccproxy/plugins/analytics/service.py +284 -0
- ccproxy/plugins/claude_api/README.md +29 -0
- ccproxy/plugins/claude_api/__init__.py +10 -0
- ccproxy/plugins/claude_api/adapter.py +829 -0
- ccproxy/plugins/claude_api/config.py +52 -0
- ccproxy/plugins/claude_api/detection_service.py +461 -0
- ccproxy/plugins/claude_api/health.py +175 -0
- ccproxy/plugins/claude_api/hooks.py +284 -0
- ccproxy/plugins/claude_api/models.py +256 -0
- ccproxy/plugins/claude_api/plugin.py +298 -0
- ccproxy/plugins/claude_api/routes.py +118 -0
- ccproxy/plugins/claude_api/streaming_metrics.py +68 -0
- ccproxy/plugins/claude_api/tasks.py +84 -0
- ccproxy/plugins/claude_sdk/README.md +35 -0
- ccproxy/plugins/claude_sdk/__init__.py +80 -0
- ccproxy/plugins/claude_sdk/adapter.py +749 -0
- ccproxy/plugins/claude_sdk/auth.py +57 -0
- ccproxy/{claude_sdk → plugins/claude_sdk}/client.py +63 -39
- ccproxy/plugins/claude_sdk/config.py +210 -0
- ccproxy/{claude_sdk → plugins/claude_sdk}/converter.py +6 -6
- ccproxy/plugins/claude_sdk/detection_service.py +163 -0
- ccproxy/{services/claude_sdk_service.py → plugins/claude_sdk/handler.py} +123 -304
- ccproxy/plugins/claude_sdk/health.py +113 -0
- ccproxy/plugins/claude_sdk/hooks.py +115 -0
- ccproxy/{claude_sdk → plugins/claude_sdk}/manager.py +42 -32
- ccproxy/{claude_sdk → plugins/claude_sdk}/message_queue.py +8 -8
- ccproxy/{models/claude_sdk.py → plugins/claude_sdk/models.py} +64 -16
- ccproxy/plugins/claude_sdk/options.py +154 -0
- ccproxy/{claude_sdk → plugins/claude_sdk}/parser.py +23 -5
- ccproxy/plugins/claude_sdk/plugin.py +269 -0
- ccproxy/plugins/claude_sdk/routes.py +104 -0
- ccproxy/{claude_sdk → plugins/claude_sdk}/session_client.py +124 -12
- ccproxy/plugins/claude_sdk/session_pool.py +700 -0
- ccproxy/{claude_sdk → plugins/claude_sdk}/stream_handle.py +48 -43
- ccproxy/{claude_sdk → plugins/claude_sdk}/stream_worker.py +22 -18
- ccproxy/{claude_sdk → plugins/claude_sdk}/streaming.py +50 -16
- ccproxy/plugins/claude_sdk/tasks.py +97 -0
- ccproxy/plugins/claude_shared/README.md +18 -0
- ccproxy/plugins/claude_shared/__init__.py +12 -0
- ccproxy/plugins/claude_shared/model_defaults.py +171 -0
- ccproxy/plugins/codex/README.md +35 -0
- ccproxy/plugins/codex/__init__.py +6 -0
- ccproxy/plugins/codex/adapter.py +635 -0
- ccproxy/{config/codex.py → plugins/codex/config.py} +78 -12
- ccproxy/plugins/codex/detection_service.py +544 -0
- ccproxy/plugins/codex/health.py +162 -0
- ccproxy/plugins/codex/hooks.py +263 -0
- ccproxy/plugins/codex/model_defaults.py +39 -0
- ccproxy/plugins/codex/models.py +263 -0
- ccproxy/plugins/codex/plugin.py +275 -0
- ccproxy/plugins/codex/routes.py +129 -0
- ccproxy/plugins/codex/streaming_metrics.py +324 -0
- ccproxy/plugins/codex/tasks.py +106 -0
- ccproxy/plugins/codex/utils/__init__.py +1 -0
- ccproxy/plugins/codex/utils/sse_parser.py +106 -0
- ccproxy/plugins/command_replay/README.md +34 -0
- ccproxy/plugins/command_replay/__init__.py +17 -0
- ccproxy/plugins/command_replay/config.py +133 -0
- ccproxy/plugins/command_replay/formatter.py +432 -0
- ccproxy/plugins/command_replay/hook.py +294 -0
- ccproxy/plugins/command_replay/plugin.py +161 -0
- ccproxy/plugins/copilot/README.md +39 -0
- ccproxy/plugins/copilot/__init__.py +11 -0
- ccproxy/plugins/copilot/adapter.py +465 -0
- ccproxy/plugins/copilot/config.py +155 -0
- ccproxy/plugins/copilot/data/copilot_fallback.json +41 -0
- ccproxy/plugins/copilot/detection_service.py +255 -0
- ccproxy/plugins/copilot/manager.py +275 -0
- ccproxy/plugins/copilot/model_defaults.py +284 -0
- ccproxy/plugins/copilot/models.py +148 -0
- ccproxy/plugins/copilot/oauth/__init__.py +16 -0
- ccproxy/plugins/copilot/oauth/client.py +494 -0
- ccproxy/plugins/copilot/oauth/models.py +385 -0
- ccproxy/plugins/copilot/oauth/provider.py +602 -0
- ccproxy/plugins/copilot/oauth/storage.py +170 -0
- ccproxy/plugins/copilot/plugin.py +360 -0
- ccproxy/plugins/copilot/routes.py +294 -0
- ccproxy/plugins/credential_balancer/README.md +124 -0
- ccproxy/plugins/credential_balancer/__init__.py +6 -0
- ccproxy/plugins/credential_balancer/config.py +270 -0
- ccproxy/plugins/credential_balancer/factory.py +415 -0
- ccproxy/plugins/credential_balancer/hook.py +51 -0
- ccproxy/plugins/credential_balancer/manager.py +587 -0
- ccproxy/plugins/credential_balancer/plugin.py +146 -0
- ccproxy/plugins/dashboard/README.md +25 -0
- ccproxy/plugins/dashboard/__init__.py +1 -0
- ccproxy/plugins/dashboard/config.py +8 -0
- ccproxy/plugins/dashboard/plugin.py +71 -0
- ccproxy/plugins/dashboard/routes.py +67 -0
- ccproxy/plugins/docker/README.md +32 -0
- ccproxy/{docker → plugins/docker}/__init__.py +3 -0
- ccproxy/{docker → plugins/docker}/adapter.py +108 -10
- ccproxy/plugins/docker/config.py +82 -0
- ccproxy/{docker → plugins/docker}/docker_path.py +4 -3
- ccproxy/{docker → plugins/docker}/middleware.py +2 -2
- ccproxy/plugins/docker/plugin.py +198 -0
- ccproxy/{docker → plugins/docker}/stream_process.py +3 -3
- ccproxy/plugins/duckdb_storage/README.md +26 -0
- ccproxy/plugins/duckdb_storage/__init__.py +1 -0
- ccproxy/plugins/duckdb_storage/config.py +22 -0
- ccproxy/plugins/duckdb_storage/plugin.py +128 -0
- ccproxy/plugins/duckdb_storage/routes.py +51 -0
- ccproxy/plugins/duckdb_storage/storage.py +633 -0
- ccproxy/plugins/max_tokens/README.md +38 -0
- ccproxy/plugins/max_tokens/__init__.py +12 -0
- ccproxy/plugins/max_tokens/adapter.py +235 -0
- ccproxy/plugins/max_tokens/config.py +86 -0
- ccproxy/plugins/max_tokens/models.py +53 -0
- ccproxy/plugins/max_tokens/plugin.py +200 -0
- ccproxy/plugins/max_tokens/service.py +271 -0
- ccproxy/plugins/max_tokens/token_limits.json +54 -0
- ccproxy/plugins/metrics/README.md +35 -0
- ccproxy/plugins/metrics/__init__.py +10 -0
- ccproxy/{observability/metrics.py → plugins/metrics/collector.py} +20 -153
- ccproxy/plugins/metrics/config.py +85 -0
- ccproxy/plugins/metrics/grafana/dashboards/ccproxy-dashboard.json +1720 -0
- ccproxy/plugins/metrics/hook.py +403 -0
- ccproxy/plugins/metrics/plugin.py +268 -0
- ccproxy/{observability → plugins/metrics}/pushgateway.py +57 -59
- ccproxy/plugins/metrics/routes.py +107 -0
- ccproxy/plugins/metrics/tasks.py +117 -0
- ccproxy/plugins/oauth_claude/README.md +35 -0
- ccproxy/plugins/oauth_claude/__init__.py +14 -0
- ccproxy/plugins/oauth_claude/client.py +270 -0
- ccproxy/plugins/oauth_claude/config.py +84 -0
- ccproxy/plugins/oauth_claude/manager.py +482 -0
- ccproxy/plugins/oauth_claude/models.py +266 -0
- ccproxy/plugins/oauth_claude/plugin.py +149 -0
- ccproxy/plugins/oauth_claude/provider.py +571 -0
- ccproxy/plugins/oauth_claude/storage.py +212 -0
- ccproxy/plugins/oauth_codex/README.md +38 -0
- ccproxy/plugins/oauth_codex/__init__.py +14 -0
- ccproxy/plugins/oauth_codex/client.py +224 -0
- ccproxy/plugins/oauth_codex/config.py +95 -0
- ccproxy/plugins/oauth_codex/manager.py +256 -0
- ccproxy/plugins/oauth_codex/models.py +239 -0
- ccproxy/plugins/oauth_codex/plugin.py +146 -0
- ccproxy/plugins/oauth_codex/provider.py +574 -0
- ccproxy/plugins/oauth_codex/storage.py +92 -0
- ccproxy/plugins/permissions/README.md +28 -0
- ccproxy/plugins/permissions/__init__.py +22 -0
- ccproxy/plugins/permissions/config.py +28 -0
- ccproxy/{cli/commands/permission_handler.py → plugins/permissions/handlers/cli.py} +49 -25
- ccproxy/plugins/permissions/handlers/protocol.py +33 -0
- ccproxy/plugins/permissions/handlers/terminal.py +675 -0
- ccproxy/{api/routes → plugins/permissions}/mcp.py +34 -7
- ccproxy/{models/permissions.py → plugins/permissions/models.py} +65 -1
- ccproxy/plugins/permissions/plugin.py +153 -0
- ccproxy/{api/routes/permissions.py → plugins/permissions/routes.py} +20 -16
- ccproxy/{api/services/permission_service.py → plugins/permissions/service.py} +65 -11
- ccproxy/{api → plugins/permissions}/ui/permission_handler_protocol.py +1 -1
- ccproxy/{api → plugins/permissions}/ui/terminal_permission_handler.py +66 -10
- ccproxy/plugins/pricing/README.md +34 -0
- ccproxy/plugins/pricing/__init__.py +6 -0
- ccproxy/{pricing → plugins/pricing}/cache.py +7 -6
- ccproxy/{config/pricing.py → plugins/pricing/config.py} +32 -6
- ccproxy/plugins/pricing/exceptions.py +35 -0
- ccproxy/plugins/pricing/loader.py +440 -0
- ccproxy/{pricing → plugins/pricing}/models.py +13 -23
- ccproxy/plugins/pricing/plugin.py +169 -0
- ccproxy/plugins/pricing/service.py +191 -0
- ccproxy/plugins/pricing/tasks.py +300 -0
- ccproxy/{pricing → plugins/pricing}/updater.py +86 -72
- ccproxy/plugins/pricing/utils.py +99 -0
- ccproxy/plugins/request_tracer/README.md +40 -0
- ccproxy/plugins/request_tracer/__init__.py +7 -0
- ccproxy/plugins/request_tracer/config.py +120 -0
- ccproxy/plugins/request_tracer/hook.py +415 -0
- ccproxy/plugins/request_tracer/plugin.py +255 -0
- ccproxy/scheduler/__init__.py +2 -14
- ccproxy/scheduler/core.py +26 -41
- ccproxy/scheduler/manager.py +63 -107
- ccproxy/scheduler/registry.py +6 -32
- ccproxy/scheduler/tasks.py +346 -314
- ccproxy/services/__init__.py +0 -1
- ccproxy/services/adapters/__init__.py +11 -0
- ccproxy/services/adapters/base.py +123 -0
- ccproxy/services/adapters/chain_composer.py +88 -0
- ccproxy/services/adapters/chain_validation.py +44 -0
- ccproxy/services/adapters/chat_accumulator.py +200 -0
- ccproxy/services/adapters/delta_utils.py +142 -0
- ccproxy/services/adapters/format_adapter.py +136 -0
- ccproxy/services/adapters/format_context.py +11 -0
- ccproxy/services/adapters/format_registry.py +158 -0
- ccproxy/services/adapters/http_adapter.py +1045 -0
- ccproxy/services/adapters/mock_adapter.py +118 -0
- ccproxy/services/adapters/protocols.py +35 -0
- ccproxy/services/adapters/simple_converters.py +571 -0
- ccproxy/services/auth_registry.py +180 -0
- ccproxy/services/cache/__init__.py +6 -0
- ccproxy/services/cache/response_cache.py +261 -0
- ccproxy/services/cli_detection.py +437 -0
- ccproxy/services/config/__init__.py +6 -0
- ccproxy/services/config/proxy_configuration.py +111 -0
- ccproxy/services/container.py +256 -0
- ccproxy/services/factories.py +380 -0
- ccproxy/services/handler_config.py +76 -0
- ccproxy/services/interfaces.py +298 -0
- ccproxy/services/mocking/__init__.py +6 -0
- ccproxy/services/mocking/mock_handler.py +291 -0
- ccproxy/services/tracing/__init__.py +7 -0
- ccproxy/services/tracing/interfaces.py +61 -0
- ccproxy/services/tracing/null_tracer.py +57 -0
- ccproxy/streaming/__init__.py +23 -0
- ccproxy/streaming/buffer.py +1056 -0
- ccproxy/streaming/deferred.py +897 -0
- ccproxy/streaming/handler.py +117 -0
- ccproxy/streaming/interfaces.py +77 -0
- ccproxy/streaming/simple_adapter.py +39 -0
- ccproxy/streaming/sse.py +109 -0
- ccproxy/streaming/sse_parser.py +127 -0
- ccproxy/templates/__init__.py +6 -0
- ccproxy/templates/plugin_scaffold.py +695 -0
- ccproxy/testing/endpoints/__init__.py +33 -0
- ccproxy/testing/endpoints/cli.py +215 -0
- ccproxy/testing/endpoints/config.py +874 -0
- ccproxy/testing/endpoints/console.py +57 -0
- ccproxy/testing/endpoints/models.py +100 -0
- ccproxy/testing/endpoints/runner.py +1903 -0
- ccproxy/testing/endpoints/tools.py +308 -0
- ccproxy/testing/mock_responses.py +70 -1
- ccproxy/testing/response_handlers.py +20 -0
- ccproxy/utils/__init__.py +0 -6
- ccproxy/utils/binary_resolver.py +476 -0
- ccproxy/utils/caching.py +327 -0
- ccproxy/utils/cli_logging.py +101 -0
- ccproxy/utils/command_line.py +251 -0
- ccproxy/utils/headers.py +228 -0
- ccproxy/utils/model_mapper.py +120 -0
- ccproxy/utils/startup_helpers.py +95 -342
- ccproxy/utils/version_checker.py +279 -6
- ccproxy_api-0.2.0.dist-info/METADATA +212 -0
- ccproxy_api-0.2.0.dist-info/RECORD +417 -0
- {ccproxy_api-0.1.6.dist-info → ccproxy_api-0.2.0.dist-info}/WHEEL +1 -1
- ccproxy_api-0.2.0.dist-info/entry_points.txt +24 -0
- ccproxy/__init__.py +0 -4
- ccproxy/adapters/__init__.py +0 -11
- ccproxy/adapters/base.py +0 -80
- ccproxy/adapters/codex/__init__.py +0 -11
- ccproxy/adapters/openai/__init__.py +0 -42
- ccproxy/adapters/openai/adapter.py +0 -953
- ccproxy/adapters/openai/models.py +0 -412
- ccproxy/adapters/openai/response_adapter.py +0 -355
- ccproxy/adapters/openai/response_models.py +0 -178
- ccproxy/api/middleware/headers.py +0 -49
- ccproxy/api/middleware/logging.py +0 -180
- ccproxy/api/middleware/request_content_logging.py +0 -297
- ccproxy/api/middleware/server_header.py +0 -58
- ccproxy/api/responses.py +0 -89
- ccproxy/api/routes/claude.py +0 -371
- ccproxy/api/routes/codex.py +0 -1231
- ccproxy/api/routes/metrics.py +0 -1029
- ccproxy/api/routes/proxy.py +0 -211
- ccproxy/api/services/__init__.py +0 -6
- ccproxy/auth/conditional.py +0 -84
- ccproxy/auth/credentials_adapter.py +0 -93
- ccproxy/auth/models.py +0 -118
- ccproxy/auth/oauth/models.py +0 -48
- ccproxy/auth/openai/__init__.py +0 -13
- ccproxy/auth/openai/credentials.py +0 -166
- ccproxy/auth/openai/oauth_client.py +0 -334
- ccproxy/auth/openai/storage.py +0 -184
- ccproxy/auth/storage/json_file.py +0 -158
- ccproxy/auth/storage/keyring.py +0 -189
- ccproxy/claude_sdk/__init__.py +0 -18
- ccproxy/claude_sdk/options.py +0 -194
- ccproxy/claude_sdk/session_pool.py +0 -550
- ccproxy/cli/docker/__init__.py +0 -34
- ccproxy/cli/docker/adapter_factory.py +0 -157
- ccproxy/cli/docker/params.py +0 -274
- ccproxy/config/auth.py +0 -153
- ccproxy/config/claude.py +0 -348
- ccproxy/config/cors.py +0 -79
- ccproxy/config/discovery.py +0 -95
- ccproxy/config/docker_settings.py +0 -264
- ccproxy/config/observability.py +0 -158
- ccproxy/config/reverse_proxy.py +0 -31
- ccproxy/config/scheduler.py +0 -108
- ccproxy/config/server.py +0 -86
- ccproxy/config/validators.py +0 -231
- ccproxy/core/codex_transformers.py +0 -389
- ccproxy/core/http.py +0 -328
- ccproxy/core/http_transformers.py +0 -812
- ccproxy/core/proxy.py +0 -143
- ccproxy/core/validators.py +0 -288
- ccproxy/models/errors.py +0 -42
- ccproxy/models/messages.py +0 -269
- ccproxy/models/requests.py +0 -107
- ccproxy/models/responses.py +0 -270
- ccproxy/models/types.py +0 -102
- ccproxy/observability/__init__.py +0 -51
- ccproxy/observability/access_logger.py +0 -457
- ccproxy/observability/sse_events.py +0 -303
- ccproxy/observability/stats_printer.py +0 -753
- ccproxy/observability/storage/__init__.py +0 -1
- ccproxy/observability/storage/duckdb_simple.py +0 -677
- ccproxy/observability/storage/models.py +0 -70
- ccproxy/observability/streaming_response.py +0 -107
- ccproxy/pricing/__init__.py +0 -19
- ccproxy/pricing/loader.py +0 -251
- ccproxy/services/claude_detection_service.py +0 -269
- ccproxy/services/codex_detection_service.py +0 -263
- ccproxy/services/credentials/__init__.py +0 -55
- ccproxy/services/credentials/config.py +0 -105
- ccproxy/services/credentials/manager.py +0 -561
- ccproxy/services/credentials/oauth_client.py +0 -481
- ccproxy/services/proxy_service.py +0 -1827
- ccproxy/static/.keep +0 -0
- ccproxy/utils/cost_calculator.py +0 -210
- ccproxy/utils/disconnection_monitor.py +0 -83
- ccproxy/utils/model_mapping.py +0 -199
- ccproxy/utils/models_provider.py +0 -150
- ccproxy/utils/simple_request_logger.py +0 -284
- ccproxy/utils/streaming_metrics.py +0 -199
- ccproxy_api-0.1.6.dist-info/METADATA +0 -615
- ccproxy_api-0.1.6.dist-info/RECORD +0 -189
- ccproxy_api-0.1.6.dist-info/entry_points.txt +0 -4
- /ccproxy/{api/middleware/auth.py → auth/models/__init__.py} +0 -0
- /ccproxy/{claude_sdk → plugins/claude_sdk}/exceptions.py +0 -0
- /ccproxy/{docker → plugins/docker}/models.py +0 -0
- /ccproxy/{docker → plugins/docker}/protocol.py +0 -0
- /ccproxy/{docker → plugins/docker}/validators.py +0 -0
- /ccproxy/{auth/oauth/storage.py → plugins/permissions/handlers/__init__.py} +0 -0
- /ccproxy/{api → plugins/permissions}/ui/__init__.py +0 -0
- {ccproxy_api-0.1.6.dist-info → ccproxy_api-0.2.0.dist-info}/licenses/LICENSE +0 -0
ccproxy/core/http.py
DELETED
|
@@ -1,328 +0,0 @@
|
|
|
1
|
-
"""Generic HTTP client abstractions for pure forwarding without business logic."""
|
|
2
|
-
|
|
3
|
-
import os
|
|
4
|
-
from abc import ABC, abstractmethod
|
|
5
|
-
from pathlib import Path
|
|
6
|
-
from typing import TYPE_CHECKING, Any
|
|
7
|
-
|
|
8
|
-
import structlog
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
logger = structlog.get_logger(__name__)
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
if TYPE_CHECKING:
|
|
15
|
-
import httpx
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
class HTTPClient(ABC):
|
|
19
|
-
"""Abstract HTTP client interface for generic HTTP operations."""
|
|
20
|
-
|
|
21
|
-
@abstractmethod
|
|
22
|
-
async def request(
|
|
23
|
-
self,
|
|
24
|
-
method: str,
|
|
25
|
-
url: str,
|
|
26
|
-
headers: dict[str, str],
|
|
27
|
-
body: bytes | None = None,
|
|
28
|
-
timeout: float | None = None,
|
|
29
|
-
) -> tuple[int, dict[str, str], bytes]:
|
|
30
|
-
"""Make an HTTP request.
|
|
31
|
-
|
|
32
|
-
Args:
|
|
33
|
-
method: HTTP method (GET, POST, etc.)
|
|
34
|
-
url: Target URL
|
|
35
|
-
headers: HTTP headers
|
|
36
|
-
body: Request body (optional)
|
|
37
|
-
timeout: Request timeout in seconds (optional)
|
|
38
|
-
|
|
39
|
-
Returns:
|
|
40
|
-
Tuple of (status_code, response_headers, response_body)
|
|
41
|
-
|
|
42
|
-
Raises:
|
|
43
|
-
HTTPError: If the request fails
|
|
44
|
-
"""
|
|
45
|
-
pass
|
|
46
|
-
|
|
47
|
-
@abstractmethod
|
|
48
|
-
async def close(self) -> None:
|
|
49
|
-
"""Close any resources held by the HTTP client."""
|
|
50
|
-
pass
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
class BaseProxyClient:
|
|
54
|
-
"""Generic proxy client with no business logic - pure forwarding."""
|
|
55
|
-
|
|
56
|
-
def __init__(self, http_client: HTTPClient) -> None:
|
|
57
|
-
"""Initialize with an HTTP client.
|
|
58
|
-
|
|
59
|
-
Args:
|
|
60
|
-
http_client: The HTTP client to use for requests
|
|
61
|
-
"""
|
|
62
|
-
self.http_client = http_client
|
|
63
|
-
|
|
64
|
-
async def forward(
|
|
65
|
-
self,
|
|
66
|
-
method: str,
|
|
67
|
-
url: str,
|
|
68
|
-
headers: dict[str, str],
|
|
69
|
-
body: bytes | None = None,
|
|
70
|
-
timeout: float | None = None,
|
|
71
|
-
) -> tuple[int, dict[str, str], bytes]:
|
|
72
|
-
"""Forward an HTTP request without any transformations.
|
|
73
|
-
|
|
74
|
-
Args:
|
|
75
|
-
method: HTTP method
|
|
76
|
-
url: Target URL
|
|
77
|
-
headers: HTTP headers
|
|
78
|
-
body: Request body (optional)
|
|
79
|
-
timeout: Request timeout in seconds (optional)
|
|
80
|
-
|
|
81
|
-
Returns:
|
|
82
|
-
Tuple of (status_code, response_headers, response_body)
|
|
83
|
-
|
|
84
|
-
Raises:
|
|
85
|
-
HTTPError: If the request fails
|
|
86
|
-
"""
|
|
87
|
-
return await self.http_client.request(method, url, headers, body, timeout)
|
|
88
|
-
|
|
89
|
-
async def close(self) -> None:
|
|
90
|
-
"""Close any resources held by the proxy client."""
|
|
91
|
-
await self.http_client.close()
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
class HTTPError(Exception):
|
|
95
|
-
"""Base exception for HTTP client errors."""
|
|
96
|
-
|
|
97
|
-
def __init__(self, message: str, status_code: int | None = None) -> None:
|
|
98
|
-
"""Initialize HTTP error.
|
|
99
|
-
|
|
100
|
-
Args:
|
|
101
|
-
message: Error message
|
|
102
|
-
status_code: HTTP status code (optional)
|
|
103
|
-
"""
|
|
104
|
-
super().__init__(message)
|
|
105
|
-
self.status_code = status_code
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
class HTTPTimeoutError(HTTPError):
|
|
109
|
-
"""Exception raised when HTTP request times out."""
|
|
110
|
-
|
|
111
|
-
def __init__(self, message: str = "Request timed out") -> None:
|
|
112
|
-
"""Initialize timeout error.
|
|
113
|
-
|
|
114
|
-
Args:
|
|
115
|
-
message: Error message
|
|
116
|
-
"""
|
|
117
|
-
super().__init__(message, status_code=408)
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
class HTTPConnectionError(HTTPError):
|
|
121
|
-
"""Exception raised when HTTP connection fails."""
|
|
122
|
-
|
|
123
|
-
def __init__(self, message: str = "Connection failed") -> None:
|
|
124
|
-
"""Initialize connection error.
|
|
125
|
-
|
|
126
|
-
Args:
|
|
127
|
-
message: Error message
|
|
128
|
-
"""
|
|
129
|
-
super().__init__(message, status_code=503)
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
class HTTPXClient(HTTPClient):
|
|
133
|
-
"""HTTPX-based HTTP client implementation."""
|
|
134
|
-
|
|
135
|
-
def __init__(
|
|
136
|
-
self,
|
|
137
|
-
timeout: float = 240.0,
|
|
138
|
-
proxy: str | None = None,
|
|
139
|
-
verify: bool | str = True,
|
|
140
|
-
) -> None:
|
|
141
|
-
"""Initialize HTTPX client.
|
|
142
|
-
|
|
143
|
-
Args:
|
|
144
|
-
timeout: Request timeout in seconds
|
|
145
|
-
proxy: HTTP proxy URL (optional)
|
|
146
|
-
verify: SSL verification (True/False or path to CA bundle)
|
|
147
|
-
"""
|
|
148
|
-
import httpx
|
|
149
|
-
|
|
150
|
-
self.timeout = timeout
|
|
151
|
-
self.proxy = proxy
|
|
152
|
-
self.verify = verify
|
|
153
|
-
self._client: httpx.AsyncClient | None = None
|
|
154
|
-
|
|
155
|
-
async def _get_client(self) -> "httpx.AsyncClient":
|
|
156
|
-
"""Get or create the HTTPX client."""
|
|
157
|
-
if self._client is None:
|
|
158
|
-
import httpx
|
|
159
|
-
|
|
160
|
-
self._client = httpx.AsyncClient(
|
|
161
|
-
timeout=self.timeout,
|
|
162
|
-
proxy=self.proxy,
|
|
163
|
-
verify=self.verify,
|
|
164
|
-
)
|
|
165
|
-
return self._client
|
|
166
|
-
|
|
167
|
-
async def request(
|
|
168
|
-
self,
|
|
169
|
-
method: str,
|
|
170
|
-
url: str,
|
|
171
|
-
headers: dict[str, str],
|
|
172
|
-
body: bytes | None = None,
|
|
173
|
-
timeout: float | None = None,
|
|
174
|
-
) -> tuple[int, dict[str, str], bytes]:
|
|
175
|
-
"""Make an HTTP request using HTTPX.
|
|
176
|
-
|
|
177
|
-
Args:
|
|
178
|
-
method: HTTP method
|
|
179
|
-
url: Target URL
|
|
180
|
-
headers: HTTP headers
|
|
181
|
-
body: Request body (optional)
|
|
182
|
-
timeout: Request timeout in seconds (optional)
|
|
183
|
-
|
|
184
|
-
Returns:
|
|
185
|
-
Tuple of (status_code, response_headers, response_body)
|
|
186
|
-
|
|
187
|
-
Raises:
|
|
188
|
-
HTTPError: If the request fails
|
|
189
|
-
"""
|
|
190
|
-
import httpx
|
|
191
|
-
|
|
192
|
-
try:
|
|
193
|
-
client = await self._get_client()
|
|
194
|
-
|
|
195
|
-
# Use provided timeout if available
|
|
196
|
-
if timeout is not None:
|
|
197
|
-
# Create a new client with different timeout if needed
|
|
198
|
-
import httpx
|
|
199
|
-
|
|
200
|
-
client = httpx.AsyncClient(
|
|
201
|
-
timeout=timeout,
|
|
202
|
-
proxy=self.proxy,
|
|
203
|
-
verify=self.verify,
|
|
204
|
-
)
|
|
205
|
-
|
|
206
|
-
response = await client.request(
|
|
207
|
-
method=method,
|
|
208
|
-
url=url,
|
|
209
|
-
headers=headers,
|
|
210
|
-
content=body,
|
|
211
|
-
)
|
|
212
|
-
|
|
213
|
-
# Always return the response, even for error status codes
|
|
214
|
-
# This allows the proxy to forward upstream errors directly
|
|
215
|
-
return (
|
|
216
|
-
response.status_code,
|
|
217
|
-
dict(response.headers),
|
|
218
|
-
response.content,
|
|
219
|
-
)
|
|
220
|
-
|
|
221
|
-
except httpx.TimeoutException as e:
|
|
222
|
-
raise HTTPTimeoutError(f"Request timed out: {e}") from e
|
|
223
|
-
except httpx.ConnectError as e:
|
|
224
|
-
raise HTTPConnectionError(f"Connection failed: {e}") from e
|
|
225
|
-
except httpx.HTTPStatusError as e:
|
|
226
|
-
# This shouldn't happen with the default raise_for_status=False
|
|
227
|
-
# but keep it just in case
|
|
228
|
-
raise HTTPError(
|
|
229
|
-
f"HTTP {e.response.status_code}: {e.response.reason_phrase}",
|
|
230
|
-
status_code=e.response.status_code,
|
|
231
|
-
) from e
|
|
232
|
-
except Exception as e:
|
|
233
|
-
raise HTTPError(f"HTTP request failed: {e}") from e
|
|
234
|
-
|
|
235
|
-
async def stream(
|
|
236
|
-
self,
|
|
237
|
-
method: str,
|
|
238
|
-
url: str,
|
|
239
|
-
headers: dict[str, str],
|
|
240
|
-
content: bytes | None = None,
|
|
241
|
-
) -> Any:
|
|
242
|
-
"""Create a streaming HTTP request.
|
|
243
|
-
|
|
244
|
-
Args:
|
|
245
|
-
method: HTTP method
|
|
246
|
-
url: Target URL
|
|
247
|
-
headers: HTTP headers
|
|
248
|
-
content: Request body (optional)
|
|
249
|
-
|
|
250
|
-
Returns:
|
|
251
|
-
HTTPX streaming response context manager
|
|
252
|
-
"""
|
|
253
|
-
client = await self._get_client()
|
|
254
|
-
return client.stream(
|
|
255
|
-
method=method,
|
|
256
|
-
url=url,
|
|
257
|
-
headers=headers,
|
|
258
|
-
content=content,
|
|
259
|
-
)
|
|
260
|
-
|
|
261
|
-
async def close(self) -> None:
|
|
262
|
-
"""Close the HTTPX client."""
|
|
263
|
-
if self._client is not None:
|
|
264
|
-
await self._client.aclose()
|
|
265
|
-
self._client = None
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
def get_proxy_url() -> str | None:
|
|
269
|
-
"""Get proxy URL from environment variables.
|
|
270
|
-
|
|
271
|
-
Returns:
|
|
272
|
-
str or None: Proxy URL if any proxy is set
|
|
273
|
-
"""
|
|
274
|
-
# Check for standard proxy environment variables
|
|
275
|
-
# For HTTPS requests, prioritize HTTPS_PROXY
|
|
276
|
-
https_proxy = os.environ.get("HTTPS_PROXY") or os.environ.get("https_proxy")
|
|
277
|
-
all_proxy = os.environ.get("ALL_PROXY")
|
|
278
|
-
http_proxy = os.environ.get("HTTP_PROXY") or os.environ.get("http_proxy")
|
|
279
|
-
|
|
280
|
-
proxy_url = https_proxy or all_proxy or http_proxy
|
|
281
|
-
|
|
282
|
-
if proxy_url:
|
|
283
|
-
logger.debug(
|
|
284
|
-
"proxy_configured",
|
|
285
|
-
proxy_url=proxy_url,
|
|
286
|
-
operation="get_proxy_url",
|
|
287
|
-
)
|
|
288
|
-
|
|
289
|
-
return proxy_url
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
def get_ssl_context() -> str | bool:
|
|
293
|
-
"""Get SSL context configuration from environment variables.
|
|
294
|
-
|
|
295
|
-
Returns:
|
|
296
|
-
SSL verification configuration:
|
|
297
|
-
- Path to CA bundle file
|
|
298
|
-
- True for default verification
|
|
299
|
-
- False to disable verification (insecure)
|
|
300
|
-
"""
|
|
301
|
-
# Check for custom CA bundle
|
|
302
|
-
ca_bundle = os.environ.get("REQUESTS_CA_BUNDLE") or os.environ.get("SSL_CERT_FILE")
|
|
303
|
-
|
|
304
|
-
# Check if SSL verification should be disabled (NOT RECOMMENDED)
|
|
305
|
-
ssl_verify = os.environ.get("SSL_VERIFY", "true").lower()
|
|
306
|
-
|
|
307
|
-
if ca_bundle and Path(ca_bundle).exists():
|
|
308
|
-
logger.info(
|
|
309
|
-
"ssl_ca_bundle_configured",
|
|
310
|
-
ca_bundle_path=ca_bundle,
|
|
311
|
-
operation="get_ssl_context",
|
|
312
|
-
)
|
|
313
|
-
return ca_bundle
|
|
314
|
-
elif ssl_verify in ("false", "0", "no"):
|
|
315
|
-
logger.warning(
|
|
316
|
-
"ssl_verification_disabled",
|
|
317
|
-
ssl_verify_value=ssl_verify,
|
|
318
|
-
operation="get_ssl_context",
|
|
319
|
-
security_warning=True,
|
|
320
|
-
)
|
|
321
|
-
return False
|
|
322
|
-
else:
|
|
323
|
-
logger.debug(
|
|
324
|
-
"ssl_default_verification",
|
|
325
|
-
ssl_verify_value=ssl_verify,
|
|
326
|
-
operation="get_ssl_context",
|
|
327
|
-
)
|
|
328
|
-
return True
|