Underground-Digital/Workflow-Engine
0
1from typing import Annotated, Literal, Optional2 3from pydantic import (4 AliasChoices,5 Field,6 HttpUrl,7 NegativeInt,8 NonNegativeInt,9 PositiveFloat,10 PositiveInt,11 computed_field,12)13from pydantic_settings import BaseSettings14 15from configs.feature.hosted_service import HostedServiceConfig16 17 18class SecurityConfig(BaseSettings):19 """20 Security-related configurations for the application21 """22 23 SECRET_KEY: str = Field(24 description="Secret key for secure session cookie signing."25 "Make sure you are changing this key for your deployment with a strong key."26 "Generate a strong key using `openssl rand -base64 42` or set via the `SECRET_KEY` environment variable.",27 default="",28 )29 30 RESET_PASSWORD_TOKEN_EXPIRY_MINUTES: PositiveInt = Field(31 description="Duration in minutes for which a password reset token remains valid",32 default=5,33 )34 35 LOGIN_DISABLED: bool = Field(36 description="Whether to disable login checks",37 default=False,38 )39 40 ADMIN_API_KEY_ENABLE: bool = Field(41 description="Whether to enable admin api key for authentication",42 default=False,43 )44 45 ADMIN_API_KEY: Optional[str] = Field(46 description="admin api key for authentication",47 default=None,48 )49 50 51class AppExecutionConfig(BaseSettings):52 """53 Configuration parameters for application execution54 """55 56 APP_MAX_EXECUTION_TIME: PositiveInt = Field(57 description="Maximum allowed execution time for the application in seconds",58 default=1200,59 )60 APP_MAX_ACTIVE_REQUESTS: NonNegativeInt = Field(61 description="Maximum number of concurrent active requests per app (0 for unlimited)",62 default=0,63 )64 65 66class CodeExecutionSandboxConfig(BaseSettings):67 """68 Configuration for the code execution sandbox environment69 """70 71 CODE_EXECUTION_ENDPOINT: HttpUrl = Field(72 description="URL endpoint for the code execution service",73 default="http://sandbox:8194",74 )75 76 CODE_EXECUTION_API_KEY: str = Field(77 description="API key for accessing the code execution service",78 default="dify-sandbox",79 )80 81 CODE_EXECUTION_CONNECT_TIMEOUT: Optional[float] = Field(82 description="Connection timeout in seconds for code execution requests",83 default=10.0,84 )85 86 CODE_EXECUTION_READ_TIMEOUT: Optional[float] = Field(87 description="Read timeout in seconds for code execution requests",88 default=60.0,89 )90 91 CODE_EXECUTION_WRITE_TIMEOUT: Optional[float] = Field(92 description="Write timeout in seconds for code execution request",93 default=10.0,94 )95 96 CODE_MAX_NUMBER: PositiveInt = Field(97 description="Maximum allowed numeric value in code execution",98 default=9223372036854775807,99 )100 101 CODE_MIN_NUMBER: NegativeInt = Field(102 description="Minimum allowed numeric value in code execution",103 default=-9223372036854775807,104 )105 106 CODE_MAX_DEPTH: PositiveInt = Field(107 description="Maximum allowed depth for nested structures in code execution",108 default=5,109 )110 111 CODE_MAX_PRECISION: PositiveInt = Field(112 description="mMaximum number of decimal places for floating-point numbers in code execution",113 default=20,114 )115 116 CODE_MAX_STRING_LENGTH: PositiveInt = Field(117 description="Maximum allowed length for strings in code execution",118 default=80000,119 )120 121 CODE_MAX_STRING_ARRAY_LENGTH: PositiveInt = Field(122 description="Maximum allowed length for string arrays in code execution",123 default=30,124 )125 126 CODE_MAX_OBJECT_ARRAY_LENGTH: PositiveInt = Field(127 description="Maximum allowed length for object arrays in code execution",128 default=30,129 )130 131 CODE_MAX_NUMBER_ARRAY_LENGTH: PositiveInt = Field(132 description="Maximum allowed length for numeric arrays in code execution",133 default=1000,134 )135 136 137class EndpointConfig(BaseSettings):138 """139 Configuration for various application endpoints and URLs140 """141 142 CONSOLE_API_URL: str = Field(143 description="Base URL for the console API,"144 "used for login authentication callback or notion integration callbacks",145 default="",146 )147 148 CONSOLE_WEB_URL: str = Field(149 description="Base URL for the console web interface," "used for frontend references and CORS configuration",150 default="",151 )152 153 SERVICE_API_URL: str = Field(154 description="Base URL for the service API, displayed to users for API access",155 default="",156 )157 158 APP_WEB_URL: str = Field(159 description="Base URL for the web application, used for frontend references",160 default="",161 )162 163 164class FileAccessConfig(BaseSettings):165 """166 Configuration for file access and handling167 """168 169 FILES_URL: str = Field(170 description="Base URL for file preview or download,"171 " used for frontend display and multi-model inputs"172 "Url is signed and has expiration time.",173 validation_alias=AliasChoices("FILES_URL", "CONSOLE_API_URL"),174 alias_priority=1,175 default="",176 )177 178 FILES_ACCESS_TIMEOUT: int = Field(179 description="Expiration time in seconds for file access URLs",180 default=300,181 )182 183 184class FileUploadConfig(BaseSettings):185 """186 Configuration for file upload limitations187 """188 189 UPLOAD_FILE_SIZE_LIMIT: NonNegativeInt = Field(190 description="Maximum allowed file size for uploads in megabytes",191 default=15,192 )193 194 UPLOAD_FILE_BATCH_LIMIT: NonNegativeInt = Field(195 description="Maximum number of files allowed in a single upload batch",196 default=5,197 )198 199 UPLOAD_IMAGE_FILE_SIZE_LIMIT: NonNegativeInt = Field(200 description="Maximum allowed image file size for uploads in megabytes",201 default=10,202 )203 204 UPLOAD_VIDEO_FILE_SIZE_LIMIT: NonNegativeInt = Field(205 description="video file size limit in Megabytes for uploading files",206 default=100,207 )208 209 UPLOAD_AUDIO_FILE_SIZE_LIMIT: NonNegativeInt = Field(210 description="audio file size limit in Megabytes for uploading files",211 default=50,212 )213 214 BATCH_UPLOAD_LIMIT: NonNegativeInt = Field(215 description="Maximum number of files allowed in a batch upload operation",216 default=20,217 )218 219 WORKFLOW_FILE_UPLOAD_LIMIT: PositiveInt = Field(220 description="Maximum number of files allowed in a workflow upload operation",221 default=10,222 )223 224 225class HttpConfig(BaseSettings):226 """227 HTTP-related configurations for the application228 """229 230 API_COMPRESSION_ENABLED: bool = Field(231 description="Enable or disable gzip compression for HTTP responses",232 default=False,233 )234 235 inner_CONSOLE_CORS_ALLOW_ORIGINS: str = Field(236 description="Comma-separated list of allowed origins for CORS in the console",237 validation_alias=AliasChoices("CONSOLE_CORS_ALLOW_ORIGINS", "CONSOLE_WEB_URL"),238 default="",239 )240 241 @computed_field242 @property243 def CONSOLE_CORS_ALLOW_ORIGINS(self) -> list[str]:244 return self.inner_CONSOLE_CORS_ALLOW_ORIGINS.split(",")245 246 inner_WEB_API_CORS_ALLOW_ORIGINS: str = Field(247 description="",248 validation_alias=AliasChoices("WEB_API_CORS_ALLOW_ORIGINS"),249 default="*",250 )251 252 @computed_field253 @property254 def WEB_API_CORS_ALLOW_ORIGINS(self) -> list[str]:255 return self.inner_WEB_API_CORS_ALLOW_ORIGINS.split(",")256 257 HTTP_REQUEST_MAX_CONNECT_TIMEOUT: Annotated[258 PositiveInt, Field(ge=10, description="Maximum connection timeout in seconds for HTTP requests")259 ] = 10260 261 HTTP_REQUEST_MAX_READ_TIMEOUT: Annotated[262 PositiveInt, Field(ge=60, description="Maximum read timeout in seconds for HTTP requests")263 ] = 60264 265 HTTP_REQUEST_MAX_WRITE_TIMEOUT: Annotated[266 PositiveInt, Field(ge=10, description="Maximum write timeout in seconds for HTTP requests")267 ] = 20268 269 HTTP_REQUEST_NODE_MAX_BINARY_SIZE: PositiveInt = Field(270 description="Maximum allowed size in bytes for binary data in HTTP requests",271 default=10 * 1024 * 1024,272 )273 274 HTTP_REQUEST_NODE_MAX_TEXT_SIZE: PositiveInt = Field(275 description="Maximum allowed size in bytes for text data in HTTP requests",276 default=1 * 1024 * 1024,277 )278 279 SSRF_PROXY_HTTP_URL: Optional[str] = Field(280 description="Proxy URL for HTTP requests to prevent Server-Side Request Forgery (SSRF)",281 default=None,282 )283 284 SSRF_PROXY_HTTPS_URL: Optional[str] = Field(285 description="Proxy URL for HTTPS requests to prevent Server-Side Request Forgery (SSRF)",286 default=None,287 )288 289 SSRF_DEFAULT_TIME_OUT: PositiveFloat = Field(290 description="The default timeout period used for network requests (SSRF)",291 default=5,292 )293 294 SSRF_DEFAULT_CONNECT_TIME_OUT: PositiveFloat = Field(295 description="The default connect timeout period used for network requests (SSRF)",296 default=5,297 )298 299 SSRF_DEFAULT_READ_TIME_OUT: PositiveFloat = Field(300 description="The default read timeout period used for network requests (SSRF)",301 default=5,302 )303 304 SSRF_DEFAULT_WRITE_TIME_OUT: PositiveFloat = Field(305 description="The default write timeout period used for network requests (SSRF)",306 default=5,307 )308 309 RESPECT_XFORWARD_HEADERS_ENABLED: bool = Field(310 description="Enable or disable the X-Forwarded-For Proxy Fix middleware from Werkzeug"311 " to respect X-* headers to redirect clients",312 default=False,313 )314 315 316class InnerAPIConfig(BaseSettings):317 """318 Configuration for internal API functionality319 """320 321 INNER_API: bool = Field(322 description="Enable or disable the internal API",323 default=False,324 )325 326 INNER_API_KEY: Optional[str] = Field(327 description="API key for accessing the internal API",328 default=None,329 )330 331 332class LoggingConfig(BaseSettings):333 """334 Configuration for application logging335 """336 337 LOG_LEVEL: str = Field(338 description="Logging level, default to INFO. Set to ERROR for production environments.",339 default="INFO",340 )341 342 LOG_FILE: Optional[str] = Field(343 description="File path for log output.",344 default=None,345 )346 347 LOG_FILE_MAX_SIZE: PositiveInt = Field(348 description="Maximum file size for file rotation retention, the unit is megabytes (MB)",349 default=20,350 )351 352 LOG_FILE_BACKUP_COUNT: PositiveInt = Field(353 description="Maximum file backup count file rotation retention",354 default=5,355 )356 357 LOG_FORMAT: str = Field(358 description="Format string for log messages",359 default="%(asctime)s.%(msecs)03d %(levelname)s [%(threadName)s] [%(filename)s:%(lineno)d] - %(message)s",360 )361 362 LOG_DATEFORMAT: Optional[str] = Field(363 description="Date format string for log timestamps",364 default=None,365 )366 367 LOG_TZ: Optional[str] = Field(368 description="Timezone for log timestamps (e.g., 'America/New_York')",369 default=None,370 )371 372 373class ModelLoadBalanceConfig(BaseSettings):374 """375 Configuration for model load balancing376 """377 378 MODEL_LB_ENABLED: bool = Field(379 description="Enable or disable load balancing for models",380 default=False,381 )382 383 384class BillingConfig(BaseSettings):385 """386 Configuration for platform billing features387 """388 389 BILLING_ENABLED: bool = Field(390 description="Enable or disable billing functionality",391 default=False,392 )393 394 395class UpdateConfig(BaseSettings):396 """397 Configuration for application update checks398 """399 400 CHECK_UPDATE_URL: str = Field(401 description="URL to check for application updates",402 default="https://updates.dify.ai",403 )404 405 406class WorkflowConfig(BaseSettings):407 """408 Configuration for workflow execution409 """410 411 WORKFLOW_MAX_EXECUTION_STEPS: PositiveInt = Field(412 description="Maximum number of steps allowed in a single workflow execution",413 default=500,414 )415 416 WORKFLOW_MAX_EXECUTION_TIME: PositiveInt = Field(417 description="Maximum execution time in seconds for a single workflow",418 default=1200,419 )420 421 WORKFLOW_CALL_MAX_DEPTH: PositiveInt = Field(422 description="Maximum allowed depth for nested workflow calls",423 default=5,424 )425 426 MAX_VARIABLE_SIZE: PositiveInt = Field(427 description="Maximum size in bytes for a single variable in workflows. Default to 200 KB.",428 default=200 * 1024,429 )430 431 432class AuthConfig(BaseSettings):433 """434 Configuration for authentication and OAuth435 """436 437 OAUTH_REDIRECT_PATH: str = Field(438 description="Redirect path for OAuth authentication callbacks",439 default="/console/api/oauth/authorize",440 )441 442 GITHUB_CLIENT_ID: Optional[str] = Field(443 description="GitHub OAuth client ID",444 default=None,445 )446 447 GITHUB_CLIENT_SECRET: Optional[str] = Field(448 description="GitHub OAuth client secret",449 default=None,450 )451 452 GOOGLE_CLIENT_ID: Optional[str] = Field(453 description="Google OAuth client ID",454 default=None,455 )456 457 GOOGLE_CLIENT_SECRET: Optional[str] = Field(458 description="Google OAuth client secret",459 default=None,460 )461 462 ACCESS_TOKEN_EXPIRE_MINUTES: PositiveInt = Field(463 description="Expiration time for access tokens in minutes",464 default=60,465 )466 467 468class ModerationConfig(BaseSettings):469 """470 Configuration for content moderation471 """472 473 MODERATION_BUFFER_SIZE: PositiveInt = Field(474 description="Size of the buffer for content moderation processing",475 default=300,476 )477 478 479class ToolConfig(BaseSettings):480 """481 Configuration for tool management482 """483 484 TOOL_ICON_CACHE_MAX_AGE: PositiveInt = Field(485 description="Maximum age in seconds for caching tool icons",486 default=3600,487 )488 489 490class MailConfig(BaseSettings):491 """492 Configuration for email services493 """494 495 MAIL_TYPE: Optional[str] = Field(496 description="Email service provider type ('smtp' or 'resend'), default to None.",497 default=None,498 )499 500 MAIL_DEFAULT_SEND_FROM: Optional[str] = Field(501 description="Default email address to use as the sender",502 default=None,503 )504 505 RESEND_API_KEY: Optional[str] = Field(506 description="API key for Resend email service",507 default=None,508 )509 510 RESEND_API_URL: Optional[str] = Field(511 description="API URL for Resend email service",512 default=None,513 )514 515 SMTP_SERVER: Optional[str] = Field(516 description="SMTP server hostname",517 default=None,518 )519 520 SMTP_PORT: Optional[int] = Field(521 description="SMTP server port number",522 default=465,523 )524 525 SMTP_USERNAME: Optional[str] = Field(526 description="Username for SMTP authentication",527 default=None,528 )529 530 SMTP_PASSWORD: Optional[str] = Field(531 description="Password for SMTP authentication",532 default=None,533 )534 535 SMTP_USE_TLS: bool = Field(536 description="Enable TLS encryption for SMTP connections",537 default=False,538 )539 540 SMTP_OPPORTUNISTIC_TLS: bool = Field(541 description="Enable opportunistic TLS for SMTP connections",542 default=False,543 )544 545 EMAIL_SEND_IP_LIMIT_PER_MINUTE: PositiveInt = Field(546 description="Maximum number of emails allowed to be sent from the same IP address in a minute",547 default=50,548 )549 550 551class RagEtlConfig(BaseSettings):552 """553 Configuration for RAG ETL processes554 """555 556 # TODO: This config is not only for rag etl, it is also for file upload, we should move it to file upload config557 ETL_TYPE: str = Field(558 description="RAG ETL type ('dify' or 'Unstructured'), default to 'dify'",559 default="dify",560 )561 562 KEYWORD_DATA_SOURCE_TYPE: str = Field(563 description="Data source type for keyword extraction"564 " ('database' or other supported types), default to 'database'",565 default="database",566 )567 568 UNSTRUCTURED_API_URL: Optional[str] = Field(569 description="API URL for Unstructured.io service",570 default=None,571 )572 573 UNSTRUCTURED_API_KEY: Optional[str] = Field(574 description="API key for Unstructured.io service",575 default=None,576 )577 578 579class DataSetConfig(BaseSettings):580 """581 Configuration for dataset management582 """583 584 PLAN_SANDBOX_CLEAN_DAY_SETTING: PositiveInt = Field(585 description="Interval in days for dataset cleanup operations - plan: sandbox",586 default=30,587 )588 589 PLAN_PRO_CLEAN_DAY_SETTING: PositiveInt = Field(590 description="Interval in days for dataset cleanup operations - plan: pro and team",591 default=7,592 )593 594 DATASET_OPERATOR_ENABLED: bool = Field(595 description="Enable or disable dataset operator functionality",596 default=False,597 )598 599 TIDB_SERVERLESS_NUMBER: PositiveInt = Field(600 description="number of tidb serverless cluster",601 default=500,602 )603 604 605class WorkspaceConfig(BaseSettings):606 """607 Configuration for workspace management608 """609 610 INVITE_EXPIRY_HOURS: PositiveInt = Field(611 description="Expiration time in hours for workspace invitation links",612 default=72,613 )614 615 616class IndexingConfig(BaseSettings):617 """618 Configuration for indexing operations619 """620 621 INDEXING_MAX_SEGMENTATION_TOKENS_LENGTH: PositiveInt = Field(622 description="Maximum token length for text segmentation during indexing",623 default=1000,624 )625 626 627class ImageFormatConfig(BaseSettings):628 MULTIMODAL_SEND_IMAGE_FORMAT: Literal["base64", "url"] = Field(629 description="Format for sending images in multimodal contexts ('base64' or 'url'), default is base64",630 default="base64",631 )632 633 634class CeleryBeatConfig(BaseSettings):635 CELERY_BEAT_SCHEDULER_TIME: int = Field(636 description="Interval in days for Celery Beat scheduler execution, default to 1 day",637 default=1,638 )639 640 641class PositionConfig(BaseSettings):642 POSITION_PROVIDER_PINS: str = Field(643 description="Comma-separated list of pinned model providers",644 default="",645 )646 647 POSITION_PROVIDER_INCLUDES: str = Field(648 description="Comma-separated list of included model providers",649 default="",650 )651 652 POSITION_PROVIDER_EXCLUDES: str = Field(653 description="Comma-separated list of excluded model providers",654 default="",655 )656 657 POSITION_TOOL_PINS: str = Field(658 description="Comma-separated list of pinned tools",659 default="",660 )661 662 POSITION_TOOL_INCLUDES: str = Field(663 description="Comma-separated list of included tools",664 default="",665 )666 667 POSITION_TOOL_EXCLUDES: str = Field(668 description="Comma-separated list of excluded tools",669 default="",670 )671 672 @computed_field673 def POSITION_PROVIDER_PINS_LIST(self) -> list[str]:674 return [item.strip() for item in self.POSITION_PROVIDER_PINS.split(",") if item.strip() != ""]675 676 @computed_field677 def POSITION_PROVIDER_INCLUDES_SET(self) -> set[str]:678 return {item.strip() for item in self.POSITION_PROVIDER_INCLUDES.split(",") if item.strip() != ""}679 680 @computed_field681 def POSITION_PROVIDER_EXCLUDES_SET(self) -> set[str]:682 return {item.strip() for item in self.POSITION_PROVIDER_EXCLUDES.split(",") if item.strip() != ""}683 684 @computed_field685 def POSITION_TOOL_PINS_LIST(self) -> list[str]:686 return [item.strip() for item in self.POSITION_TOOL_PINS.split(",") if item.strip() != ""]687 688 @computed_field689 def POSITION_TOOL_INCLUDES_SET(self) -> set[str]:690 return {item.strip() for item in self.POSITION_TOOL_INCLUDES.split(",") if item.strip() != ""}691 692 @computed_field693 def POSITION_TOOL_EXCLUDES_SET(self) -> set[str]:694 return {item.strip() for item in self.POSITION_TOOL_EXCLUDES.split(",") if item.strip() != ""}695 696 697class LoginConfig(BaseSettings):698 ENABLE_EMAIL_CODE_LOGIN: bool = Field(699 description="whether to enable email code login",700 default=False,701 )702 ENABLE_EMAIL_PASSWORD_LOGIN: bool = Field(703 description="whether to enable email password login",704 default=True,705 )706 ENABLE_SOCIAL_OAUTH_LOGIN: bool = Field(707 description="whether to enable github/google oauth login",708 default=False,709 )710 EMAIL_CODE_LOGIN_TOKEN_EXPIRY_MINUTES: PositiveInt = Field(711 description="expiry time in minutes for email code login token",712 default=5,713 )714 ALLOW_REGISTER: bool = Field(715 description="whether to enable register",716 default=False,717 )718 ALLOW_CREATE_WORKSPACE: bool = Field(719 description="whether to enable create workspace",720 default=False,721 )722 723 724class FeatureConfig(725 # place the configs in alphabet order726 AppExecutionConfig,727 AuthConfig, # Changed from OAuthConfig to AuthConfig728 BillingConfig,729 CodeExecutionSandboxConfig,730 DataSetConfig,731 EndpointConfig,732 FileAccessConfig,733 FileUploadConfig,734 HttpConfig,735 ImageFormatConfig,736 InnerAPIConfig,737 IndexingConfig,738 LoggingConfig,739 MailConfig,740 ModelLoadBalanceConfig,741 ModerationConfig,742 PositionConfig,743 RagEtlConfig,744 SecurityConfig,745 ToolConfig,746 UpdateConfig,747 WorkflowConfig,748 WorkspaceConfig,749 LoginConfig,750 # hosted services config751 HostedServiceConfig,752 CeleryBeatConfig,753):754 pass755 