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/auth/dependencies.py
CHANGED
|
@@ -1,229 +1,195 @@
|
|
|
1
|
-
"""FastAPI dependency injection for authentication."""
|
|
1
|
+
"""FastAPI dependency injection utilities for authentication."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
2
4
|
|
|
3
5
|
from typing import TYPE_CHECKING, Annotated
|
|
4
6
|
|
|
5
|
-
from fastapi import Depends, HTTPException, status
|
|
7
|
+
from fastapi import Depends, HTTPException, Request, status
|
|
6
8
|
from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
|
|
7
9
|
|
|
8
|
-
|
|
9
|
-
if TYPE_CHECKING:
|
|
10
|
-
from ccproxy.config.settings import Settings
|
|
11
|
-
|
|
12
10
|
from ccproxy.auth.bearer import BearerTokenAuthManager
|
|
13
|
-
from ccproxy.auth.credentials_adapter import CredentialsAuthManager
|
|
14
11
|
from ccproxy.auth.exceptions import AuthenticationError, AuthenticationRequiredError
|
|
15
12
|
from ccproxy.auth.manager import AuthManager
|
|
13
|
+
from ccproxy.config.settings import Settings
|
|
16
14
|
|
|
17
15
|
|
|
18
|
-
#
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
async def get_credentials_auth_manager() -> AuthManager:
|
|
23
|
-
"""Get credentials-based authentication manager.
|
|
24
|
-
|
|
25
|
-
Returns:
|
|
26
|
-
CredentialsAuthManager instance
|
|
27
|
-
"""
|
|
28
|
-
return CredentialsAuthManager()
|
|
16
|
+
if TYPE_CHECKING: # pragma: no cover - import cycle guard for type checking only
|
|
17
|
+
pass
|
|
29
18
|
|
|
30
19
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
) -> AuthManager:
|
|
34
|
-
"""Get bearer token authentication manager.
|
|
20
|
+
# FastAPI security scheme for bearer tokens
|
|
21
|
+
bearer_scheme = HTTPBearer(auto_error=False)
|
|
35
22
|
|
|
36
|
-
Args:
|
|
37
|
-
credentials: HTTP authorization credentials
|
|
38
23
|
|
|
39
|
-
|
|
40
|
-
|
|
24
|
+
def get_settings() -> Settings:
|
|
25
|
+
"""Get settings instance directly (without service container)."""
|
|
26
|
+
return Settings()
|
|
41
27
|
|
|
42
|
-
Raises:
|
|
43
|
-
HTTPException: If no valid bearer token provided
|
|
44
|
-
"""
|
|
45
|
-
if not credentials or not credentials.credentials:
|
|
46
|
-
raise HTTPException(
|
|
47
|
-
status_code=status.HTTP_401_UNAUTHORIZED,
|
|
48
|
-
detail="Bearer token required",
|
|
49
|
-
headers={"WWW-Authenticate": "Bearer"},
|
|
50
|
-
)
|
|
51
28
|
|
|
52
|
-
|
|
29
|
+
SettingsDep = Annotated[Settings, Depends(get_settings)]
|
|
53
30
|
|
|
54
31
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
settings: "Settings",
|
|
58
|
-
) -> AuthManager:
|
|
59
|
-
"""Internal function to get auth manager with specific settings.
|
|
32
|
+
def _resolve_runtime_settings(request: Request) -> Settings | None:
|
|
33
|
+
"""Best-effort retrieval of settings without importing API dependencies."""
|
|
60
34
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
35
|
+
container = getattr(request.app.state, "service_container", None)
|
|
36
|
+
if container is None:
|
|
37
|
+
try:
|
|
38
|
+
from ccproxy.services.container import ServiceContainer
|
|
64
39
|
|
|
65
|
-
|
|
66
|
-
|
|
40
|
+
container = ServiceContainer.get_current(strict=False)
|
|
41
|
+
except (ImportError, RuntimeError):
|
|
42
|
+
container = None
|
|
67
43
|
|
|
68
|
-
|
|
69
|
-
HTTPException: If no valid authentication available
|
|
70
|
-
"""
|
|
71
|
-
# Try bearer token first if provided
|
|
72
|
-
if credentials and credentials.credentials:
|
|
44
|
+
if container is not None:
|
|
73
45
|
try:
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
bearer_auth = BearerTokenAuthManager(credentials.credentials)
|
|
78
|
-
if await bearer_auth.is_authenticated():
|
|
79
|
-
return bearer_auth
|
|
80
|
-
else:
|
|
81
|
-
# Token doesn't match configured auth_token
|
|
82
|
-
raise HTTPException(
|
|
83
|
-
status_code=status.HTTP_401_UNAUTHORIZED,
|
|
84
|
-
detail="Invalid bearer token",
|
|
85
|
-
headers={"WWW-Authenticate": "Bearer"},
|
|
86
|
-
)
|
|
87
|
-
else:
|
|
88
|
-
# No auth_token configured, accept any bearer token
|
|
89
|
-
bearer_auth = BearerTokenAuthManager(credentials.credentials)
|
|
90
|
-
if await bearer_auth.is_authenticated():
|
|
91
|
-
return bearer_auth
|
|
92
|
-
except (AuthenticationError, ValueError):
|
|
46
|
+
return container.get_service(Settings)
|
|
47
|
+
except ValueError:
|
|
48
|
+
# Service not registered yet; fall through to default settings.
|
|
93
49
|
pass
|
|
94
50
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
return credentials_auth
|
|
101
|
-
except AuthenticationError:
|
|
102
|
-
pass
|
|
51
|
+
try:
|
|
52
|
+
return Settings()
|
|
53
|
+
except Exception:
|
|
54
|
+
# Settings construction can fail in minimal test contexts.
|
|
55
|
+
return None
|
|
103
56
|
|
|
104
|
-
raise HTTPException(
|
|
105
|
-
status_code=status.HTTP_401_UNAUTHORIZED,
|
|
106
|
-
detail="Authentication required",
|
|
107
|
-
headers={"WWW-Authenticate": "Bearer"},
|
|
108
|
-
)
|
|
109
57
|
|
|
58
|
+
def _expected_token(settings: Settings | None) -> str | None:
|
|
59
|
+
"""Extract configured auth token from settings if present."""
|
|
110
60
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
] = None,
|
|
115
|
-
) -> AuthManager:
|
|
116
|
-
"""Get authentication manager with fallback strategy.
|
|
61
|
+
if settings and settings.security.auth_token:
|
|
62
|
+
return settings.security.auth_token.get_secret_value()
|
|
63
|
+
return None
|
|
117
64
|
|
|
118
|
-
Try bearer token first, then fall back to credentials.
|
|
119
65
|
|
|
120
|
-
|
|
121
|
-
|
|
66
|
+
async def _build_bearer_auth_manager(
|
|
67
|
+
credentials: HTTPAuthorizationCredentials | None,
|
|
68
|
+
expected_token: str | None,
|
|
69
|
+
*,
|
|
70
|
+
require_credentials: bool,
|
|
71
|
+
) -> AuthManager | None:
|
|
72
|
+
"""Create a bearer auth manager when credentials satisfy expectations."""
|
|
73
|
+
|
|
74
|
+
token = credentials.credentials if credentials and credentials.credentials else None
|
|
75
|
+
|
|
76
|
+
if token is None:
|
|
77
|
+
if require_credentials:
|
|
78
|
+
raise HTTPException(
|
|
79
|
+
status_code=status.HTTP_401_UNAUTHORIZED,
|
|
80
|
+
detail="Authentication required",
|
|
81
|
+
headers={"WWW-Authenticate": "Bearer"},
|
|
82
|
+
)
|
|
83
|
+
return None
|
|
84
|
+
|
|
85
|
+
if expected_token is not None and token != expected_token:
|
|
86
|
+
raise HTTPException(
|
|
87
|
+
status_code=status.HTTP_401_UNAUTHORIZED,
|
|
88
|
+
detail="Invalid authentication credentials",
|
|
89
|
+
headers={"WWW-Authenticate": "Bearer"},
|
|
90
|
+
)
|
|
122
91
|
|
|
123
|
-
|
|
124
|
-
|
|
92
|
+
try:
|
|
93
|
+
bearer_auth = BearerTokenAuthManager(token)
|
|
94
|
+
except ValueError as exc:
|
|
95
|
+
raise HTTPException(
|
|
96
|
+
status_code=status.HTTP_401_UNAUTHORIZED,
|
|
97
|
+
detail=str(exc),
|
|
98
|
+
headers={"WWW-Authenticate": "Bearer"},
|
|
99
|
+
) from exc
|
|
125
100
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
101
|
+
try:
|
|
102
|
+
if await bearer_auth.is_authenticated():
|
|
103
|
+
return bearer_auth
|
|
104
|
+
except AuthenticationError as exc:
|
|
105
|
+
raise HTTPException(
|
|
106
|
+
status_code=status.HTTP_401_UNAUTHORIZED,
|
|
107
|
+
detail=str(exc),
|
|
108
|
+
headers={"WWW-Authenticate": "Bearer"},
|
|
109
|
+
) from exc
|
|
131
110
|
|
|
132
|
-
|
|
133
|
-
|
|
111
|
+
if require_credentials:
|
|
112
|
+
raise HTTPException(
|
|
113
|
+
status_code=status.HTTP_401_UNAUTHORIZED,
|
|
114
|
+
detail="Authentication failed",
|
|
115
|
+
headers={"WWW-Authenticate": "Bearer"},
|
|
116
|
+
)
|
|
117
|
+
return None
|
|
134
118
|
|
|
135
119
|
|
|
136
|
-
async def
|
|
137
|
-
credentials: Annotated[
|
|
138
|
-
|
|
139
|
-
] = None,
|
|
120
|
+
async def get_auth_manager(
|
|
121
|
+
credentials: Annotated[HTTPAuthorizationCredentials | None, Depends(bearer_scheme)],
|
|
122
|
+
settings: SettingsDep,
|
|
140
123
|
) -> AuthManager:
|
|
141
|
-
"""
|
|
142
|
-
|
|
143
|
-
This version uses FastAPI's dependency injection for settings,
|
|
144
|
-
which allows test overrides to work properly.
|
|
145
|
-
|
|
146
|
-
Args:
|
|
147
|
-
credentials: HTTP authorization credentials
|
|
148
|
-
settings: Application settings (injected by FastAPI)
|
|
124
|
+
"""Return an authentication manager when credentials are required."""
|
|
149
125
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
settings = get_settings()
|
|
160
|
-
return await _get_auth_manager_with_settings(credentials, settings)
|
|
126
|
+
auth_manager = await _build_bearer_auth_manager(
|
|
127
|
+
credentials,
|
|
128
|
+
_expected_token(settings),
|
|
129
|
+
require_credentials=True,
|
|
130
|
+
)
|
|
131
|
+
# require_credentials ensures auth_manager is never None here.
|
|
132
|
+
assert auth_manager is not None
|
|
133
|
+
return auth_manager
|
|
161
134
|
|
|
162
135
|
|
|
163
136
|
async def require_auth(
|
|
164
137
|
auth_manager: Annotated[AuthManager, Depends(get_auth_manager)],
|
|
165
138
|
) -> AuthManager:
|
|
166
|
-
"""
|
|
167
|
-
|
|
168
|
-
Args:
|
|
169
|
-
auth_manager: Authentication manager
|
|
139
|
+
"""Enforce authentication, translating failures into HTTP errors."""
|
|
170
140
|
|
|
171
|
-
Returns:
|
|
172
|
-
AuthManager instance
|
|
173
|
-
|
|
174
|
-
Raises:
|
|
175
|
-
HTTPException: If authentication fails
|
|
176
|
-
"""
|
|
177
141
|
try:
|
|
178
142
|
if not await auth_manager.is_authenticated():
|
|
179
143
|
raise AuthenticationRequiredError("Authentication required")
|
|
180
144
|
return auth_manager
|
|
181
|
-
except AuthenticationError as
|
|
145
|
+
except AuthenticationError as exc:
|
|
182
146
|
raise HTTPException(
|
|
183
147
|
status_code=status.HTTP_401_UNAUTHORIZED,
|
|
184
|
-
detail=str(
|
|
148
|
+
detail=str(exc),
|
|
185
149
|
headers={"WWW-Authenticate": "Bearer"},
|
|
186
|
-
) from
|
|
150
|
+
) from exc
|
|
187
151
|
|
|
188
152
|
|
|
189
153
|
async def get_access_token(
|
|
190
154
|
auth_manager: Annotated[AuthManager, Depends(require_auth)],
|
|
191
155
|
) -> str:
|
|
192
|
-
"""
|
|
193
|
-
|
|
194
|
-
Args:
|
|
195
|
-
auth_manager: Authentication manager
|
|
156
|
+
"""Retrieve an access token from an authenticated manager."""
|
|
196
157
|
|
|
197
|
-
Returns:
|
|
198
|
-
Access token string
|
|
199
|
-
|
|
200
|
-
Raises:
|
|
201
|
-
HTTPException: If token retrieval fails
|
|
202
|
-
"""
|
|
203
158
|
try:
|
|
204
159
|
return await auth_manager.get_access_token()
|
|
205
|
-
except AuthenticationError as
|
|
160
|
+
except AuthenticationError as exc:
|
|
206
161
|
raise HTTPException(
|
|
207
162
|
status_code=status.HTTP_401_UNAUTHORIZED,
|
|
208
|
-
detail=str(
|
|
163
|
+
detail=str(exc),
|
|
209
164
|
headers={"WWW-Authenticate": "Bearer"},
|
|
210
|
-
) from
|
|
165
|
+
) from exc
|
|
211
166
|
|
|
212
167
|
|
|
213
|
-
async def
|
|
168
|
+
async def get_conditional_auth_manager(
|
|
169
|
+
request: Request,
|
|
214
170
|
credentials: Annotated[
|
|
215
171
|
HTTPAuthorizationCredentials | None, Depends(bearer_scheme)
|
|
216
172
|
] = None,
|
|
217
|
-
) -> AuthManager:
|
|
218
|
-
"""
|
|
219
|
-
# Import here to avoid circular imports
|
|
220
|
-
from ccproxy.config.settings import get_settings
|
|
173
|
+
) -> AuthManager | None:
|
|
174
|
+
"""Return an auth manager only when the configuration requires it."""
|
|
221
175
|
|
|
222
|
-
settings =
|
|
223
|
-
|
|
176
|
+
settings = _resolve_runtime_settings(request)
|
|
177
|
+
expected_token = _expected_token(settings)
|
|
178
|
+
|
|
179
|
+
if expected_token is None:
|
|
180
|
+
return None
|
|
181
|
+
|
|
182
|
+
return await _build_bearer_auth_manager(
|
|
183
|
+
credentials,
|
|
184
|
+
expected_token,
|
|
185
|
+
require_credentials=True,
|
|
186
|
+
)
|
|
224
187
|
|
|
225
188
|
|
|
226
189
|
# Type aliases for common dependencies
|
|
227
190
|
AuthManagerDep = Annotated[AuthManager, Depends(get_auth_manager)]
|
|
228
191
|
RequiredAuthDep = Annotated[AuthManager, Depends(require_auth)]
|
|
229
192
|
AccessTokenDep = Annotated[str, Depends(get_access_token)]
|
|
193
|
+
ConditionalAuthDep = Annotated[
|
|
194
|
+
AuthManager | None, Depends(get_conditional_auth_manager)
|
|
195
|
+
]
|
ccproxy/auth/exceptions.py
CHANGED
|
@@ -61,19 +61,7 @@ class OAuthError(AuthenticationError):
|
|
|
61
61
|
pass
|
|
62
62
|
|
|
63
63
|
|
|
64
|
-
class OAuthLoginError(OAuthError):
|
|
65
|
-
"""OAuth login failed."""
|
|
66
|
-
|
|
67
|
-
pass
|
|
68
|
-
|
|
69
|
-
|
|
70
64
|
class OAuthTokenRefreshError(OAuthError):
|
|
71
65
|
"""OAuth token refresh failed."""
|
|
72
66
|
|
|
73
67
|
pass
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
class OAuthCallbackError(OAuthError):
|
|
77
|
-
"""OAuth callback failed."""
|
|
78
|
-
|
|
79
|
-
pass
|
ccproxy/auth/manager.py
CHANGED
|
@@ -1,13 +1,21 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""Unified authentication manager interface for all providers."""
|
|
2
2
|
|
|
3
|
-
from
|
|
4
|
-
from typing import Any, Protocol
|
|
3
|
+
from typing import Any, Protocol, runtime_checkable
|
|
5
4
|
|
|
6
|
-
from ccproxy.auth.models import
|
|
5
|
+
from ccproxy.auth.models.credentials import BaseCredentials
|
|
6
|
+
from ccproxy.auth.oauth.protocol import StandardProfileFields
|
|
7
7
|
|
|
8
8
|
|
|
9
|
+
@runtime_checkable
|
|
9
10
|
class AuthManager(Protocol):
|
|
10
|
-
"""
|
|
11
|
+
"""Unified authentication manager protocol for all providers.
|
|
12
|
+
|
|
13
|
+
This protocol defines the complete interface that all authentication managers
|
|
14
|
+
must implement, supporting both provider-specific methods (like Claude credentials)
|
|
15
|
+
and generic methods (like auth headers) for maximum flexibility.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
# ==================== Core Authentication Methods ====================
|
|
11
19
|
|
|
12
20
|
async def get_access_token(self) -> str:
|
|
13
21
|
"""Get valid access token.
|
|
@@ -20,14 +28,17 @@ class AuthManager(Protocol):
|
|
|
20
28
|
"""
|
|
21
29
|
...
|
|
22
30
|
|
|
23
|
-
async def get_credentials(self) ->
|
|
31
|
+
async def get_credentials(self) -> BaseCredentials:
|
|
24
32
|
"""Get valid credentials.
|
|
25
33
|
|
|
34
|
+
Note: For non-Claude providers, this may return minimal/dummy credentials
|
|
35
|
+
or raise AuthenticationError if not supported.
|
|
36
|
+
|
|
26
37
|
Returns:
|
|
27
38
|
Valid credentials
|
|
28
39
|
|
|
29
40
|
Raises:
|
|
30
|
-
AuthenticationError: If authentication fails
|
|
41
|
+
AuthenticationError: If authentication fails or not supported
|
|
31
42
|
"""
|
|
32
43
|
...
|
|
33
44
|
|
|
@@ -39,64 +50,39 @@ class AuthManager(Protocol):
|
|
|
39
50
|
"""
|
|
40
51
|
...
|
|
41
52
|
|
|
42
|
-
async def get_user_profile(self) ->
|
|
43
|
-
"""Get user profile information.
|
|
53
|
+
async def get_user_profile(self) -> StandardProfileFields | None:
|
|
54
|
+
"""Get standardized user profile information.
|
|
44
55
|
|
|
45
56
|
Returns:
|
|
46
|
-
|
|
57
|
+
Standardized profile details when available, otherwise ``None``
|
|
58
|
+
for providers that do not expose profile metadata.
|
|
47
59
|
"""
|
|
48
60
|
...
|
|
49
61
|
|
|
62
|
+
# ==================== Provider-Generic Methods ====================
|
|
50
63
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
@abstractmethod
|
|
55
|
-
async def get_access_token(self) -> str:
|
|
56
|
-
"""Get valid access token.
|
|
57
|
-
|
|
58
|
-
Returns:
|
|
59
|
-
Access token string
|
|
60
|
-
|
|
61
|
-
Raises:
|
|
62
|
-
AuthenticationError: If authentication fails
|
|
63
|
-
"""
|
|
64
|
-
pass
|
|
65
|
-
|
|
66
|
-
@abstractmethod
|
|
67
|
-
async def get_credentials(self) -> ClaudeCredentials:
|
|
68
|
-
"""Get valid credentials.
|
|
64
|
+
async def validate_credentials(self) -> bool:
|
|
65
|
+
"""Validate that credentials are available and valid.
|
|
69
66
|
|
|
70
67
|
Returns:
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
Raises:
|
|
74
|
-
AuthenticationError: If authentication fails
|
|
68
|
+
True if credentials are valid, False otherwise
|
|
75
69
|
"""
|
|
76
|
-
|
|
70
|
+
...
|
|
77
71
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
"""Check if current authentication is valid.
|
|
72
|
+
def get_provider_name(self) -> str:
|
|
73
|
+
"""Get the provider name for logging.
|
|
81
74
|
|
|
82
75
|
Returns:
|
|
83
|
-
|
|
76
|
+
Provider name string (e.g., "anthropic-claude", "openai-codex")
|
|
84
77
|
"""
|
|
85
|
-
|
|
78
|
+
...
|
|
86
79
|
|
|
87
|
-
|
|
88
|
-
"""Get user profile information.
|
|
80
|
+
# ==================== Context Manager Support ====================
|
|
89
81
|
|
|
90
|
-
|
|
91
|
-
UserProfile if available, None otherwise
|
|
92
|
-
"""
|
|
93
|
-
return None
|
|
94
|
-
|
|
95
|
-
async def __aenter__(self) -> "BaseAuthManager":
|
|
82
|
+
async def __aenter__(self) -> "AuthManager":
|
|
96
83
|
"""Async context manager entry."""
|
|
97
|
-
|
|
84
|
+
...
|
|
98
85
|
|
|
99
|
-
@abstractmethod
|
|
100
86
|
async def __aexit__(self, exc_type: Any, exc_val: Any, exc_tb: Any) -> None:
|
|
101
87
|
"""Async context manager exit."""
|
|
102
|
-
|
|
88
|
+
...
|