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
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
"""Plugin management API endpoints."""
|
|
2
|
+
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
from fastapi import APIRouter, HTTPException, Request
|
|
6
|
+
from pydantic import BaseModel
|
|
7
|
+
from starlette import status
|
|
8
|
+
|
|
9
|
+
import ccproxy.core.logging
|
|
10
|
+
from ccproxy.auth.dependencies import ConditionalAuthDep
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
logger = ccproxy.core.logging.get_logger(__name__)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
router = APIRouter(prefix="/plugins", tags=["plugins"])
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class PluginInfo(BaseModel):
|
|
20
|
+
"""Plugin information model."""
|
|
21
|
+
|
|
22
|
+
name: str
|
|
23
|
+
type: str # "builtin" or "plugin"
|
|
24
|
+
status: str # "active", "inactive", "error"
|
|
25
|
+
version: str | None = None
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class PluginListResponse(BaseModel):
|
|
29
|
+
"""Response model for plugin list."""
|
|
30
|
+
|
|
31
|
+
plugins: list[PluginInfo]
|
|
32
|
+
total: int
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class PluginStatusEntry(BaseModel):
|
|
36
|
+
name: str
|
|
37
|
+
version: str | None = None
|
|
38
|
+
type: str # "provider" or "system"
|
|
39
|
+
provides: list[str] = []
|
|
40
|
+
requires: list[str] = []
|
|
41
|
+
optional_requires: list[str] = []
|
|
42
|
+
initialized: bool
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class PluginStatusResponse(BaseModel):
|
|
46
|
+
initialization_order: list[str]
|
|
47
|
+
services: dict[str, str] # service_name -> provider plugin
|
|
48
|
+
plugins: list[PluginStatusEntry]
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class PluginHealthResponse(BaseModel):
|
|
52
|
+
"""Response model for plugin health check."""
|
|
53
|
+
|
|
54
|
+
plugin: str
|
|
55
|
+
status: str # "healthy", "unhealthy", "unknown"
|
|
56
|
+
adapter_loaded: bool
|
|
57
|
+
details: dict[str, Any] | None = None
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
# Only core plugin management endpoints are exposed:
|
|
61
|
+
# - GET /plugins: list loaded plugins
|
|
62
|
+
# - GET /plugins/{plugin_name}/health: check plugin health if provided by runtime
|
|
63
|
+
# - GET /plugins/status: summarize manifests and initialization state
|
|
64
|
+
#
|
|
65
|
+
# Dynamic reload/discover/unregister are not supported in v2 and have been removed.
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
# Plugin registry is accessed directly from app state
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
@router.get("", response_model=PluginListResponse)
|
|
72
|
+
async def list_plugins(
|
|
73
|
+
request: Request,
|
|
74
|
+
auth: ConditionalAuthDep = None,
|
|
75
|
+
) -> PluginListResponse:
|
|
76
|
+
"""List all loaded plugins and built-in providers.
|
|
77
|
+
|
|
78
|
+
Returns:
|
|
79
|
+
List of all available plugins and providers
|
|
80
|
+
"""
|
|
81
|
+
plugins: list[PluginInfo] = []
|
|
82
|
+
|
|
83
|
+
# Access v2 plugin registry from app state
|
|
84
|
+
if hasattr(request.app.state, "plugin_registry"):
|
|
85
|
+
from ccproxy.core.plugins import PluginRegistry
|
|
86
|
+
|
|
87
|
+
registry: PluginRegistry = request.app.state.plugin_registry
|
|
88
|
+
|
|
89
|
+
for name in registry.list_plugins():
|
|
90
|
+
factory = registry.get_factory(name)
|
|
91
|
+
if factory:
|
|
92
|
+
from ccproxy.core.plugins import factory_type_name
|
|
93
|
+
|
|
94
|
+
manifest = factory.get_manifest()
|
|
95
|
+
plugin_type = factory_type_name(factory)
|
|
96
|
+
|
|
97
|
+
plugins.append(
|
|
98
|
+
PluginInfo(
|
|
99
|
+
name=name,
|
|
100
|
+
type=plugin_type,
|
|
101
|
+
status="active",
|
|
102
|
+
version=manifest.version,
|
|
103
|
+
)
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
return PluginListResponse(plugins=plugins, total=len(plugins))
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
@router.get("/{plugin_name}/health", response_model=PluginHealthResponse)
|
|
110
|
+
async def plugin_health(
|
|
111
|
+
plugin_name: str,
|
|
112
|
+
request: Request,
|
|
113
|
+
auth: ConditionalAuthDep = None,
|
|
114
|
+
) -> PluginHealthResponse:
|
|
115
|
+
"""Check the health status of a specific plugin.
|
|
116
|
+
|
|
117
|
+
Args:
|
|
118
|
+
plugin_name: Name of the plugin to check
|
|
119
|
+
|
|
120
|
+
Returns:
|
|
121
|
+
Health status of the plugin
|
|
122
|
+
|
|
123
|
+
Raises:
|
|
124
|
+
HTTPException: If plugin not found
|
|
125
|
+
"""
|
|
126
|
+
# Access v2 plugin registry from app state
|
|
127
|
+
if not hasattr(request.app.state, "plugin_registry"):
|
|
128
|
+
raise HTTPException(status_code=503, detail="Plugin registry not initialized")
|
|
129
|
+
|
|
130
|
+
from ccproxy.core.plugins import PluginRegistry
|
|
131
|
+
|
|
132
|
+
registry: PluginRegistry = request.app.state.plugin_registry
|
|
133
|
+
|
|
134
|
+
# Check if plugin exists
|
|
135
|
+
if plugin_name not in registry.list_plugins():
|
|
136
|
+
raise HTTPException(
|
|
137
|
+
status_code=status.HTTP_404_NOT_FOUND,
|
|
138
|
+
detail=f"Plugin '{plugin_name}' not found",
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
# Get the plugin runtime instance
|
|
142
|
+
runtime = registry.get_runtime(plugin_name)
|
|
143
|
+
if runtime and hasattr(runtime, "health_check"):
|
|
144
|
+
try:
|
|
145
|
+
health_result = await runtime.health_check()
|
|
146
|
+
# Convert HealthCheckResult to PluginHealthResponse
|
|
147
|
+
# Handle both dict and object response
|
|
148
|
+
if isinstance(health_result, dict):
|
|
149
|
+
status_value = health_result.get("status", "unknown")
|
|
150
|
+
output_value = health_result.get("output")
|
|
151
|
+
version_value = health_result.get("version")
|
|
152
|
+
details_value = health_result.get("details")
|
|
153
|
+
else:
|
|
154
|
+
# Access attributes for non-dict responses
|
|
155
|
+
status_value = getattr(health_result, "status", "unknown")
|
|
156
|
+
output_value = getattr(health_result, "output", None)
|
|
157
|
+
version_value = getattr(health_result, "version", None)
|
|
158
|
+
details_value = getattr(health_result, "details", None)
|
|
159
|
+
|
|
160
|
+
return PluginHealthResponse(
|
|
161
|
+
plugin=plugin_name,
|
|
162
|
+
status="healthy"
|
|
163
|
+
if status_value == "pass"
|
|
164
|
+
else "unhealthy"
|
|
165
|
+
if status_value == "fail"
|
|
166
|
+
else "unknown",
|
|
167
|
+
adapter_loaded=True,
|
|
168
|
+
details={
|
|
169
|
+
"type": "plugin",
|
|
170
|
+
"active": True,
|
|
171
|
+
"health_check": {
|
|
172
|
+
"status": status_value,
|
|
173
|
+
"output": output_value,
|
|
174
|
+
"version": version_value,
|
|
175
|
+
"details": details_value,
|
|
176
|
+
},
|
|
177
|
+
},
|
|
178
|
+
)
|
|
179
|
+
except (OSError, PermissionError) as e:
|
|
180
|
+
logger.error(
|
|
181
|
+
"plugin_health_check_io_failed",
|
|
182
|
+
plugin=plugin_name,
|
|
183
|
+
error=str(e),
|
|
184
|
+
exc_info=e,
|
|
185
|
+
)
|
|
186
|
+
return PluginHealthResponse(
|
|
187
|
+
plugin=plugin_name,
|
|
188
|
+
status="unhealthy",
|
|
189
|
+
adapter_loaded=True,
|
|
190
|
+
details={"type": "plugin", "active": True, "io_error": str(e)},
|
|
191
|
+
)
|
|
192
|
+
except Exception as e:
|
|
193
|
+
logger.error(
|
|
194
|
+
"plugin_health_check_failed",
|
|
195
|
+
plugin=plugin_name,
|
|
196
|
+
error=str(e),
|
|
197
|
+
exc_info=e,
|
|
198
|
+
)
|
|
199
|
+
return PluginHealthResponse(
|
|
200
|
+
plugin=plugin_name,
|
|
201
|
+
status="unhealthy",
|
|
202
|
+
adapter_loaded=True,
|
|
203
|
+
details={"type": "plugin", "active": True, "error": str(e)},
|
|
204
|
+
)
|
|
205
|
+
else:
|
|
206
|
+
# Plugin doesn't have health check, use basic status
|
|
207
|
+
return PluginHealthResponse(
|
|
208
|
+
plugin=plugin_name,
|
|
209
|
+
status="healthy",
|
|
210
|
+
adapter_loaded=True,
|
|
211
|
+
details={"type": "plugin", "active": True},
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
# Endpoints are loaded at startup only
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
@router.get("/status", response_model=PluginStatusResponse)
|
|
218
|
+
async def plugins_status(
|
|
219
|
+
request: Request, auth: ConditionalAuthDep = None
|
|
220
|
+
) -> PluginStatusResponse:
|
|
221
|
+
"""Get plugin system status, including manifests and init order.
|
|
222
|
+
|
|
223
|
+
Returns:
|
|
224
|
+
Initialization order, registered services, and per-plugin manifest summary
|
|
225
|
+
"""
|
|
226
|
+
if not hasattr(request.app.state, "plugin_registry"):
|
|
227
|
+
raise HTTPException(status_code=503, detail="Plugin registry not initialized")
|
|
228
|
+
|
|
229
|
+
from ccproxy.core.plugins import PluginRegistry
|
|
230
|
+
|
|
231
|
+
registry: PluginRegistry = request.app.state.plugin_registry
|
|
232
|
+
|
|
233
|
+
# Get manifests and runtime status
|
|
234
|
+
entries: list[PluginStatusEntry] = []
|
|
235
|
+
for name in registry.list_plugins():
|
|
236
|
+
factory = registry.get_factory(name)
|
|
237
|
+
if not factory:
|
|
238
|
+
continue
|
|
239
|
+
manifest = factory.get_manifest()
|
|
240
|
+
runtime = registry.get_runtime(name)
|
|
241
|
+
|
|
242
|
+
# Determine plugin type via factory helper
|
|
243
|
+
from ccproxy.core.plugins import factory_type_name
|
|
244
|
+
|
|
245
|
+
plugin_type = factory_type_name(factory)
|
|
246
|
+
|
|
247
|
+
entries.append(
|
|
248
|
+
PluginStatusEntry(
|
|
249
|
+
name=name,
|
|
250
|
+
version=manifest.version,
|
|
251
|
+
type=plugin_type,
|
|
252
|
+
provides=list(manifest.provides),
|
|
253
|
+
requires=list(manifest.requires),
|
|
254
|
+
optional_requires=list(manifest.optional_requires),
|
|
255
|
+
initialized=runtime is not None
|
|
256
|
+
and getattr(runtime, "initialized", False),
|
|
257
|
+
)
|
|
258
|
+
)
|
|
259
|
+
|
|
260
|
+
# Extract init order and services map
|
|
261
|
+
init_order = list(getattr(registry, "initialization_order", []) or [])
|
|
262
|
+
services_map = dict(getattr(registry, "_service_providers", {}) or {})
|
|
263
|
+
|
|
264
|
+
return PluginStatusResponse(
|
|
265
|
+
initialization_order=init_order,
|
|
266
|
+
services=services_map,
|
|
267
|
+
plugins=entries,
|
|
268
|
+
)
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
@router.delete("/{plugin_name}")
|
|
272
|
+
async def unregister_plugin() -> dict[str, str]:
|
|
273
|
+
"""Plugin unregistration is not supported in v2; endpoint removed."""
|
|
274
|
+
raise HTTPException(
|
|
275
|
+
status_code=status.HTTP_501_NOT_IMPLEMENTED,
|
|
276
|
+
detail="Plugin unregistration is not supported; restart with desired config.",
|
|
277
|
+
)
|
ccproxy/auth/__init__.py
CHANGED
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
"""Authentication module for centralized auth handling."""
|
|
2
2
|
|
|
3
3
|
from ccproxy.auth.bearer import BearerTokenAuthManager
|
|
4
|
-
from ccproxy.auth.credentials_adapter import CredentialsAuthManager
|
|
5
4
|
from ccproxy.auth.dependencies import (
|
|
6
5
|
AccessTokenDep,
|
|
7
6
|
AuthManagerDep,
|
|
8
7
|
RequiredAuthDep,
|
|
9
8
|
get_access_token,
|
|
10
9
|
get_auth_manager,
|
|
11
|
-
get_bearer_auth_manager,
|
|
12
|
-
get_credentials_auth_manager,
|
|
13
10
|
require_auth,
|
|
14
11
|
)
|
|
15
12
|
from ccproxy.auth.exceptions import (
|
|
@@ -22,32 +19,22 @@ from ccproxy.auth.exceptions import (
|
|
|
22
19
|
CredentialsStorageError,
|
|
23
20
|
InsufficientPermissionsError,
|
|
24
21
|
InvalidTokenError,
|
|
25
|
-
OAuthCallbackError,
|
|
26
22
|
OAuthError,
|
|
27
|
-
OAuthLoginError,
|
|
28
23
|
OAuthTokenRefreshError,
|
|
29
24
|
)
|
|
30
|
-
from ccproxy.auth.manager import AuthManager
|
|
25
|
+
from ccproxy.auth.manager import AuthManager
|
|
31
26
|
from ccproxy.auth.storage import (
|
|
32
|
-
JsonFileTokenStorage,
|
|
33
|
-
KeyringTokenStorage,
|
|
34
27
|
TokenStorage,
|
|
35
28
|
)
|
|
36
|
-
from ccproxy.services.credentials.manager import CredentialsManager
|
|
37
29
|
|
|
38
30
|
|
|
39
31
|
__all__ = [
|
|
40
|
-
# Manager
|
|
32
|
+
# Manager interface
|
|
41
33
|
"AuthManager",
|
|
42
|
-
"BaseAuthManager",
|
|
43
34
|
# Implementations
|
|
44
35
|
"BearerTokenAuthManager",
|
|
45
|
-
"CredentialsAuthManager",
|
|
46
|
-
"CredentialsManager",
|
|
47
36
|
# Storage interfaces and implementations
|
|
48
37
|
"TokenStorage",
|
|
49
|
-
"JsonFileTokenStorage",
|
|
50
|
-
"KeyringTokenStorage",
|
|
51
38
|
# Exceptions
|
|
52
39
|
"AuthenticationError",
|
|
53
40
|
"AuthenticationRequiredError",
|
|
@@ -58,14 +45,10 @@ __all__ = [
|
|
|
58
45
|
"CredentialsStorageError",
|
|
59
46
|
"InvalidTokenError",
|
|
60
47
|
"InsufficientPermissionsError",
|
|
61
|
-
"OAuthCallbackError",
|
|
62
48
|
"OAuthError",
|
|
63
|
-
"OAuthLoginError",
|
|
64
49
|
"OAuthTokenRefreshError",
|
|
65
50
|
# Dependencies
|
|
66
51
|
"get_auth_manager",
|
|
67
|
-
"get_bearer_auth_manager",
|
|
68
|
-
"get_credentials_auth_manager",
|
|
69
52
|
"require_auth",
|
|
70
53
|
"get_access_token",
|
|
71
54
|
# Type aliases
|
ccproxy/auth/bearer.py
CHANGED
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
from typing import Any
|
|
4
4
|
|
|
5
5
|
from ccproxy.auth.exceptions import AuthenticationError
|
|
6
|
-
from ccproxy.auth.
|
|
7
|
-
from ccproxy.auth.
|
|
6
|
+
from ccproxy.auth.models.credentials import BaseCredentials
|
|
7
|
+
from ccproxy.auth.oauth.protocol import StandardProfileFields
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
class BearerTokenAuthManager
|
|
10
|
+
class BearerTokenAuthManager:
|
|
11
11
|
"""Authentication manager for static bearer tokens."""
|
|
12
12
|
|
|
13
13
|
def __init__(self, token: str) -> None:
|
|
@@ -33,12 +33,8 @@ class BearerTokenAuthManager(BaseAuthManager):
|
|
|
33
33
|
raise AuthenticationError("No bearer token available")
|
|
34
34
|
return self.token
|
|
35
35
|
|
|
36
|
-
async def get_credentials(self) ->
|
|
37
|
-
"""
|
|
38
|
-
|
|
39
|
-
Raises:
|
|
40
|
-
AuthenticationError: Bearer tokens don't support full credentials
|
|
41
|
-
"""
|
|
36
|
+
async def get_credentials(self) -> BaseCredentials:
|
|
37
|
+
"""Bearer tokens do not expose structured credentials."""
|
|
42
38
|
raise AuthenticationError(
|
|
43
39
|
"Bearer token authentication doesn't support full credentials"
|
|
44
40
|
)
|
|
@@ -51,12 +47,8 @@ class BearerTokenAuthManager(BaseAuthManager):
|
|
|
51
47
|
"""
|
|
52
48
|
return bool(self.token)
|
|
53
49
|
|
|
54
|
-
async def get_user_profile(self) ->
|
|
55
|
-
"""
|
|
56
|
-
|
|
57
|
-
Returns:
|
|
58
|
-
None - bearer tokens don't support user profiles
|
|
59
|
-
"""
|
|
50
|
+
async def get_user_profile(self) -> StandardProfileFields | None:
|
|
51
|
+
"""Return ``None`` because bearer tokens have no profile context."""
|
|
60
52
|
return None
|
|
61
53
|
|
|
62
54
|
async def __aenter__(self) -> "BearerTokenAuthManager":
|
|
@@ -66,3 +58,21 @@ class BearerTokenAuthManager(BaseAuthManager):
|
|
|
66
58
|
async def __aexit__(self, exc_type: Any, exc_val: Any, exc_tb: Any) -> None:
|
|
67
59
|
"""Async context manager exit."""
|
|
68
60
|
pass
|
|
61
|
+
|
|
62
|
+
# ==================== Provider-Generic Methods ====================
|
|
63
|
+
|
|
64
|
+
async def validate_credentials(self) -> bool:
|
|
65
|
+
"""Validate that credentials are available and valid.
|
|
66
|
+
|
|
67
|
+
Returns:
|
|
68
|
+
True if credentials are valid, False otherwise
|
|
69
|
+
"""
|
|
70
|
+
return bool(self.token)
|
|
71
|
+
|
|
72
|
+
def get_provider_name(self) -> str:
|
|
73
|
+
"""Get the provider name for logging.
|
|
74
|
+
|
|
75
|
+
Returns:
|
|
76
|
+
Provider name string
|
|
77
|
+
"""
|
|
78
|
+
return "bearer-token"
|