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
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
"""Request ID middleware for generating and tracking request IDs."""
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
from collections.abc import Awaitable, Callable, MutableMapping
|
|
4
4
|
from datetime import UTC, datetime
|
|
5
5
|
from typing import Any
|
|
6
6
|
|
|
7
|
-
import structlog
|
|
8
7
|
from fastapi import Request, Response
|
|
9
8
|
from starlette.middleware.base import BaseHTTPMiddleware
|
|
10
|
-
from starlette.types import ASGIApp
|
|
9
|
+
from starlette.types import ASGIApp, Receive, Send
|
|
11
10
|
|
|
12
|
-
from ccproxy.
|
|
11
|
+
from ccproxy.core.id_utils import generate_short_id
|
|
12
|
+
from ccproxy.core.logging import get_logger
|
|
13
|
+
from ccproxy.core.request_context import request_context
|
|
13
14
|
|
|
14
15
|
|
|
15
|
-
logger =
|
|
16
|
+
logger = get_logger(__name__)
|
|
16
17
|
|
|
17
18
|
|
|
18
19
|
class RequestIDMiddleware(BaseHTTPMiddleware):
|
|
@@ -26,7 +27,33 @@ class RequestIDMiddleware(BaseHTTPMiddleware):
|
|
|
26
27
|
"""
|
|
27
28
|
super().__init__(app)
|
|
28
29
|
|
|
29
|
-
async def
|
|
30
|
+
async def __call__(
|
|
31
|
+
self, scope: MutableMapping[str, Any], receive: Receive, send: Send
|
|
32
|
+
) -> None:
|
|
33
|
+
"""ASGI interface to inject request ID early."""
|
|
34
|
+
if scope["type"] == "http":
|
|
35
|
+
# Generate or extract request ID
|
|
36
|
+
headers_dict = dict(scope.get("headers", []))
|
|
37
|
+
request_id = (
|
|
38
|
+
headers_dict.get(b"x-request-id", b"").decode("utf-8")
|
|
39
|
+
or generate_short_id()
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
# Store in ASGI extensions for other middleware
|
|
43
|
+
if "extensions" not in scope:
|
|
44
|
+
scope["extensions"] = {}
|
|
45
|
+
scope["extensions"]["request_id"] = request_id
|
|
46
|
+
|
|
47
|
+
# If not in headers, add it
|
|
48
|
+
if b"x-request-id" not in headers_dict:
|
|
49
|
+
scope["headers"] = list(scope.get("headers", []))
|
|
50
|
+
scope["headers"].append((b"x-request-id", request_id.encode("utf-8")))
|
|
51
|
+
|
|
52
|
+
return await super().__call__(scope, receive, send)
|
|
53
|
+
|
|
54
|
+
async def dispatch(
|
|
55
|
+
self, request: Request, call_next: Callable[[Request], Awaitable[Response]]
|
|
56
|
+
) -> Response:
|
|
30
57
|
"""Process the request and add request ID/context.
|
|
31
58
|
|
|
32
59
|
Args:
|
|
@@ -37,18 +64,14 @@ class RequestIDMiddleware(BaseHTTPMiddleware):
|
|
|
37
64
|
The HTTP response
|
|
38
65
|
"""
|
|
39
66
|
# Generate or extract request ID
|
|
40
|
-
request_id = request.headers.get("x-request-id") or
|
|
67
|
+
request_id = request.headers.get("x-request-id") or generate_short_id()
|
|
41
68
|
|
|
42
69
|
# Generate datetime for consistent logging across all layers
|
|
43
70
|
log_timestamp = datetime.now(UTC)
|
|
44
71
|
|
|
45
|
-
# Get DuckDB storage from app state if available
|
|
46
|
-
storage = getattr(request.app.state, "duckdb_storage", None)
|
|
47
|
-
|
|
48
72
|
# Use the proper request context manager to ensure __aexit__ is called
|
|
49
73
|
async with request_context(
|
|
50
74
|
request_id=request_id,
|
|
51
|
-
storage=storage,
|
|
52
75
|
log_timestamp=log_timestamp,
|
|
53
76
|
method=request.method,
|
|
54
77
|
path=str(request.url.path),
|
|
@@ -61,14 +84,10 @@ class RequestIDMiddleware(BaseHTTPMiddleware):
|
|
|
61
84
|
request.state.request_id = request_id
|
|
62
85
|
request.state.context = ctx
|
|
63
86
|
|
|
64
|
-
# Add DuckDB storage to context if available
|
|
65
|
-
if hasattr(request.state, "duckdb_storage"):
|
|
66
|
-
ctx.storage = request.state.duckdb_storage
|
|
67
|
-
|
|
68
87
|
# Process the request
|
|
69
88
|
response = await call_next(request)
|
|
70
89
|
|
|
71
90
|
# Add request ID to response headers
|
|
72
91
|
response.headers["x-request-id"] = request_id
|
|
73
92
|
|
|
74
|
-
return response
|
|
93
|
+
return response
|
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
"""Streaming response wrapper for hook emission.
|
|
2
|
+
|
|
3
|
+
This module provides a wrapper for streaming responses that emits
|
|
4
|
+
REQUEST_COMPLETED hook event when the stream actually completes.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import asyncio
|
|
10
|
+
import json
|
|
11
|
+
import time
|
|
12
|
+
from collections.abc import AsyncGenerator, AsyncIterator
|
|
13
|
+
from datetime import datetime
|
|
14
|
+
from typing import TYPE_CHECKING, Any
|
|
15
|
+
|
|
16
|
+
from fastapi.responses import StreamingResponse
|
|
17
|
+
|
|
18
|
+
from ccproxy.core.logging import get_logger
|
|
19
|
+
from ccproxy.core.plugins.hooks import HookContext, HookEvent
|
|
20
|
+
from ccproxy.utils.headers import extract_response_headers
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
if TYPE_CHECKING:
|
|
24
|
+
from ccproxy.core.plugins.hooks import HookManager
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
logger = get_logger(__name__)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class StreamingResponseWithHooks(StreamingResponse):
|
|
31
|
+
"""Streaming response wrapper that emits hooks on completion.
|
|
32
|
+
|
|
33
|
+
This wrapper ensures REQUEST_COMPLETED is emitted when streaming
|
|
34
|
+
actually finishes, not when the response is initially created.
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
def __init__(
|
|
38
|
+
self,
|
|
39
|
+
content: AsyncGenerator[bytes, None] | AsyncIterator[bytes],
|
|
40
|
+
hook_manager: HookManager | None,
|
|
41
|
+
request_id: str,
|
|
42
|
+
request_data: dict[str, Any],
|
|
43
|
+
start_time: float,
|
|
44
|
+
status_code: int = 200,
|
|
45
|
+
request_metadata: dict[str, Any] | None = None,
|
|
46
|
+
origin: str = "client",
|
|
47
|
+
is_sse: bool = False,
|
|
48
|
+
**kwargs: Any,
|
|
49
|
+
) -> None:
|
|
50
|
+
"""Initialize streaming response with hook emission.
|
|
51
|
+
|
|
52
|
+
Args:
|
|
53
|
+
content: The async generator producing streaming content
|
|
54
|
+
hook_manager: Hook manager for emitting events
|
|
55
|
+
request_id: Request ID for correlation
|
|
56
|
+
request_data: Original request data for context
|
|
57
|
+
start_time: Request start timestamp
|
|
58
|
+
status_code: HTTP status code for the response
|
|
59
|
+
request_metadata: Metadata from RequestContext (includes tokens, cost, etc.)
|
|
60
|
+
**kwargs: Additional arguments passed to StreamingResponse
|
|
61
|
+
"""
|
|
62
|
+
self.hook_manager = hook_manager
|
|
63
|
+
self.request_id = request_id
|
|
64
|
+
self.request_data = request_data
|
|
65
|
+
self.request_metadata = request_metadata or {}
|
|
66
|
+
self.start_time = start_time
|
|
67
|
+
self.origin = origin
|
|
68
|
+
self.is_sse = is_sse
|
|
69
|
+
|
|
70
|
+
# Wrap the content generator to add hook emission
|
|
71
|
+
wrapped_content = self._wrap_with_hooks(content, status_code)
|
|
72
|
+
|
|
73
|
+
super().__init__(wrapped_content, status_code=status_code, **kwargs)
|
|
74
|
+
|
|
75
|
+
async def _wrap_with_hooks(
|
|
76
|
+
self,
|
|
77
|
+
content: AsyncGenerator[bytes, None] | AsyncIterator[bytes],
|
|
78
|
+
status_code: int,
|
|
79
|
+
) -> AsyncGenerator[bytes, None]:
|
|
80
|
+
"""Wrap content generator with hook emission on completion.
|
|
81
|
+
|
|
82
|
+
Args:
|
|
83
|
+
content: The original content generator
|
|
84
|
+
status_code: HTTP status code
|
|
85
|
+
|
|
86
|
+
Yields:
|
|
87
|
+
bytes: Content chunks from the original generator
|
|
88
|
+
"""
|
|
89
|
+
error_occurred: str | None = None
|
|
90
|
+
error_type_name: str | None = None
|
|
91
|
+
final_status = status_code
|
|
92
|
+
# Collect chunks for HTTP_RESPONSE hook
|
|
93
|
+
collected_chunks: list[bytes] = []
|
|
94
|
+
|
|
95
|
+
closed_by: str | None = None
|
|
96
|
+
|
|
97
|
+
try:
|
|
98
|
+
# Stream all content from the original generator
|
|
99
|
+
async for chunk in content:
|
|
100
|
+
collected_chunks.append(chunk) # Collect for HTTP hook
|
|
101
|
+
yield chunk
|
|
102
|
+
|
|
103
|
+
except GeneratorExit:
|
|
104
|
+
# Client disconnected - still emit completion hook
|
|
105
|
+
error_occurred = "client_disconnected"
|
|
106
|
+
error_type_name = "GeneratorExit"
|
|
107
|
+
closed_by = "client"
|
|
108
|
+
return
|
|
109
|
+
|
|
110
|
+
except asyncio.CancelledError as e:
|
|
111
|
+
error_occurred = "client_cancelled"
|
|
112
|
+
error_type_name = type(e).__name__
|
|
113
|
+
closed_by = "client"
|
|
114
|
+
return
|
|
115
|
+
|
|
116
|
+
except Exception as e:
|
|
117
|
+
# Error during streaming
|
|
118
|
+
error_occurred = str(e)
|
|
119
|
+
error_type_name = type(e).__name__
|
|
120
|
+
final_status = 500
|
|
121
|
+
closed_by = "server_error"
|
|
122
|
+
raise
|
|
123
|
+
|
|
124
|
+
finally:
|
|
125
|
+
end_time = time.time()
|
|
126
|
+
duration = end_time - self.start_time
|
|
127
|
+
|
|
128
|
+
# Emit HTTP_RESPONSE hook first with collected body, then REQUEST_COMPLETED
|
|
129
|
+
if self.hook_manager:
|
|
130
|
+
try:
|
|
131
|
+
# First emit HTTP_RESPONSE hook with collected streaming body
|
|
132
|
+
await self._emit_http_response_hook(
|
|
133
|
+
collected_chunks, final_status, end_time
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
# Then emit REQUEST_COMPLETED hook (existing behavior)
|
|
137
|
+
completion_data = {
|
|
138
|
+
"request_id": self.request_id,
|
|
139
|
+
"duration": duration,
|
|
140
|
+
"response_status": final_status,
|
|
141
|
+
"streaming_completed": True,
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
# Include original request data
|
|
145
|
+
if self.request_data:
|
|
146
|
+
completion_data.update(
|
|
147
|
+
{
|
|
148
|
+
"method": self.request_data.get("method"),
|
|
149
|
+
"url": self.request_data.get("url"),
|
|
150
|
+
"headers": self.request_data.get("headers"),
|
|
151
|
+
}
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
# Add error info if an error occurred
|
|
155
|
+
if error_occurred:
|
|
156
|
+
completion_data["error"] = error_occurred
|
|
157
|
+
event = HookEvent.REQUEST_FAILED
|
|
158
|
+
else:
|
|
159
|
+
event = HookEvent.REQUEST_COMPLETED
|
|
160
|
+
|
|
161
|
+
# Merge request metadata (tokens, cost, etc.) into hook metadata
|
|
162
|
+
hook_metadata = {"request_id": self.request_id}
|
|
163
|
+
hook_metadata.update(self.request_metadata)
|
|
164
|
+
|
|
165
|
+
hook_context = HookContext(
|
|
166
|
+
event=event,
|
|
167
|
+
timestamp=datetime.fromtimestamp(end_time),
|
|
168
|
+
data=completion_data,
|
|
169
|
+
metadata=hook_metadata,
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
await self.hook_manager.emit_with_context(hook_context)
|
|
173
|
+
|
|
174
|
+
except Exception:
|
|
175
|
+
# Silently ignore hook emission errors to avoid breaking the stream
|
|
176
|
+
pass
|
|
177
|
+
|
|
178
|
+
success = error_occurred is None
|
|
179
|
+
body_size = sum(len(chunk) for chunk in collected_chunks)
|
|
180
|
+
log_fields: dict[str, Any] = {
|
|
181
|
+
"request_id": self.request_id,
|
|
182
|
+
"method": self.request_data.get("method"),
|
|
183
|
+
"url": self.request_data.get("url"),
|
|
184
|
+
"origin": self.origin,
|
|
185
|
+
"status_code": final_status,
|
|
186
|
+
"duration_ms": round(duration * 1000, 3),
|
|
187
|
+
"streaming": True,
|
|
188
|
+
"success": success,
|
|
189
|
+
"category": "http",
|
|
190
|
+
"has_body": body_size > 0,
|
|
191
|
+
"body_size": body_size,
|
|
192
|
+
}
|
|
193
|
+
if not success and error_type_name:
|
|
194
|
+
log_fields["error_type"] = error_type_name
|
|
195
|
+
if not closed_by:
|
|
196
|
+
closed_by = "server"
|
|
197
|
+
log_fields["closed_by"] = closed_by
|
|
198
|
+
if not success and error_occurred:
|
|
199
|
+
log_fields["error_reason"] = error_occurred
|
|
200
|
+
|
|
201
|
+
# Propagate metadata for downstream consumers (e.g., upstream logging)
|
|
202
|
+
try:
|
|
203
|
+
self.request_metadata["stream_closed_by"] = closed_by
|
|
204
|
+
if not success and error_occurred:
|
|
205
|
+
self.request_metadata["stream_error_reason"] = error_occurred
|
|
206
|
+
if error_type_name:
|
|
207
|
+
self.request_metadata["stream_error_type"] = error_type_name
|
|
208
|
+
except Exception:
|
|
209
|
+
# Metadata propagation is best-effort
|
|
210
|
+
pass
|
|
211
|
+
|
|
212
|
+
if self.is_sse:
|
|
213
|
+
logger.info("sse_connection_ended", **log_fields)
|
|
214
|
+
else:
|
|
215
|
+
logger.info("request_completed", **log_fields)
|
|
216
|
+
|
|
217
|
+
async def _emit_http_response_hook(
|
|
218
|
+
self, collected_chunks: list[bytes], status_code: int, end_time: float
|
|
219
|
+
) -> None:
|
|
220
|
+
"""Emit HTTP_RESPONSE hook with collected streaming response body.
|
|
221
|
+
|
|
222
|
+
Args:
|
|
223
|
+
collected_chunks: All chunks collected from the stream
|
|
224
|
+
status_code: Final HTTP status code
|
|
225
|
+
end_time: Timestamp when streaming completed
|
|
226
|
+
"""
|
|
227
|
+
try:
|
|
228
|
+
# Combine all chunks to get full response body
|
|
229
|
+
full_response_body = b"".join(collected_chunks)
|
|
230
|
+
|
|
231
|
+
# Build HTTP response context
|
|
232
|
+
http_response_context = {
|
|
233
|
+
"request_id": self.request_id,
|
|
234
|
+
"status_code": status_code,
|
|
235
|
+
"is_client_response": True, # Distinguish from provider responses
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
# Include request data for context
|
|
239
|
+
if self.request_data:
|
|
240
|
+
http_response_context.update(
|
|
241
|
+
{
|
|
242
|
+
"method": self.request_data.get("method"),
|
|
243
|
+
"url": self.request_data.get("url"),
|
|
244
|
+
"headers": self.request_data.get("headers"),
|
|
245
|
+
}
|
|
246
|
+
)
|
|
247
|
+
|
|
248
|
+
# Add response headers if available, preserving order and case
|
|
249
|
+
try:
|
|
250
|
+
http_response_context["response_headers"] = extract_response_headers(
|
|
251
|
+
self
|
|
252
|
+
)
|
|
253
|
+
except Exception:
|
|
254
|
+
if hasattr(self, "headers"):
|
|
255
|
+
http_response_context["response_headers"] = dict(self.headers)
|
|
256
|
+
|
|
257
|
+
# Parse response body
|
|
258
|
+
if full_response_body:
|
|
259
|
+
try:
|
|
260
|
+
# For streaming responses, try to parse as text first
|
|
261
|
+
response_text = full_response_body.decode("utf-8", errors="replace")
|
|
262
|
+
|
|
263
|
+
# Check if it looks like JSON
|
|
264
|
+
headers_obj = http_response_context.get("response_headers")
|
|
265
|
+
content_type = ""
|
|
266
|
+
if headers_obj is not None and isinstance(headers_obj, dict):
|
|
267
|
+
content_type = headers_obj.get("content-type", "")
|
|
268
|
+
|
|
269
|
+
if "application/json" in content_type:
|
|
270
|
+
try:
|
|
271
|
+
http_response_context["response_body"] = json.loads(
|
|
272
|
+
response_text
|
|
273
|
+
)
|
|
274
|
+
except json.JSONDecodeError:
|
|
275
|
+
http_response_context["response_body"] = response_text
|
|
276
|
+
else:
|
|
277
|
+
# For streaming responses (like SSE), include as text
|
|
278
|
+
http_response_context["response_body"] = response_text
|
|
279
|
+
|
|
280
|
+
except UnicodeDecodeError:
|
|
281
|
+
# If decode fails, include as bytes
|
|
282
|
+
http_response_context["response_body"] = full_response_body
|
|
283
|
+
|
|
284
|
+
# Emit HTTP_RESPONSE hook
|
|
285
|
+
if self.hook_manager:
|
|
286
|
+
await self.hook_manager.emit(
|
|
287
|
+
HookEvent.HTTP_RESPONSE, http_response_context
|
|
288
|
+
)
|
|
289
|
+
|
|
290
|
+
except Exception:
|
|
291
|
+
# Silently ignore HTTP hook emission errors
|
|
292
|
+
pass
|
ccproxy/api/routes/__init__.py
CHANGED
|
@@ -1,24 +1,15 @@
|
|
|
1
1
|
"""API routes for CCProxy API Server."""
|
|
2
2
|
|
|
3
3
|
# from ccproxy.api.routes.auth import router as auth_router # Module doesn't exist
|
|
4
|
-
from ccproxy.api.routes.claude import router as claude_router
|
|
5
4
|
from ccproxy.api.routes.health import router as health_router
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
)
|
|
10
|
-
from ccproxy.api.routes.metrics import (
|
|
11
|
-
prometheus_router as metrics_router,
|
|
12
|
-
)
|
|
13
|
-
from ccproxy.api.routes.proxy import router as proxy_router
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
# proxy routes are now handled by plugin system
|
|
14
8
|
|
|
15
9
|
|
|
16
10
|
__all__ = [
|
|
17
11
|
# "auth_router", # Module doesn't exist
|
|
18
|
-
"claude_router",
|
|
19
12
|
"health_router",
|
|
20
|
-
|
|
21
|
-
"
|
|
22
|
-
"dashboard_router",
|
|
23
|
-
"proxy_router",
|
|
13
|
+
# Metrics, logs, and dashboard routes are provided by plugins now
|
|
14
|
+
# "proxy_router", # Removed - handled by plugin system
|
|
24
15
|
]
|