ccproxy-api 0.1.7__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 +434 -219
- ccproxy/api/bootstrap.py +30 -0
- ccproxy/api/decorators.py +85 -0
- ccproxy/api/dependencies.py +144 -168
- ccproxy/api/format_validation.py +54 -0
- ccproxy/api/middleware/cors.py +6 -3
- ccproxy/api/middleware/errors.py +388 -524
- 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 +540 -19
- ccproxy/data/codex_headers_fallback.json +114 -7
- 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 +61 -105
- ccproxy/scheduler/registry.py +6 -32
- ccproxy/scheduler/tasks.py +268 -276
- 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 +68 -446
- ccproxy/utils/version_checker.py +273 -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.7.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 -1251
- 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 -243
- ccproxy/services/codex_detection_service.py +0 -252
- 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.7.dist-info/METADATA +0 -615
- ccproxy_api-0.1.7.dist-info/RECORD +0 -191
- ccproxy_api-0.1.7.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.7.dist-info → ccproxy_api-0.2.0.dist-info}/licenses/LICENSE +0 -0
ccproxy/core/constants.py
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
"""Core constants
|
|
1
|
+
"""Core constants for format identifiers and related shared values."""
|
|
2
|
+
|
|
3
|
+
# Format identifiers
|
|
4
|
+
FORMAT_OPENAI_CHAT = "openai.chat_completions"
|
|
5
|
+
FORMAT_OPENAI_RESPONSES = "openai.responses"
|
|
6
|
+
FORMAT_ANTHROPIC_MESSAGES = "anthropic.messages"
|
|
2
7
|
|
|
3
8
|
# HTTP headers
|
|
4
9
|
REQUEST_ID_HEADER = "X-Request-ID"
|
|
@@ -46,52 +51,13 @@ CONFIG_FILE_NAMES = [
|
|
|
46
51
|
"config.yaml",
|
|
47
52
|
"config.yml",
|
|
48
53
|
]
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
ERROR_MSG_MODEL_NOT_FOUND = "Model not found or not available"
|
|
60
|
-
ERROR_MSG_RATE_LIMIT_EXCEEDED = "Rate limit exceeded"
|
|
61
|
-
ERROR_MSG_INVALID_REQUEST = "Invalid request format"
|
|
62
|
-
ERROR_MSG_INTERNAL_ERROR = "Internal server error"
|
|
63
|
-
|
|
64
|
-
# Status codes
|
|
65
|
-
STATUS_OK = 200
|
|
66
|
-
STATUS_CREATED = 201
|
|
67
|
-
STATUS_BAD_REQUEST = 400
|
|
68
|
-
STATUS_UNAUTHORIZED = 401
|
|
69
|
-
STATUS_FORBIDDEN = 403
|
|
70
|
-
STATUS_NOT_FOUND = 404
|
|
71
|
-
STATUS_RATE_LIMITED = 429
|
|
72
|
-
STATUS_INTERNAL_ERROR = 500
|
|
73
|
-
STATUS_BAD_GATEWAY = 502
|
|
74
|
-
STATUS_SERVICE_UNAVAILABLE = 503
|
|
75
|
-
|
|
76
|
-
# Stream event types
|
|
77
|
-
STREAM_EVENT_MESSAGE_START = "message_start"
|
|
78
|
-
STREAM_EVENT_MESSAGE_DELTA = "message_delta"
|
|
79
|
-
STREAM_EVENT_MESSAGE_STOP = "message_stop"
|
|
80
|
-
STREAM_EVENT_CONTENT_BLOCK_START = "content_block_start"
|
|
81
|
-
STREAM_EVENT_CONTENT_BLOCK_DELTA = "content_block_delta"
|
|
82
|
-
STREAM_EVENT_CONTENT_BLOCK_STOP = "content_block_stop"
|
|
83
|
-
|
|
84
|
-
# Content types
|
|
85
|
-
CONTENT_TYPE_JSON = "application/json"
|
|
86
|
-
CONTENT_TYPE_STREAM = "text/event-stream"
|
|
87
|
-
CONTENT_TYPE_TEXT = "text/plain"
|
|
88
|
-
|
|
89
|
-
# Character limits
|
|
90
|
-
MAX_PROMPT_LENGTH = 200_000 # Maximum prompt length in characters
|
|
91
|
-
MAX_MESSAGE_LENGTH = 100_000 # Maximum message length
|
|
92
|
-
MAX_TOOL_CALLS = 100 # Maximum number of tool calls per request
|
|
93
|
-
|
|
94
|
-
# Validation patterns
|
|
95
|
-
EMAIL_PATTERN = r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"
|
|
96
|
-
URL_PATTERN = r"^https?://[^\s/$.?#].[^\s]*$"
|
|
97
|
-
UUID_PATTERN = r"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
|
|
54
|
+
# Common upstream endpoint paths (provider APIs)
|
|
55
|
+
UPSTREAM_ENDPOINT_OPENAI_RESPONSES = "/responses"
|
|
56
|
+
UPSTREAM_ENDPOINT_OPENAI_CHAT_COMPLETIONS = "/chat/completions"
|
|
57
|
+
UPSTREAM_ENDPOINT_ANTHROPIC_MESSAGES = "/v1/messages"
|
|
58
|
+
# Additional common OpenAI-style endpoints
|
|
59
|
+
UPSTREAM_ENDPOINT_OPENAI_EMBEDDINGS = "/embeddings"
|
|
60
|
+
UPSTREAM_ENDPOINT_OPENAI_MODELS = "/models"
|
|
61
|
+
# GitHub Copilot internal API endpoints
|
|
62
|
+
UPSTREAM_ENDPOINT_COPILOT_INTERNAL_USER = "/copilot_internal/user"
|
|
63
|
+
UPSTREAM_ENDPOINT_COPILOT_INTERNAL_TOKEN = "/copilot_internal/v2/token"
|
ccproxy/core/errors.py
CHANGED
|
@@ -273,6 +273,57 @@ class PermissionAlreadyResolvedError(PermissionRequestError):
|
|
|
273
273
|
)
|
|
274
274
|
|
|
275
275
|
|
|
276
|
+
class PluginResourceError(ProxyError):
|
|
277
|
+
"""Error raised when a plugin resource is unavailable or misconfigured.
|
|
278
|
+
|
|
279
|
+
This is a general exception for plugins to use when required resources
|
|
280
|
+
(like configuration, external services, or dependencies) are not available.
|
|
281
|
+
"""
|
|
282
|
+
|
|
283
|
+
def __init__(
|
|
284
|
+
self,
|
|
285
|
+
message: str,
|
|
286
|
+
plugin_name: str | None = None,
|
|
287
|
+
resource_type: str | None = None,
|
|
288
|
+
cause: Exception | None = None,
|
|
289
|
+
):
|
|
290
|
+
"""Initialize with a message and optional details.
|
|
291
|
+
|
|
292
|
+
Args:
|
|
293
|
+
message: The error message
|
|
294
|
+
plugin_name: Name of the plugin encountering the error
|
|
295
|
+
resource_type: Type of resource that's unavailable (e.g., "instructions", "config", "auth")
|
|
296
|
+
cause: The underlying exception
|
|
297
|
+
"""
|
|
298
|
+
super().__init__(message, cause)
|
|
299
|
+
self.plugin_name = plugin_name
|
|
300
|
+
self.resource_type = resource_type
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
class PluginLoadError(ProxyError):
|
|
304
|
+
"""Error raised when plugin loading fails.
|
|
305
|
+
|
|
306
|
+
This exception is used when plugins cannot be loaded due to import errors,
|
|
307
|
+
missing dependencies, missing classes, or other loading-related issues.
|
|
308
|
+
"""
|
|
309
|
+
|
|
310
|
+
def __init__(
|
|
311
|
+
self,
|
|
312
|
+
message: str,
|
|
313
|
+
plugin_name: str | None = None,
|
|
314
|
+
cause: Exception | None = None,
|
|
315
|
+
):
|
|
316
|
+
"""Initialize with a message and optional details.
|
|
317
|
+
|
|
318
|
+
Args:
|
|
319
|
+
message: The error message
|
|
320
|
+
plugin_name: Name of the plugin that failed to load
|
|
321
|
+
cause: The underlying exception
|
|
322
|
+
"""
|
|
323
|
+
super().__init__(message, cause)
|
|
324
|
+
self.plugin_name = plugin_name
|
|
325
|
+
|
|
326
|
+
|
|
276
327
|
__all__ = [
|
|
277
328
|
# Core proxy errors
|
|
278
329
|
"ProxyError",
|
|
@@ -281,6 +332,8 @@ __all__ = [
|
|
|
281
332
|
"ProxyConnectionError",
|
|
282
333
|
"ProxyTimeoutError",
|
|
283
334
|
"ProxyAuthenticationError",
|
|
335
|
+
"PluginResourceError",
|
|
336
|
+
"PluginLoadError",
|
|
284
337
|
# API-level errors
|
|
285
338
|
"ClaudeProxyError",
|
|
286
339
|
"ValidationError",
|
ccproxy/core/id_utils.py
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"""Utilities for generating short, debug-friendly IDs."""
|
|
2
|
+
|
|
3
|
+
import uuid
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
# Length of generated IDs - easily adjustable
|
|
7
|
+
ID_LENGTH = 8
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def generate_short_id() -> str:
|
|
11
|
+
"""Generate a short, debug-friendly ID.
|
|
12
|
+
|
|
13
|
+
Creates an 8-character hex string from a UUID4, providing good
|
|
14
|
+
collision resistance while being much easier to type and remember
|
|
15
|
+
during debugging.
|
|
16
|
+
|
|
17
|
+
Returns:
|
|
18
|
+
Short hex string (e.g., 'f47ac10b')
|
|
19
|
+
"""
|
|
20
|
+
return uuid.uuid4().hex[:ID_LENGTH]
|
ccproxy/core/interfaces.py
CHANGED
|
@@ -8,7 +8,6 @@ from abc import ABC, abstractmethod
|
|
|
8
8
|
from collections.abc import AsyncIterator
|
|
9
9
|
from typing import Any, Protocol, TypeVar, runtime_checkable
|
|
10
10
|
|
|
11
|
-
from ccproxy.auth.models import ClaudeCredentials
|
|
12
11
|
from ccproxy.core.types import TransformContext
|
|
13
12
|
|
|
14
13
|
|
|
@@ -17,12 +16,12 @@ __all__ = [
|
|
|
17
16
|
"RequestTransformer",
|
|
18
17
|
"ResponseTransformer",
|
|
19
18
|
"StreamTransformer",
|
|
20
|
-
"APIAdapter",
|
|
21
19
|
"TransformerProtocol",
|
|
22
20
|
# Storage interfaces
|
|
23
|
-
"TokenStorage",
|
|
24
21
|
# Metrics interfaces
|
|
25
22
|
"MetricExporter",
|
|
23
|
+
# Streaming configuration protocol
|
|
24
|
+
"StreamingConfigurable",
|
|
26
25
|
]
|
|
27
26
|
|
|
28
27
|
|
|
@@ -92,65 +91,6 @@ class StreamTransformer(ABC):
|
|
|
92
91
|
pass
|
|
93
92
|
|
|
94
93
|
|
|
95
|
-
class APIAdapter(ABC):
|
|
96
|
-
"""Abstract base class for API format adapters.
|
|
97
|
-
|
|
98
|
-
Combines all transformation interfaces to provide a complete adapter
|
|
99
|
-
for converting between different API formats.
|
|
100
|
-
"""
|
|
101
|
-
|
|
102
|
-
@abstractmethod
|
|
103
|
-
def adapt_request(self, request: dict[str, Any]) -> dict[str, Any]:
|
|
104
|
-
"""Convert a request from one API format to another.
|
|
105
|
-
|
|
106
|
-
Args:
|
|
107
|
-
request: The request data to convert
|
|
108
|
-
|
|
109
|
-
Returns:
|
|
110
|
-
The converted request data
|
|
111
|
-
|
|
112
|
-
Raises:
|
|
113
|
-
ValueError: If the request format is invalid or unsupported
|
|
114
|
-
"""
|
|
115
|
-
pass
|
|
116
|
-
|
|
117
|
-
@abstractmethod
|
|
118
|
-
def adapt_response(self, response: dict[str, Any]) -> dict[str, Any]:
|
|
119
|
-
"""Convert a response from one API format to another.
|
|
120
|
-
|
|
121
|
-
Args:
|
|
122
|
-
response: The response data to convert
|
|
123
|
-
|
|
124
|
-
Returns:
|
|
125
|
-
The converted response data
|
|
126
|
-
|
|
127
|
-
Raises:
|
|
128
|
-
ValueError: If the response format is invalid or unsupported
|
|
129
|
-
"""
|
|
130
|
-
pass
|
|
131
|
-
|
|
132
|
-
@abstractmethod
|
|
133
|
-
def adapt_stream(
|
|
134
|
-
self, stream: AsyncIterator[dict[str, Any]]
|
|
135
|
-
) -> AsyncIterator[dict[str, Any]]:
|
|
136
|
-
"""Convert a streaming response from one API format to another.
|
|
137
|
-
|
|
138
|
-
Args:
|
|
139
|
-
stream: The streaming response data to convert
|
|
140
|
-
|
|
141
|
-
Yields:
|
|
142
|
-
The converted streaming response chunks
|
|
143
|
-
|
|
144
|
-
Raises:
|
|
145
|
-
ValueError: If the stream format is invalid or unsupported
|
|
146
|
-
"""
|
|
147
|
-
# This should be implemented as an async generator
|
|
148
|
-
# async def adapt_stream(self, stream): ...
|
|
149
|
-
# async for item in stream:
|
|
150
|
-
# yield transformed_item
|
|
151
|
-
raise NotImplementedError
|
|
152
|
-
|
|
153
|
-
|
|
154
94
|
@runtime_checkable
|
|
155
95
|
class TransformerProtocol(Protocol[T, R]):
|
|
156
96
|
"""Protocol defining the transformer interface."""
|
|
@@ -160,61 +100,6 @@ class TransformerProtocol(Protocol[T, R]):
|
|
|
160
100
|
...
|
|
161
101
|
|
|
162
102
|
|
|
163
|
-
# === Storage Interfaces ===
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
class TokenStorage(ABC):
|
|
167
|
-
"""Abstract interface for token storage backends."""
|
|
168
|
-
|
|
169
|
-
@abstractmethod
|
|
170
|
-
async def load(self) -> ClaudeCredentials | None:
|
|
171
|
-
"""Load credentials from storage.
|
|
172
|
-
|
|
173
|
-
Returns:
|
|
174
|
-
Parsed credentials if found and valid, None otherwise
|
|
175
|
-
"""
|
|
176
|
-
pass
|
|
177
|
-
|
|
178
|
-
@abstractmethod
|
|
179
|
-
async def save(self, credentials: ClaudeCredentials) -> bool:
|
|
180
|
-
"""Save credentials to storage.
|
|
181
|
-
|
|
182
|
-
Args:
|
|
183
|
-
credentials: Credentials to save
|
|
184
|
-
|
|
185
|
-
Returns:
|
|
186
|
-
True if saved successfully, False otherwise
|
|
187
|
-
"""
|
|
188
|
-
pass
|
|
189
|
-
|
|
190
|
-
@abstractmethod
|
|
191
|
-
async def exists(self) -> bool:
|
|
192
|
-
"""Check if credentials exist in storage.
|
|
193
|
-
|
|
194
|
-
Returns:
|
|
195
|
-
True if credentials exist, False otherwise
|
|
196
|
-
"""
|
|
197
|
-
pass
|
|
198
|
-
|
|
199
|
-
@abstractmethod
|
|
200
|
-
async def delete(self) -> bool:
|
|
201
|
-
"""Delete credentials from storage.
|
|
202
|
-
|
|
203
|
-
Returns:
|
|
204
|
-
True if deleted successfully, False otherwise
|
|
205
|
-
"""
|
|
206
|
-
pass
|
|
207
|
-
|
|
208
|
-
@abstractmethod
|
|
209
|
-
def get_location(self) -> str:
|
|
210
|
-
"""Get the storage location description.
|
|
211
|
-
|
|
212
|
-
Returns:
|
|
213
|
-
Human-readable description of where credentials are stored
|
|
214
|
-
"""
|
|
215
|
-
pass
|
|
216
|
-
|
|
217
|
-
|
|
218
103
|
# === Metrics Interfaces ===
|
|
219
104
|
|
|
220
105
|
|
|
@@ -237,11 +122,19 @@ class MetricExporter(ABC):
|
|
|
237
122
|
"""
|
|
238
123
|
pass
|
|
239
124
|
|
|
240
|
-
@abstractmethod
|
|
241
|
-
async def health_check(self) -> bool:
|
|
242
|
-
"""Check if the metrics export system is healthy.
|
|
243
125
|
|
|
244
|
-
|
|
245
|
-
|
|
126
|
+
@runtime_checkable
|
|
127
|
+
class StreamingConfigurable(Protocol):
|
|
128
|
+
"""Protocol for adapters that accept streaming-related configuration.
|
|
129
|
+
|
|
130
|
+
Implementers can use this to receive DI-injected toggles such as whether
|
|
131
|
+
to serialize thinking content as XML in OpenAI streams.
|
|
132
|
+
"""
|
|
133
|
+
|
|
134
|
+
def configure_streaming(self, *, openai_thinking_xml: bool | None = None) -> None:
|
|
135
|
+
"""Apply streaming flags.
|
|
136
|
+
|
|
137
|
+
Args:
|
|
138
|
+
openai_thinking_xml: Enable/disable thinking-as-XML in OpenAI streams
|
|
246
139
|
"""
|
|
247
|
-
|
|
140
|
+
...
|