ccproxy-api 0.1.7__py3-none-any.whl → 0.2.0a4__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.0a4.dist-info/METADATA +212 -0
- ccproxy_api-0.2.0a4.dist-info/RECORD +417 -0
- {ccproxy_api-0.1.7.dist-info → ccproxy_api-0.2.0a4.dist-info}/WHEEL +1 -1
- ccproxy_api-0.2.0a4.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.0a4.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,252 +0,0 @@
|
|
|
1
|
-
"""Service for automatically detecting Codex CLI headers at startup."""
|
|
2
|
-
|
|
3
|
-
from __future__ import annotations
|
|
4
|
-
|
|
5
|
-
import asyncio
|
|
6
|
-
import json
|
|
7
|
-
import os
|
|
8
|
-
import socket
|
|
9
|
-
import subprocess
|
|
10
|
-
from pathlib import Path
|
|
11
|
-
from typing import Any
|
|
12
|
-
|
|
13
|
-
import structlog
|
|
14
|
-
from fastapi import FastAPI, Request, Response
|
|
15
|
-
|
|
16
|
-
from ccproxy.config.discovery import get_ccproxy_cache_dir
|
|
17
|
-
from ccproxy.config.settings import Settings
|
|
18
|
-
from ccproxy.models.detection import (
|
|
19
|
-
CodexCacheData,
|
|
20
|
-
CodexHeaders,
|
|
21
|
-
CodexInstructionsData,
|
|
22
|
-
)
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
logger = structlog.get_logger(__name__)
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
class CodexDetectionService:
|
|
29
|
-
"""Service for automatically detecting Codex CLI headers at startup."""
|
|
30
|
-
|
|
31
|
-
def __init__(self, settings: Settings) -> None:
|
|
32
|
-
"""Initialize Codex detection service."""
|
|
33
|
-
self.settings = settings
|
|
34
|
-
self.cache_dir = get_ccproxy_cache_dir()
|
|
35
|
-
self.cache_dir.mkdir(parents=True, exist_ok=True)
|
|
36
|
-
self._cached_data: CodexCacheData | None = None
|
|
37
|
-
|
|
38
|
-
async def initialize_detection(self) -> CodexCacheData:
|
|
39
|
-
"""Initialize Codex detection at startup."""
|
|
40
|
-
try:
|
|
41
|
-
# Get current Codex version
|
|
42
|
-
current_version = await self._get_codex_version()
|
|
43
|
-
|
|
44
|
-
# Try to load from cache first
|
|
45
|
-
detected_data = self._load_from_cache(current_version)
|
|
46
|
-
cached = detected_data is not None
|
|
47
|
-
if cached:
|
|
48
|
-
logger.debug("detection_codex_headers_debug", version=current_version)
|
|
49
|
-
else:
|
|
50
|
-
# No cache or version changed - detect fresh
|
|
51
|
-
detected_data = await self._detect_codex_headers(current_version)
|
|
52
|
-
# Cache the results
|
|
53
|
-
self._save_to_cache(detected_data)
|
|
54
|
-
|
|
55
|
-
self._cached_data = detected_data
|
|
56
|
-
|
|
57
|
-
logger.info(
|
|
58
|
-
"detection_codex_headers_completed",
|
|
59
|
-
version=current_version,
|
|
60
|
-
cached=cached,
|
|
61
|
-
)
|
|
62
|
-
|
|
63
|
-
# TODO: add proper testing without codex cli installed
|
|
64
|
-
if detected_data is None:
|
|
65
|
-
raise ValueError("Codex detection failed")
|
|
66
|
-
return detected_data
|
|
67
|
-
|
|
68
|
-
except Exception as e:
|
|
69
|
-
logger.warning("detection_codex_headers_failed", fallback=True, error=e)
|
|
70
|
-
# Return fallback data
|
|
71
|
-
fallback_data = self._get_fallback_data()
|
|
72
|
-
self._cached_data = fallback_data
|
|
73
|
-
return fallback_data
|
|
74
|
-
|
|
75
|
-
def get_cached_data(self) -> CodexCacheData | None:
|
|
76
|
-
"""Get currently cached detection data."""
|
|
77
|
-
return self._cached_data
|
|
78
|
-
|
|
79
|
-
async def _get_codex_version(self) -> str:
|
|
80
|
-
"""Get Codex CLI version."""
|
|
81
|
-
try:
|
|
82
|
-
result = subprocess.run(
|
|
83
|
-
["codex", "--version"],
|
|
84
|
-
capture_output=True,
|
|
85
|
-
text=True,
|
|
86
|
-
timeout=10,
|
|
87
|
-
)
|
|
88
|
-
if result.returncode == 0:
|
|
89
|
-
# Extract version from output like "codex 0.21.0"
|
|
90
|
-
version_line = result.stdout.strip()
|
|
91
|
-
if " " in version_line:
|
|
92
|
-
# Handle "codex 0.21.0" format - extract just the version number
|
|
93
|
-
return version_line.split()[-1]
|
|
94
|
-
return version_line
|
|
95
|
-
else:
|
|
96
|
-
raise RuntimeError(f"Codex version command failed: {result.stderr}")
|
|
97
|
-
|
|
98
|
-
except (subprocess.TimeoutExpired, FileNotFoundError, RuntimeError) as e:
|
|
99
|
-
logger.warning("codex_version_detection_failed", error=str(e))
|
|
100
|
-
return "unknown"
|
|
101
|
-
|
|
102
|
-
async def _detect_codex_headers(self, version: str) -> CodexCacheData:
|
|
103
|
-
"""Execute Codex CLI with proxy to capture headers and instructions."""
|
|
104
|
-
# Data captured from the request
|
|
105
|
-
captured_data: dict[str, Any] = {}
|
|
106
|
-
|
|
107
|
-
async def capture_handler(request: Request) -> Response:
|
|
108
|
-
"""Capture the Codex CLI request."""
|
|
109
|
-
captured_data["headers"] = dict(request.headers)
|
|
110
|
-
captured_data["body"] = await request.body()
|
|
111
|
-
# Return a mock response to satisfy Codex CLI
|
|
112
|
-
return Response(
|
|
113
|
-
content='{"choices": [{"message": {"content": "Test response"}}]}',
|
|
114
|
-
media_type="application/json",
|
|
115
|
-
status_code=200,
|
|
116
|
-
)
|
|
117
|
-
|
|
118
|
-
# Create temporary FastAPI app
|
|
119
|
-
temp_app = FastAPI()
|
|
120
|
-
temp_app.post("/backend-api/codex/responses")(capture_handler)
|
|
121
|
-
|
|
122
|
-
# Find available port
|
|
123
|
-
sock = socket.socket()
|
|
124
|
-
sock.bind(("", 0))
|
|
125
|
-
port = sock.getsockname()[1]
|
|
126
|
-
sock.close()
|
|
127
|
-
|
|
128
|
-
# Start server in background
|
|
129
|
-
from uvicorn import Config, Server
|
|
130
|
-
|
|
131
|
-
config = Config(temp_app, host="127.0.0.1", port=port, log_level="error")
|
|
132
|
-
server = Server(config)
|
|
133
|
-
|
|
134
|
-
logger.debug("start")
|
|
135
|
-
server_task = asyncio.create_task(server.serve())
|
|
136
|
-
|
|
137
|
-
try:
|
|
138
|
-
# Wait for server to start
|
|
139
|
-
await asyncio.sleep(0.5)
|
|
140
|
-
|
|
141
|
-
# Execute Codex CLI with proxy
|
|
142
|
-
env = {
|
|
143
|
-
**dict(os.environ),
|
|
144
|
-
"OPENAI_BASE_URL": f"http://127.0.0.1:{port}/backend-api/codex",
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
process = await asyncio.create_subprocess_exec(
|
|
148
|
-
"codex",
|
|
149
|
-
"exec",
|
|
150
|
-
"test",
|
|
151
|
-
env=env,
|
|
152
|
-
stdout=asyncio.subprocess.PIPE,
|
|
153
|
-
stderr=asyncio.subprocess.PIPE,
|
|
154
|
-
)
|
|
155
|
-
# stderr = ""
|
|
156
|
-
# if process.stderr:
|
|
157
|
-
# stderr = await process.stderr.read(128)
|
|
158
|
-
# stdout = ""
|
|
159
|
-
# if process.stdout:
|
|
160
|
-
# stdout = await process.stdout.read(128)
|
|
161
|
-
# logger.warning("rcecdy", stderr=stderr, stdout=stdout)
|
|
162
|
-
|
|
163
|
-
# Wait for process with timeout
|
|
164
|
-
try:
|
|
165
|
-
await asyncio.wait_for(process.wait(), timeout=300)
|
|
166
|
-
except TimeoutError:
|
|
167
|
-
process.kill()
|
|
168
|
-
await process.wait()
|
|
169
|
-
|
|
170
|
-
# Stop server
|
|
171
|
-
server.should_exit = True
|
|
172
|
-
await server_task
|
|
173
|
-
|
|
174
|
-
if not captured_data:
|
|
175
|
-
raise RuntimeError("Failed to capture Codex CLI request")
|
|
176
|
-
|
|
177
|
-
# Extract headers and instructions
|
|
178
|
-
headers = self._extract_headers(captured_data["headers"])
|
|
179
|
-
instructions = self._extract_instructions(captured_data["body"])
|
|
180
|
-
|
|
181
|
-
return CodexCacheData(
|
|
182
|
-
codex_version=version, headers=headers, instructions=instructions
|
|
183
|
-
)
|
|
184
|
-
|
|
185
|
-
except Exception as e:
|
|
186
|
-
# Ensure server is stopped
|
|
187
|
-
server.should_exit = True
|
|
188
|
-
if not server_task.done():
|
|
189
|
-
await server_task
|
|
190
|
-
raise
|
|
191
|
-
|
|
192
|
-
def _load_from_cache(self, version: str) -> CodexCacheData | None:
|
|
193
|
-
"""Load cached data for specific Codex version."""
|
|
194
|
-
cache_file = self.cache_dir / f"codex_headers_{version}.json"
|
|
195
|
-
|
|
196
|
-
if not cache_file.exists():
|
|
197
|
-
return None
|
|
198
|
-
|
|
199
|
-
try:
|
|
200
|
-
with cache_file.open("r") as f:
|
|
201
|
-
data = json.load(f)
|
|
202
|
-
return CodexCacheData.model_validate(data)
|
|
203
|
-
except Exception:
|
|
204
|
-
return None
|
|
205
|
-
|
|
206
|
-
def _save_to_cache(self, data: CodexCacheData) -> None:
|
|
207
|
-
"""Save detection data to cache."""
|
|
208
|
-
cache_file = self.cache_dir / f"codex_headers_{data.codex_version}.json"
|
|
209
|
-
|
|
210
|
-
try:
|
|
211
|
-
with cache_file.open("w") as f:
|
|
212
|
-
json.dump(data.model_dump(), f, indent=2, default=str)
|
|
213
|
-
logger.debug(
|
|
214
|
-
"cache_saved", file=str(cache_file), version=data.codex_version
|
|
215
|
-
)
|
|
216
|
-
except Exception as e:
|
|
217
|
-
logger.warning("cache_save_failed", file=str(cache_file), error=str(e))
|
|
218
|
-
|
|
219
|
-
def _extract_headers(self, headers: dict[str, str]) -> CodexHeaders:
|
|
220
|
-
"""Extract Codex CLI headers from captured request."""
|
|
221
|
-
try:
|
|
222
|
-
return CodexHeaders.model_validate(headers)
|
|
223
|
-
except Exception as e:
|
|
224
|
-
logger.error("header_extraction_failed", error=str(e))
|
|
225
|
-
raise ValueError(f"Failed to extract required headers: {e}") from e
|
|
226
|
-
|
|
227
|
-
def _extract_instructions(self, body: bytes) -> CodexInstructionsData:
|
|
228
|
-
"""Extract instructions from captured request body."""
|
|
229
|
-
try:
|
|
230
|
-
data = json.loads(body.decode("utf-8"))
|
|
231
|
-
instructions_content = data.get("instructions")
|
|
232
|
-
|
|
233
|
-
if instructions_content is None:
|
|
234
|
-
raise ValueError("No instructions field found in request body")
|
|
235
|
-
|
|
236
|
-
return CodexInstructionsData(instructions_field=instructions_content)
|
|
237
|
-
|
|
238
|
-
except Exception as e:
|
|
239
|
-
logger.error("instructions_extraction_failed", error=str(e))
|
|
240
|
-
raise ValueError(f"Failed to extract instructions: {e}") from e
|
|
241
|
-
|
|
242
|
-
def _get_fallback_data(self) -> CodexCacheData:
|
|
243
|
-
"""Get fallback data when detection fails."""
|
|
244
|
-
logger.warning("using_fallback_codex_data")
|
|
245
|
-
|
|
246
|
-
# Load fallback data from package data file
|
|
247
|
-
package_data_file = (
|
|
248
|
-
Path(__file__).parent.parent / "data" / "codex_headers_fallback.json"
|
|
249
|
-
)
|
|
250
|
-
with package_data_file.open("r") as f:
|
|
251
|
-
fallback_data_dict = json.load(f)
|
|
252
|
-
return CodexCacheData.model_validate(fallback_data_dict)
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
"""Credentials management package."""
|
|
2
|
-
|
|
3
|
-
from ccproxy.auth.exceptions import (
|
|
4
|
-
CredentialsError,
|
|
5
|
-
CredentialsExpiredError,
|
|
6
|
-
CredentialsInvalidError,
|
|
7
|
-
CredentialsNotFoundError,
|
|
8
|
-
CredentialsStorageError,
|
|
9
|
-
OAuthCallbackError,
|
|
10
|
-
OAuthError,
|
|
11
|
-
OAuthLoginError,
|
|
12
|
-
OAuthTokenRefreshError,
|
|
13
|
-
)
|
|
14
|
-
from ccproxy.auth.models import (
|
|
15
|
-
AccountInfo,
|
|
16
|
-
ClaudeCredentials,
|
|
17
|
-
OAuthToken,
|
|
18
|
-
OrganizationInfo,
|
|
19
|
-
UserProfile,
|
|
20
|
-
)
|
|
21
|
-
from ccproxy.auth.storage import JsonFileTokenStorage as JsonFileStorage
|
|
22
|
-
from ccproxy.auth.storage import TokenStorage as CredentialsStorageBackend
|
|
23
|
-
from ccproxy.services.credentials.config import CredentialsConfig, OAuthConfig
|
|
24
|
-
from ccproxy.services.credentials.manager import CredentialsManager
|
|
25
|
-
from ccproxy.services.credentials.oauth_client import OAuthClient
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
__all__ = [
|
|
29
|
-
# Manager
|
|
30
|
-
"CredentialsManager",
|
|
31
|
-
# Config
|
|
32
|
-
"CredentialsConfig",
|
|
33
|
-
"OAuthConfig",
|
|
34
|
-
# Models
|
|
35
|
-
"ClaudeCredentials",
|
|
36
|
-
"OAuthToken",
|
|
37
|
-
"OrganizationInfo",
|
|
38
|
-
"AccountInfo",
|
|
39
|
-
"UserProfile",
|
|
40
|
-
# Storage
|
|
41
|
-
"CredentialsStorageBackend",
|
|
42
|
-
"JsonFileStorage",
|
|
43
|
-
# OAuth
|
|
44
|
-
"OAuthClient",
|
|
45
|
-
# Exceptions
|
|
46
|
-
"CredentialsError",
|
|
47
|
-
"CredentialsNotFoundError",
|
|
48
|
-
"CredentialsInvalidError",
|
|
49
|
-
"CredentialsExpiredError",
|
|
50
|
-
"CredentialsStorageError",
|
|
51
|
-
"OAuthError",
|
|
52
|
-
"OAuthLoginError",
|
|
53
|
-
"OAuthTokenRefreshError",
|
|
54
|
-
"OAuthCallbackError",
|
|
55
|
-
]
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
"""Configuration for credentials and OAuth."""
|
|
2
|
-
|
|
3
|
-
import os
|
|
4
|
-
|
|
5
|
-
from pydantic import BaseModel, Field
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
def _get_default_storage_paths() -> list[str]:
|
|
9
|
-
"""Get default storage paths, with test override support."""
|
|
10
|
-
# Allow tests to override credential paths
|
|
11
|
-
if os.getenv("CCPROXY_TEST_MODE") == "true":
|
|
12
|
-
# Use a test-specific location that won't pollute real credentials
|
|
13
|
-
return [
|
|
14
|
-
"/tmp/ccproxy-test/.config/claude/.credentials.json",
|
|
15
|
-
"/tmp/ccproxy-test/.claude/.credentials.json",
|
|
16
|
-
]
|
|
17
|
-
|
|
18
|
-
return [
|
|
19
|
-
"~/.config/claude/.credentials.json", # Alternative legacy location
|
|
20
|
-
"~/.claude/.credentials.json", # Legacy location
|
|
21
|
-
"~/.config/ccproxy/credentials.json", # location in app config
|
|
22
|
-
]
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
class OAuthConfig(BaseModel):
|
|
26
|
-
"""OAuth configuration settings."""
|
|
27
|
-
|
|
28
|
-
base_url: str = Field(
|
|
29
|
-
default="https://console.anthropic.com",
|
|
30
|
-
description="Base URL for OAuth API endpoints",
|
|
31
|
-
)
|
|
32
|
-
beta_version: str = Field(
|
|
33
|
-
default="oauth-2025-04-20",
|
|
34
|
-
description="OAuth beta version header",
|
|
35
|
-
)
|
|
36
|
-
token_url: str = Field(
|
|
37
|
-
default="https://console.anthropic.com/v1/oauth/token",
|
|
38
|
-
description="OAuth token endpoint URL",
|
|
39
|
-
)
|
|
40
|
-
authorize_url: str = Field(
|
|
41
|
-
default="https://claude.ai/oauth/authorize",
|
|
42
|
-
description="OAuth authorization endpoint URL",
|
|
43
|
-
)
|
|
44
|
-
profile_url: str = Field(
|
|
45
|
-
default="https://api.anthropic.com/api/oauth/profile",
|
|
46
|
-
description="OAuth profile endpoint URL",
|
|
47
|
-
)
|
|
48
|
-
client_id: str = Field(
|
|
49
|
-
default="9d1c250a-e61b-44d9-88ed-5944d1962f5e",
|
|
50
|
-
description="OAuth client ID",
|
|
51
|
-
)
|
|
52
|
-
redirect_uri: str = Field(
|
|
53
|
-
default="http://localhost:54545/callback",
|
|
54
|
-
description="OAuth redirect URI",
|
|
55
|
-
)
|
|
56
|
-
scopes: list[str] = Field(
|
|
57
|
-
default_factory=lambda: [
|
|
58
|
-
"org:create_api_key",
|
|
59
|
-
"user:profile",
|
|
60
|
-
"user:inference",
|
|
61
|
-
],
|
|
62
|
-
description="OAuth scopes to request",
|
|
63
|
-
)
|
|
64
|
-
request_timeout: int = Field(
|
|
65
|
-
default=30,
|
|
66
|
-
description="Timeout in seconds for OAuth requests",
|
|
67
|
-
)
|
|
68
|
-
user_agent: str = Field(
|
|
69
|
-
default="Claude-Code/1.0.43",
|
|
70
|
-
description="User agent string for OAuth requests",
|
|
71
|
-
)
|
|
72
|
-
callback_timeout: int = Field(
|
|
73
|
-
default=300,
|
|
74
|
-
description="Timeout in seconds for OAuth callback",
|
|
75
|
-
ge=60,
|
|
76
|
-
le=600,
|
|
77
|
-
)
|
|
78
|
-
callback_port: int = Field(
|
|
79
|
-
default=54545,
|
|
80
|
-
description="Port for OAuth callback server",
|
|
81
|
-
ge=1024,
|
|
82
|
-
le=65535,
|
|
83
|
-
)
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
class CredentialsConfig(BaseModel):
|
|
87
|
-
"""Configuration for credentials management."""
|
|
88
|
-
|
|
89
|
-
storage_paths: list[str] = Field(
|
|
90
|
-
default_factory=lambda: _get_default_storage_paths(),
|
|
91
|
-
description="Paths to search for credentials files",
|
|
92
|
-
)
|
|
93
|
-
oauth: OAuthConfig = Field(
|
|
94
|
-
default_factory=OAuthConfig,
|
|
95
|
-
description="OAuth configuration",
|
|
96
|
-
)
|
|
97
|
-
auto_refresh: bool = Field(
|
|
98
|
-
default=True,
|
|
99
|
-
description="Automatically refresh expired tokens",
|
|
100
|
-
)
|
|
101
|
-
refresh_buffer_seconds: int = Field(
|
|
102
|
-
default=300,
|
|
103
|
-
description="Refresh token this many seconds before expiry",
|
|
104
|
-
ge=0,
|
|
105
|
-
)
|