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,231 @@
1
+ """Configuration validation utilities."""
2
+
3
+ import re
4
+ from pathlib import Path
5
+ from typing import Any, Optional, Union
6
+ from urllib.parse import urlparse
7
+
8
+
9
+ class ConfigValidationError(Exception):
10
+ """Configuration validation error."""
11
+
12
+ pass
13
+
14
+
15
+ def validate_host(host: str) -> str:
16
+ """Validate host address.
17
+
18
+ Args:
19
+ host: Host address to validate
20
+
21
+ Returns:
22
+ The validated host address
23
+
24
+ Raises:
25
+ ConfigValidationError: If host is invalid
26
+ """
27
+ if not host:
28
+ raise ConfigValidationError("Host cannot be empty")
29
+
30
+ # Allow localhost, IP addresses, and domain names
31
+ if host in ["localhost", "0.0.0.0", "127.0.0.1"]:
32
+ return host
33
+
34
+ # Basic IP address validation
35
+ if re.match(r"^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$", host):
36
+ parts = host.split(".")
37
+ if all(0 <= int(part) <= 255 for part in parts):
38
+ return host
39
+ raise ConfigValidationError(f"Invalid IP address: {host}")
40
+
41
+ # Basic domain name validation
42
+ if re.match(r"^[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$", host):
43
+ return host
44
+
45
+ return host # Allow other formats for flexibility
46
+
47
+
48
+ def validate_port(port: int | str) -> int:
49
+ """Validate port number.
50
+
51
+ Args:
52
+ port: Port number to validate
53
+
54
+ Returns:
55
+ The validated port number
56
+
57
+ Raises:
58
+ ConfigValidationError: If port is invalid
59
+ """
60
+ if isinstance(port, str):
61
+ try:
62
+ port = int(port)
63
+ except ValueError as e:
64
+ raise ConfigValidationError(f"Port must be a valid integer: {port}") from e
65
+
66
+ if not isinstance(port, int):
67
+ raise ConfigValidationError(f"Port must be an integer: {port}")
68
+
69
+ if port < 1 or port > 65535:
70
+ raise ConfigValidationError(f"Port must be between 1 and 65535: {port}")
71
+
72
+ return port
73
+
74
+
75
+ def validate_url(url: str) -> str:
76
+ """Validate URL format.
77
+
78
+ Args:
79
+ url: URL to validate
80
+
81
+ Returns:
82
+ The validated URL
83
+
84
+ Raises:
85
+ ConfigValidationError: If URL is invalid
86
+ """
87
+ if not url:
88
+ raise ConfigValidationError("URL cannot be empty")
89
+
90
+ try:
91
+ result = urlparse(url)
92
+ if not result.scheme or not result.netloc:
93
+ raise ConfigValidationError(f"Invalid URL format: {url}")
94
+ except Exception as e:
95
+ raise ConfigValidationError(f"Invalid URL: {url}") from e
96
+
97
+ return url
98
+
99
+
100
+ def validate_path(path: str | Path) -> Path:
101
+ """Validate file path.
102
+
103
+ Args:
104
+ path: Path to validate
105
+
106
+ Returns:
107
+ The validated Path object
108
+
109
+ Raises:
110
+ ConfigValidationError: If path is invalid
111
+ """
112
+ if isinstance(path, str):
113
+ path = Path(path)
114
+
115
+ if not isinstance(path, Path):
116
+ raise ConfigValidationError(f"Path must be a string or Path object: {path}")
117
+
118
+ return path
119
+
120
+
121
+ def validate_log_level(level: str) -> str:
122
+ """Validate log level.
123
+
124
+ Args:
125
+ level: Log level to validate
126
+
127
+ Returns:
128
+ The validated log level
129
+
130
+ Raises:
131
+ ConfigValidationError: If log level is invalid
132
+ """
133
+ valid_levels = ["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]
134
+ level = level.upper()
135
+
136
+ if level not in valid_levels:
137
+ raise ConfigValidationError(
138
+ f"Invalid log level: {level}. Must be one of: {valid_levels}"
139
+ )
140
+
141
+ return level
142
+
143
+
144
+ def validate_cors_origins(origins: list[str]) -> list[str]:
145
+ """Validate CORS origins.
146
+
147
+ Args:
148
+ origins: List of origin URLs to validate
149
+
150
+ Returns:
151
+ The validated list of origins
152
+
153
+ Raises:
154
+ ConfigValidationError: If any origin is invalid
155
+ """
156
+ if not isinstance(origins, list):
157
+ raise ConfigValidationError("CORS origins must be a list")
158
+
159
+ validated_origins = []
160
+ for origin in origins:
161
+ if origin == "*":
162
+ validated_origins.append(origin)
163
+ else:
164
+ validated_origins.append(validate_url(origin))
165
+
166
+ return validated_origins
167
+
168
+
169
+ def validate_timeout(timeout: int | float) -> int | float:
170
+ """Validate timeout value.
171
+
172
+ Args:
173
+ timeout: Timeout value to validate
174
+
175
+ Returns:
176
+ The validated timeout value
177
+
178
+ Raises:
179
+ ConfigValidationError: If timeout is invalid
180
+ """
181
+ if not isinstance(timeout, int | float):
182
+ raise ConfigValidationError(f"Timeout must be a number: {timeout}")
183
+
184
+ if timeout <= 0:
185
+ raise ConfigValidationError(f"Timeout must be positive: {timeout}")
186
+
187
+ return timeout
188
+
189
+
190
+ def validate_config_dict(config: dict[str, Any]) -> dict[str, Any]:
191
+ """Validate configuration dictionary.
192
+
193
+ Args:
194
+ config: Configuration dictionary to validate
195
+
196
+ Returns:
197
+ The validated configuration dictionary
198
+
199
+ Raises:
200
+ ConfigValidationError: If configuration is invalid
201
+ """
202
+ if not isinstance(config, dict):
203
+ raise ConfigValidationError("Configuration must be a dictionary")
204
+
205
+ validated_config: dict[str, Any] = {}
206
+
207
+ # Validate specific fields if present
208
+ if "host" in config:
209
+ validated_config["host"] = validate_host(config["host"])
210
+
211
+ if "port" in config:
212
+ validated_config["port"] = validate_port(config["port"])
213
+
214
+ if "target_url" in config:
215
+ validated_config["target_url"] = validate_url(config["target_url"])
216
+
217
+ if "log_level" in config:
218
+ validated_config["log_level"] = validate_log_level(config["log_level"])
219
+
220
+ if "cors_origins" in config:
221
+ validated_config["cors_origins"] = validate_cors_origins(config["cors_origins"])
222
+
223
+ if "timeout" in config:
224
+ validated_config["timeout"] = validate_timeout(config["timeout"])
225
+
226
+ # Copy other fields without validation
227
+ for key, value in config.items():
228
+ if key not in validated_config:
229
+ validated_config[key] = value
230
+
231
+ return validated_config
@@ -0,0 +1,274 @@
1
+ """Core abstractions for the CCProxy API."""
2
+
3
+ from ccproxy.core.async_utils import (
4
+ async_cache_result,
5
+ async_timer,
6
+ gather_with_concurrency,
7
+ get_package_dir,
8
+ get_root_package_name,
9
+ patched_typing,
10
+ retry_async,
11
+ run_in_executor,
12
+ safe_await,
13
+ wait_for_condition,
14
+ )
15
+ from ccproxy.core.constants import (
16
+ ANTHROPIC_API_BASE_PATH,
17
+ AUTH_HEADER,
18
+ CHAT_COMPLETIONS_ENDPOINT,
19
+ CONFIG_FILE_NAMES,
20
+ CONTENT_TYPE_HEADER,
21
+ CONTENT_TYPE_JSON,
22
+ CONTENT_TYPE_STREAM,
23
+ CONTENT_TYPE_TEXT,
24
+ DEFAULT_DOCKER_IMAGE,
25
+ DEFAULT_DOCKER_TIMEOUT,
26
+ DEFAULT_MAX_TOKENS,
27
+ DEFAULT_MODEL,
28
+ DEFAULT_RATE_LIMIT,
29
+ DEFAULT_STREAM,
30
+ DEFAULT_TEMPERATURE,
31
+ DEFAULT_TIMEOUT,
32
+ DEFAULT_TOP_P,
33
+ EMAIL_PATTERN,
34
+ ENV_PREFIX,
35
+ ERROR_MSG_INTERNAL_ERROR,
36
+ ERROR_MSG_INVALID_REQUEST,
37
+ ERROR_MSG_INVALID_TOKEN,
38
+ ERROR_MSG_MODEL_NOT_FOUND,
39
+ ERROR_MSG_RATE_LIMIT_EXCEEDED,
40
+ JSON_EXTENSIONS,
41
+ LOG_LEVELS,
42
+ MAX_MESSAGE_LENGTH,
43
+ MAX_PROMPT_LENGTH,
44
+ MAX_TOOL_CALLS,
45
+ MESSAGES_ENDPOINT,
46
+ MODELS_ENDPOINT,
47
+ OPENAI_API_BASE_PATH,
48
+ REQUEST_ID_HEADER,
49
+ STATUS_BAD_GATEWAY,
50
+ STATUS_BAD_REQUEST,
51
+ STATUS_CREATED,
52
+ STATUS_FORBIDDEN,
53
+ STATUS_INTERNAL_ERROR,
54
+ STATUS_NOT_FOUND,
55
+ STATUS_OK,
56
+ STATUS_RATE_LIMITED,
57
+ STATUS_SERVICE_UNAVAILABLE,
58
+ STATUS_UNAUTHORIZED,
59
+ STREAM_EVENT_CONTENT_BLOCK_DELTA,
60
+ STREAM_EVENT_CONTENT_BLOCK_START,
61
+ STREAM_EVENT_CONTENT_BLOCK_STOP,
62
+ STREAM_EVENT_MESSAGE_DELTA,
63
+ STREAM_EVENT_MESSAGE_START,
64
+ STREAM_EVENT_MESSAGE_STOP,
65
+ TOML_EXTENSIONS,
66
+ URL_PATTERN,
67
+ UUID_PATTERN,
68
+ YAML_EXTENSIONS,
69
+ )
70
+ from ccproxy.core.errors import (
71
+ MiddlewareError,
72
+ ProxyAuthenticationError,
73
+ ProxyConnectionError,
74
+ ProxyError,
75
+ ProxyTimeoutError,
76
+ TransformationError,
77
+ )
78
+ from ccproxy.core.http import (
79
+ BaseProxyClient,
80
+ HTTPClient,
81
+ HTTPConnectionError,
82
+ HTTPError,
83
+ HTTPTimeoutError,
84
+ HTTPXClient,
85
+ )
86
+ from ccproxy.core.interfaces import (
87
+ APIAdapter,
88
+ MetricExporter,
89
+ StreamTransformer,
90
+ TokenStorage,
91
+ )
92
+ from ccproxy.core.interfaces import (
93
+ RequestTransformer as IRequestTransformer,
94
+ )
95
+ from ccproxy.core.interfaces import (
96
+ ResponseTransformer as IResponseTransformer,
97
+ )
98
+ from ccproxy.core.interfaces import (
99
+ TransformerProtocol as ITransformerProtocol,
100
+ )
101
+ from ccproxy.core.middleware import (
102
+ BaseMiddleware,
103
+ CompositeMiddleware,
104
+ MiddlewareChain,
105
+ MiddlewareProtocol,
106
+ NextMiddleware,
107
+ )
108
+ from ccproxy.core.proxy import (
109
+ BaseProxy,
110
+ HTTPProxy,
111
+ ProxyProtocol,
112
+ WebSocketProxy,
113
+ )
114
+ from ccproxy.core.transformers import (
115
+ BaseTransformer,
116
+ ChainedTransformer,
117
+ RequestTransformer,
118
+ ResponseTransformer,
119
+ TransformerProtocol,
120
+ )
121
+ from ccproxy.core.types import (
122
+ MiddlewareConfig,
123
+ ProxyConfig,
124
+ ProxyMethod,
125
+ ProxyRequest,
126
+ ProxyResponse,
127
+ TransformContext,
128
+ )
129
+ from ccproxy.core.types import (
130
+ ProxyProtocol as ProxyProtocolEnum,
131
+ )
132
+ from ccproxy.core.validators import (
133
+ ValidationError,
134
+ validate_choice,
135
+ validate_dict,
136
+ validate_email,
137
+ validate_list,
138
+ validate_non_empty_string,
139
+ validate_path,
140
+ validate_port,
141
+ validate_range,
142
+ validate_timeout,
143
+ validate_url,
144
+ validate_uuid,
145
+ )
146
+
147
+
148
+ __all__ = [
149
+ # Proxy abstractions
150
+ "BaseProxy",
151
+ "HTTPProxy",
152
+ "WebSocketProxy",
153
+ "ProxyProtocol",
154
+ # HTTP client abstractions
155
+ "HTTPClient",
156
+ "BaseProxyClient",
157
+ "HTTPError",
158
+ "HTTPTimeoutError",
159
+ "HTTPConnectionError",
160
+ "HTTPXClient",
161
+ # Interface abstractions
162
+ "APIAdapter",
163
+ "MetricExporter",
164
+ "IRequestTransformer",
165
+ "IResponseTransformer",
166
+ "StreamTransformer",
167
+ "TokenStorage",
168
+ "ITransformerProtocol",
169
+ # Transformer abstractions
170
+ "BaseTransformer",
171
+ "RequestTransformer",
172
+ "ResponseTransformer",
173
+ "TransformerProtocol",
174
+ "ChainedTransformer",
175
+ # Middleware abstractions
176
+ "BaseMiddleware",
177
+ "MiddlewareChain",
178
+ "MiddlewareProtocol",
179
+ "CompositeMiddleware",
180
+ "NextMiddleware",
181
+ # Error types
182
+ "ProxyError",
183
+ "TransformationError",
184
+ "MiddlewareError",
185
+ "ProxyConnectionError",
186
+ "ProxyTimeoutError",
187
+ "ProxyAuthenticationError",
188
+ "ValidationError",
189
+ # Type definitions
190
+ "ProxyRequest",
191
+ "ProxyResponse",
192
+ "TransformContext",
193
+ "ProxyMethod",
194
+ "ProxyProtocolEnum",
195
+ "ProxyConfig",
196
+ "MiddlewareConfig",
197
+ # Async utilities
198
+ "async_cache_result",
199
+ "async_timer",
200
+ "gather_with_concurrency",
201
+ "get_package_dir",
202
+ "get_root_package_name",
203
+ "patched_typing",
204
+ "retry_async",
205
+ "run_in_executor",
206
+ "safe_await",
207
+ "wait_for_condition",
208
+ # Constants
209
+ "ANTHROPIC_API_BASE_PATH",
210
+ "AUTH_HEADER",
211
+ "CHAT_COMPLETIONS_ENDPOINT",
212
+ "CONFIG_FILE_NAMES",
213
+ "CONTENT_TYPE_HEADER",
214
+ "CONTENT_TYPE_JSON",
215
+ "CONTENT_TYPE_STREAM",
216
+ "CONTENT_TYPE_TEXT",
217
+ "DEFAULT_DOCKER_IMAGE",
218
+ "DEFAULT_DOCKER_TIMEOUT",
219
+ "DEFAULT_MAX_TOKENS",
220
+ "DEFAULT_MODEL",
221
+ "DEFAULT_RATE_LIMIT",
222
+ "DEFAULT_STREAM",
223
+ "DEFAULT_TEMPERATURE",
224
+ "DEFAULT_TIMEOUT",
225
+ "DEFAULT_TOP_P",
226
+ "EMAIL_PATTERN",
227
+ "ENV_PREFIX",
228
+ "ERROR_MSG_INTERNAL_ERROR",
229
+ "ERROR_MSG_INVALID_REQUEST",
230
+ "ERROR_MSG_INVALID_TOKEN",
231
+ "ERROR_MSG_MODEL_NOT_FOUND",
232
+ "ERROR_MSG_RATE_LIMIT_EXCEEDED",
233
+ "JSON_EXTENSIONS",
234
+ "LOG_LEVELS",
235
+ "MAX_MESSAGE_LENGTH",
236
+ "MAX_PROMPT_LENGTH",
237
+ "MAX_TOOL_CALLS",
238
+ "MESSAGES_ENDPOINT",
239
+ "MODELS_ENDPOINT",
240
+ "OPENAI_API_BASE_PATH",
241
+ "REQUEST_ID_HEADER",
242
+ "STATUS_BAD_GATEWAY",
243
+ "STATUS_BAD_REQUEST",
244
+ "STATUS_CREATED",
245
+ "STATUS_FORBIDDEN",
246
+ "STATUS_INTERNAL_ERROR",
247
+ "STATUS_NOT_FOUND",
248
+ "STATUS_OK",
249
+ "STATUS_RATE_LIMITED",
250
+ "STATUS_SERVICE_UNAVAILABLE",
251
+ "STATUS_UNAUTHORIZED",
252
+ "STREAM_EVENT_CONTENT_BLOCK_DELTA",
253
+ "STREAM_EVENT_CONTENT_BLOCK_START",
254
+ "STREAM_EVENT_CONTENT_BLOCK_STOP",
255
+ "STREAM_EVENT_MESSAGE_DELTA",
256
+ "STREAM_EVENT_MESSAGE_START",
257
+ "STREAM_EVENT_MESSAGE_STOP",
258
+ "TOML_EXTENSIONS",
259
+ "URL_PATTERN",
260
+ "UUID_PATTERN",
261
+ "YAML_EXTENSIONS",
262
+ # Validators
263
+ "validate_choice",
264
+ "validate_dict",
265
+ "validate_email",
266
+ "validate_list",
267
+ "validate_non_empty_string",
268
+ "validate_path",
269
+ "validate_port",
270
+ "validate_range",
271
+ "validate_timeout",
272
+ "validate_url",
273
+ "validate_uuid",
274
+ ]