ccproxy-api 0.1.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.
Files changed (148) hide show
  1. ccproxy/__init__.py +4 -0
  2. ccproxy/__main__.py +7 -0
  3. ccproxy/_version.py +21 -0
  4. ccproxy/adapters/__init__.py +11 -0
  5. ccproxy/adapters/base.py +80 -0
  6. ccproxy/adapters/openai/__init__.py +43 -0
  7. ccproxy/adapters/openai/adapter.py +915 -0
  8. ccproxy/adapters/openai/models.py +412 -0
  9. ccproxy/adapters/openai/streaming.py +449 -0
  10. ccproxy/api/__init__.py +28 -0
  11. ccproxy/api/app.py +225 -0
  12. ccproxy/api/dependencies.py +140 -0
  13. ccproxy/api/middleware/__init__.py +11 -0
  14. ccproxy/api/middleware/auth.py +0 -0
  15. ccproxy/api/middleware/cors.py +55 -0
  16. ccproxy/api/middleware/errors.py +703 -0
  17. ccproxy/api/middleware/headers.py +51 -0
  18. ccproxy/api/middleware/logging.py +175 -0
  19. ccproxy/api/middleware/request_id.py +69 -0
  20. ccproxy/api/middleware/server_header.py +62 -0
  21. ccproxy/api/responses.py +84 -0
  22. ccproxy/api/routes/__init__.py +16 -0
  23. ccproxy/api/routes/claude.py +181 -0
  24. ccproxy/api/routes/health.py +489 -0
  25. ccproxy/api/routes/metrics.py +1033 -0
  26. ccproxy/api/routes/proxy.py +238 -0
  27. ccproxy/auth/__init__.py +75 -0
  28. ccproxy/auth/bearer.py +68 -0
  29. ccproxy/auth/credentials_adapter.py +93 -0
  30. ccproxy/auth/dependencies.py +229 -0
  31. ccproxy/auth/exceptions.py +79 -0
  32. ccproxy/auth/manager.py +102 -0
  33. ccproxy/auth/models.py +118 -0
  34. ccproxy/auth/oauth/__init__.py +26 -0
  35. ccproxy/auth/oauth/models.py +49 -0
  36. ccproxy/auth/oauth/routes.py +396 -0
  37. ccproxy/auth/oauth/storage.py +0 -0
  38. ccproxy/auth/storage/__init__.py +12 -0
  39. ccproxy/auth/storage/base.py +57 -0
  40. ccproxy/auth/storage/json_file.py +159 -0
  41. ccproxy/auth/storage/keyring.py +192 -0
  42. ccproxy/claude_sdk/__init__.py +20 -0
  43. ccproxy/claude_sdk/client.py +169 -0
  44. ccproxy/claude_sdk/converter.py +331 -0
  45. ccproxy/claude_sdk/options.py +120 -0
  46. ccproxy/cli/__init__.py +14 -0
  47. ccproxy/cli/commands/__init__.py +8 -0
  48. ccproxy/cli/commands/auth.py +553 -0
  49. ccproxy/cli/commands/config/__init__.py +14 -0
  50. ccproxy/cli/commands/config/commands.py +766 -0
  51. ccproxy/cli/commands/config/schema_commands.py +119 -0
  52. ccproxy/cli/commands/serve.py +630 -0
  53. ccproxy/cli/docker/__init__.py +34 -0
  54. ccproxy/cli/docker/adapter_factory.py +157 -0
  55. ccproxy/cli/docker/params.py +278 -0
  56. ccproxy/cli/helpers.py +144 -0
  57. ccproxy/cli/main.py +193 -0
  58. ccproxy/cli/options/__init__.py +14 -0
  59. ccproxy/cli/options/claude_options.py +216 -0
  60. ccproxy/cli/options/core_options.py +40 -0
  61. ccproxy/cli/options/security_options.py +48 -0
  62. ccproxy/cli/options/server_options.py +117 -0
  63. ccproxy/config/__init__.py +40 -0
  64. ccproxy/config/auth.py +154 -0
  65. ccproxy/config/claude.py +124 -0
  66. ccproxy/config/cors.py +79 -0
  67. ccproxy/config/discovery.py +87 -0
  68. ccproxy/config/docker_settings.py +265 -0
  69. ccproxy/config/loader.py +108 -0
  70. ccproxy/config/observability.py +158 -0
  71. ccproxy/config/pricing.py +88 -0
  72. ccproxy/config/reverse_proxy.py +31 -0
  73. ccproxy/config/scheduler.py +89 -0
  74. ccproxy/config/security.py +14 -0
  75. ccproxy/config/server.py +81 -0
  76. ccproxy/config/settings.py +534 -0
  77. ccproxy/config/validators.py +231 -0
  78. ccproxy/core/__init__.py +274 -0
  79. ccproxy/core/async_utils.py +675 -0
  80. ccproxy/core/constants.py +97 -0
  81. ccproxy/core/errors.py +256 -0
  82. ccproxy/core/http.py +328 -0
  83. ccproxy/core/http_transformers.py +428 -0
  84. ccproxy/core/interfaces.py +247 -0
  85. ccproxy/core/logging.py +189 -0
  86. ccproxy/core/middleware.py +114 -0
  87. ccproxy/core/proxy.py +143 -0
  88. ccproxy/core/system.py +38 -0
  89. ccproxy/core/transformers.py +259 -0
  90. ccproxy/core/types.py +129 -0
  91. ccproxy/core/validators.py +288 -0
  92. ccproxy/docker/__init__.py +67 -0
  93. ccproxy/docker/adapter.py +588 -0
  94. ccproxy/docker/docker_path.py +207 -0
  95. ccproxy/docker/middleware.py +103 -0
  96. ccproxy/docker/models.py +228 -0
  97. ccproxy/docker/protocol.py +192 -0
  98. ccproxy/docker/stream_process.py +264 -0
  99. ccproxy/docker/validators.py +173 -0
  100. ccproxy/models/__init__.py +123 -0
  101. ccproxy/models/errors.py +42 -0
  102. ccproxy/models/messages.py +243 -0
  103. ccproxy/models/requests.py +85 -0
  104. ccproxy/models/responses.py +227 -0
  105. ccproxy/models/types.py +102 -0
  106. ccproxy/observability/__init__.py +51 -0
  107. ccproxy/observability/access_logger.py +400 -0
  108. ccproxy/observability/context.py +447 -0
  109. ccproxy/observability/metrics.py +539 -0
  110. ccproxy/observability/pushgateway.py +366 -0
  111. ccproxy/observability/sse_events.py +303 -0
  112. ccproxy/observability/stats_printer.py +755 -0
  113. ccproxy/observability/storage/__init__.py +1 -0
  114. ccproxy/observability/storage/duckdb_simple.py +665 -0
  115. ccproxy/observability/storage/models.py +55 -0
  116. ccproxy/pricing/__init__.py +19 -0
  117. ccproxy/pricing/cache.py +212 -0
  118. ccproxy/pricing/loader.py +267 -0
  119. ccproxy/pricing/models.py +106 -0
  120. ccproxy/pricing/updater.py +309 -0
  121. ccproxy/scheduler/__init__.py +39 -0
  122. ccproxy/scheduler/core.py +335 -0
  123. ccproxy/scheduler/exceptions.py +34 -0
  124. ccproxy/scheduler/manager.py +186 -0
  125. ccproxy/scheduler/registry.py +150 -0
  126. ccproxy/scheduler/tasks.py +484 -0
  127. ccproxy/services/__init__.py +10 -0
  128. ccproxy/services/claude_sdk_service.py +614 -0
  129. ccproxy/services/credentials/__init__.py +55 -0
  130. ccproxy/services/credentials/config.py +105 -0
  131. ccproxy/services/credentials/manager.py +562 -0
  132. ccproxy/services/credentials/oauth_client.py +482 -0
  133. ccproxy/services/proxy_service.py +1536 -0
  134. ccproxy/static/.keep +0 -0
  135. ccproxy/testing/__init__.py +34 -0
  136. ccproxy/testing/config.py +148 -0
  137. ccproxy/testing/content_generation.py +197 -0
  138. ccproxy/testing/mock_responses.py +262 -0
  139. ccproxy/testing/response_handlers.py +161 -0
  140. ccproxy/testing/scenarios.py +241 -0
  141. ccproxy/utils/__init__.py +6 -0
  142. ccproxy/utils/cost_calculator.py +210 -0
  143. ccproxy/utils/streaming_metrics.py +199 -0
  144. ccproxy_api-0.1.0.dist-info/METADATA +253 -0
  145. ccproxy_api-0.1.0.dist-info/RECORD +148 -0
  146. ccproxy_api-0.1.0.dist-info/WHEEL +4 -0
  147. ccproxy_api-0.1.0.dist-info/entry_points.txt +2 -0
  148. ccproxy_api-0.1.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,89 @@
1
+ """Scheduler configuration settings."""
2
+
3
+ from pydantic import Field
4
+ from pydantic_settings import BaseSettings
5
+
6
+
7
+ class SchedulerSettings(BaseSettings):
8
+ """
9
+ Configuration settings for the unified scheduler system.
10
+
11
+ Controls global scheduler behavior and individual task configurations.
12
+ Settings can be configured via environment variables with SCHEDULER__ prefix.
13
+ """
14
+
15
+ # Global scheduler settings
16
+ enabled: bool = Field(
17
+ default=True,
18
+ description="Whether the scheduler system is enabled",
19
+ )
20
+
21
+ max_concurrent_tasks: int = Field(
22
+ default=10,
23
+ ge=1,
24
+ le=100,
25
+ description="Maximum number of tasks that can run concurrently",
26
+ )
27
+
28
+ graceful_shutdown_timeout: float = Field(
29
+ default=30.0,
30
+ ge=1.0,
31
+ le=300.0,
32
+ description="Timeout in seconds for graceful task shutdown",
33
+ )
34
+
35
+ # Pricing updater task settings
36
+ pricing_update_enabled: bool = Field(
37
+ default=True,
38
+ description="Whether pricing cache update task is enabled",
39
+ )
40
+
41
+ pricing_update_interval_hours: int = Field(
42
+ default=24,
43
+ ge=1,
44
+ le=168, # Max 1 week
45
+ description="Interval in hours between pricing cache updates",
46
+ )
47
+
48
+ pricing_force_refresh_on_startup: bool = Field(
49
+ default=False,
50
+ description="Whether to force pricing refresh immediately on startup",
51
+ )
52
+
53
+ # Observability tasks (migrated from ObservabilitySettings)
54
+ pushgateway_enabled: bool = Field(
55
+ default=False,
56
+ description="Whether pushgateway metrics pushing task is enabled",
57
+ )
58
+
59
+ pushgateway_interval_seconds: float = Field(
60
+ default=60.0,
61
+ ge=1.0,
62
+ le=3600.0, # Max 1 hour
63
+ description="Interval in seconds between pushgateway metric pushes",
64
+ )
65
+
66
+ pushgateway_max_backoff_seconds: float = Field(
67
+ default=300.0,
68
+ ge=1.0,
69
+ le=1800.0, # Max 30 minutes
70
+ description="Maximum backoff delay for failed pushgateway operations",
71
+ )
72
+
73
+ stats_printing_enabled: bool = Field(
74
+ default=False,
75
+ description="Whether stats printing task is enabled",
76
+ )
77
+
78
+ stats_printing_interval_seconds: float = Field(
79
+ default=300.0,
80
+ ge=1.0,
81
+ le=3600.0, # Max 1 hour
82
+ description="Interval in seconds between stats printing",
83
+ )
84
+
85
+ class Config:
86
+ """Pydantic configuration."""
87
+
88
+ env_prefix = "SCHEDULER__"
89
+ case_sensitive = False
@@ -0,0 +1,14 @@
1
+ """Security configuration settings."""
2
+
3
+ from typing import Literal
4
+
5
+ from pydantic import BaseModel, Field
6
+
7
+
8
+ class SecuritySettings(BaseModel):
9
+ """Security-specific configuration settings."""
10
+
11
+ auth_token: str | None = Field(
12
+ default=None,
13
+ description="Bearer token for API authentication (optional)",
14
+ )
@@ -0,0 +1,81 @@
1
+ """Server configuration settings."""
2
+
3
+ from pydantic import BaseModel, Field, field_validator
4
+
5
+
6
+ class ServerSettings(BaseModel):
7
+ """Server-specific configuration settings."""
8
+
9
+ host: str = Field(
10
+ default="127.0.0.1",
11
+ description="Server host address",
12
+ )
13
+
14
+ port: int = Field(
15
+ default=8000,
16
+ description="Server port number",
17
+ ge=1,
18
+ le=65535,
19
+ )
20
+
21
+ workers: int = Field(
22
+ default=1,
23
+ description="Number of worker processes",
24
+ ge=1,
25
+ le=32,
26
+ )
27
+
28
+ reload: bool = Field(
29
+ default=False,
30
+ description="Enable auto-reload for development",
31
+ )
32
+
33
+ log_level: str = Field(
34
+ default="INFO",
35
+ description="Logging level",
36
+ )
37
+
38
+ log_format: str = Field(
39
+ default="auto",
40
+ description="Logging output format: 'rich' for development, 'json' for production, 'auto' for automatic selection",
41
+ )
42
+
43
+ log_show_path: bool = Field(
44
+ default=False,
45
+ description="Whether to show module path in logs (automatically enabled for DEBUG level)",
46
+ )
47
+
48
+ log_show_time: bool = Field(
49
+ default=True,
50
+ description="Whether to show timestamps in logs",
51
+ )
52
+
53
+ log_console_width: int | None = Field(
54
+ default=None,
55
+ description="Optional console width override for Rich output",
56
+ )
57
+
58
+ log_file: str | None = Field(
59
+ default=None,
60
+ description="Path to JSON log file. If specified, logs will be written to this file in JSON format",
61
+ )
62
+
63
+ @field_validator("log_level")
64
+ @classmethod
65
+ def validate_log_level(cls, v: str) -> str:
66
+ """Validate and normalize log level."""
67
+ upper_v = v.upper()
68
+ valid_levels = ["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]
69
+ if upper_v not in valid_levels:
70
+ raise ValueError(f"Invalid log level: {v}. Must be one of {valid_levels}")
71
+ return upper_v
72
+
73
+ @field_validator("log_format")
74
+ @classmethod
75
+ def validate_log_format(cls, v: str) -> str:
76
+ """Validate and normalize log format."""
77
+ lower_v = v.lower()
78
+ valid_formats = ["auto", "rich", "json", "plain"]
79
+ if lower_v not in valid_formats:
80
+ raise ValueError(f"Invalid log format: {v}. Must be one of {valid_formats}")
81
+ return lower_v